Ego-Lite Selector Formats: Complete Guide to Element Resolution

Ego-Lite supports more than 14 distinct selector formats—including CSS, text, accessibility roles, XPath, and attribute-based patterns—parsed through the parseLocator function in package/ego-browser/src/element-resolver.ts.

The citrolabs/ego-lite library provides a flexible element resolution system for browser automation that goes beyond standard CSS queries. Understanding the available selector formats is essential for writing stable, self-documenting element queries that align with how modern web applications are built.

How the Element Resolver Works

At the heart of ego-lite's element discovery lies the parseLocator routine defined in package/ego-browser/src/element-resolver.ts. This function inspects selector strings for specific prefixes and patterns, mapping each to a distinct locator kind that determines the search strategy. The parser also extracts ordinal modifiers before processing the underlying selector format.

Supported Selector Formats

Ego-lite recognizes a rich syntax for targeting elements, ranging from standard CSS to accessibility-centric selectors.

CSS and Internal Queries

  • css: – Standard CSS selectors (e.g., css:button.primary). Implemented in parseLocator (lines 36‑38).
  • internal:scope: and internal:filter: – Direct internal query strings used by the test harness (lines 31‑33).
  • Plain strings with modifiers – When combined with nth= or last modifiers, plain strings are treated as raw CSS selectors (lines 116‑118).

Text-Based Locators

  • text: – Finds visible text nodes. Supports exact matching via the exact: sub-syntax (lines 44‑50).
  • text= – Shorthand for partial text matching where exact: false (lines 52‑58).
  • label: – Matches <label> elements or ARIA-labelled controls by their text content (lines 60‑66).

Accessibility and Semantic Selectors

  • role: – Targets elements by ARIA role with optional name matching, such as role:button[name="Close"]. The name= parameter accepts plain strings, JSON strings, or TextMatcher objects (lines 101‑108).

Attribute-Based Selectors

  • href: – Matches <a> elements whose href resolves to the supplied path or full URL (lines 40‑42).
  • placeholder: – Targets <input> and <textarea> elements by placeholder attribute (lines 68‑74).
  • alt: – Selects <img> and <input> elements with matching alt attributes (lines 76‑82).
  • title: – Finds any element carrying a matching title attribute (lines 84‑90).
  • testid: – Selects elements by data-testid attribute, commonly used in testing workflows (lines 92‑99).

XPath Expressions

  • xpath= – Evaluates XPath expressions against the document. Important: XPath selectors must be prefixed with internal:nth=<n>; or internal:last; to function (lines 112‑115).

Optional Prefix Normalization

The resolver automatically strips the optional loc= prefix before processing, allowing syntax like loc=css:button to function identically to css:button. This normalization occurs early in parseLocator (lines 33‑35).

Ordinal Modifiers for Index Selection

Ego-lite supports positional selection through modifiers that can be prepended to any selector:

  • internal:nth=<n>; – Selects the n‑th match using zero-based indexing.
  • internal:last; – Selects the final matching element.

These modifiers are extracted and removed before the underlying selector format is processed, as implemented in lines 17‑27 of the resolver.

Fallback Resolution Behavior

When a selector lacks a recognized prefix, ego-lite falls back to treating the string as a standard CSS selector. According to the implementation in resolveElementCenter (lines 26‑33), the resolver passes the raw selector to queryAllExpression in package/ego-browser/src/locator-query.js via a runtime evaluation call. This fallback ensures that any valid CSS selector works even without explicit prefix notation.

Practical Code Examples

// CSS selector
await ego.js('css:button.submit');

// Text search (partial match)
await ego.js('text:Login');

// Exact text match using the exact: sub-syntax
await ego.js('text:exact:"Sign in"');

// Accessibility role with name matching
await ego.js('role:button[name="Close"]');

// href selector matching path or full URL
await ego.js('href:/settings/profile');

// Test-ID selector for data-testid attributes
await ego.js('testid:nav-item-5');

// XPath with required nth modifier
await ego.js('internal:nth=0;xpath=//div[@class="card"]');

// Internal scope query for harness use
await ego.js('internal:scope:div > span');

// Using the optional loc= prefix
await ego.js('loc=placeholder:Search...');

Summary

  • Ego-lite's parseLocator function in package/ego-browser/src/element-resolver.ts recognizes 14+ distinct selector formats.
  • Supported prefixes include css:, text:, text=, label:, placeholder:, alt:, title:, testid:, href:, role:, and xpath= (with modifiers).
  • Ordinal selection uses internal:nth=<n>; or internal:last; prepended to any selector.
  • The optional loc= prefix is stripped before processing, providing syntax flexibility.
  • Unrecognized selectors fall back to standard CSS evaluation via queryAllExpression in locator-query.js.

Frequently Asked Questions

What is the difference between text: and text= selectors in ego-lite?

The text: prefix performs text matching that respects the exact: sub-syntax for precise control, while text= is a shorthand that forces partial matching with exact: false. Both locator kinds map to the text resolver, but text= provides a more concise syntax when you do not need exact string equality.

Can I use XPath selectors without the nth or last modifier in ego-lite?

No. According to the source code in parseLocator (lines 112‑115), XPath expressions must be combined with either internal:nth=<n>; or internal:last; modifiers to be recognized by the resolver. Without these ordinal markers, the selector may be misinterpreted or fail to resolve.

How does ego-lite handle unsupported selector formats?

When parseLocator encounters a string without a recognized prefix, it falls back to treating the entire selector as a standard CSS query. The resolver passes the raw string to queryAllExpression in package/ego-browser/src/locator-query.js, allowing standard CSS selectors to work even when not explicitly prefixed with css:.

What file contains the core parsing logic for ego-lite selectors?

The core parsing logic resides in package/ego-browser/src/element-resolver.ts, specifically within the parseLocator function (lines 17‑118). This file defines how each prefix is recognized and mapped to its respective locator kind, while the fallback CSS evaluation is handled by queryAllExpression in package/ego-browser/src/locator-query.js.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →