pq module (v0.3.x)
pq provides query builders and reusable DOM matching helpers.
import { pq } from "@page-proxy/pp";
pq.selector(definition)
Builds reusable selector logic.
definition parameters:
nameMetadata label exposed onselector.definition.baseSelector(optional) Optional CSS prefilter. Trimmed; blank values fall back to"*".matches(element)Required predicate that decides whether an element matches.postMap(element)(optional) Optional transform for matched elements returned fromquery,queryAll,waitUntilMatch, andonElementMatches.
const premiumCards = pq.selector({
name: "premium-cards",
baseSelector: ".card",
matches: (el) => pq.innerTextMatches(el, /premium/i),
});
const first = premiumCards.query();
const all = premiumCards.queryAll();
const observer = premiumCards.onElementMatches((el) => {
console.log("New premium card:", el);
});
const nextMatch = await premiumCards.waitUntilMatch();
Available methods:
definition
Exposes the same object passed into pq.selector(definition).
Useful for reading selector metadata/configuration at runtime.
console.log(premiumCards.definition.name); // "premium-cards"
console.log(premiumCards.definition.baseSelector); // ".card"
matches(el)
Tests one element against your selector rules.
- checks
baseSelectorfirst (unless it resolves to"*") - runs your
matches(el)predicate - returns
trueorfalse
var candidate = document.querySelector(".card");
if (candidate && premiumCards.matches(candidate)) {
console.log("Candidate is a match");
}
query()
Returns the first current match from the document, or null when none match.
var firstMatch = premiumCards.query();
console.log("First match:", firstMatch);
queryAll()
Returns all current matches as an array.
var allMatches = premiumCards.queryAll();
console.log("Total matches:", allMatches.length);
waitUntilMatch(targetNode?, observerOptions?)
Returns a Promise that resolves when a matching element exists.
- first checks current DOM for an immediate match
- otherwise observes created elements until a match appears
- default options:
targetNode:document.body || document.documentElementobserverOptions:{ childList: true, subtree: true }
const match = await premiumCards.waitUntilMatch();
console.log("Resolved match:", match);
onElementMatches(func, targetNode, observerOptions)
Starts observing DOM insertions and runs func for matches.
- returns an
ElementCreatedObserver(built onMutationObserver) - runs once on the current subtree immediately
- continues for future added nodes
- default options:
targetNode:document.body || document.documentElementobserverOptions:{ childList: true, subtree: true }
var observer = premiumCards.onElementMatches(
function (value) {
console.log("Observed match:", value);
},
document.body,
{ childList: true, subtree: true },
);
observer.disconnect();
Match helpers
Supported helpers:
tagMatches: exact tag equality aftertrim().toLowerCase()selectorMatches: nativeElement.matcheswrapperinnerTextMatches: uses only direct text nodes (not descendant text); regex matchers removegbefore testingbboxMatches: compares left/top/right/bottom in page coordinates; default tolerance75propMatches/propContains/propExists: read special keys (tag,id,class,name,innerText,bbox) plus regular attributes
pq.tagMatches(el, "button");
pq.selectorMatches(el, ".cta.primary");
pq.innerTextMatches(el, "Upgrade");
pq.bboxMatches(el, { x: 100, y: 220, width: 280, height: 48 }, 25);
pq.propContains(el, "class", "featured");
Parent traversal
traverseParents(el, matcher, options?) walks from el.parentElement upward and returns the first match (or null).
const sectionId = pq.traverseParents(button, (parent) => parent.matches("section"), {
postMap: (parent) => parent.id,
});