# Ego-Lite Selector Formats: Complete Guide to Element Resolution

> Explore ego-lite's versatile selector formats including CSS, text, roles, XPath, and attributes for robust element resolution. Discover the full guide to element selection.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: deep-dive
- Published: 2026-08-26

---

**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`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/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

```typescript
// 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`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/locator-query.js).