# How the `loc=` Locator Syntax Works in ego‑lite

> Understand how ego-lite's loc= locator syntax parses XPath, CSS, text, attributes, and ARIA roles. Learn to write efficient selectors for your tests.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: how-to-guide
- Published: 2026-08-27

---

**The `loc=` prefix in ego‑lite activates a structured locator parser in `src/locator‑query.ts` that routes selectors to specialized handlers for XPath, CSS, text matching, attributes, and ARIA roles, falling back to plain CSS selectors when no specific prefix matches.**

ego‑lite provides agents with a unified string syntax to locate page elements. When a selector begins with `loc=`, the library treats the remainder as a structured locator and parses it in `src/locator‑query.ts` to generate efficient DOM‑query expressions. This architecture enables expressive, high‑level selectors—such as targeting by ARIA role or link href—while maintaining compatibility with standard CSS.

## Core Parsing Flow in locator‑query.ts

All `loc=` processing originates in **`src/locator‑query.ts`**, specifically within the `queryAllExpression` function. The parser implements a cascading dispatch mechanism that examines the selector string and constructs the appropriate JavaScript expression for browser evaluation.

### Normalization and Strategy Dispatch

The parser first strips the `loc=` prefix to reveal the underlying strategy:

```typescript
const normalized = raw.startsWith("loc=") ? raw.slice(4) : raw;

```

After normalization, the code checks for specific locator prefixes. If none match, the raw string is treated as a plain CSS selector and passed to `querySelectorAll`.

### Supported Locator Types

The implementation recognizes eight distinct locator categories according to the source logic:

- **XPath** – Strings starting with `xpath=` trigger `document.evaluate` for complex DOM traversal.
- **CSS** – The `css:` prefix delegates directly to `querySelectorAll`.
- **Href** – The `href:` prefix targets `<a>` elements matching a specific path or full URL.
- **Text** – The `text:` prefix (or legacy `text=`) matches visible text content with optional exact‑match modifiers.
- **Attributes** – Prefixes `label:`, `placeholder:`, `alt:`, `title:`, and `testid:` filter elements by case‑insensitive attribute values.
- **ARIA Role** – The `role:` prefix accepts syntax like `role:button[name=…]` to select elements by explicit or implicit ARIA role, optionally filtering by accessible name.

## The queryAllExpression Builder

The `queryAllExpression` function constructs the actual JavaScript snippet executed in the browser context. Each branch returns a specialized expression:

```typescript
if (raw.startsWith("xpath=")) { /* build XPath expression */ }
if (normalized.startsWith("css:")) { /* standard querySelectorAll */ }
if (normalized.startsWith("href:")) { /* anchor href matcher */ }
if (normalized.startsWith("text:")) { /* text content matcher */ }
// ... role parsing via parseRoleLocator()
return querySelectorAllExpression(rootExpression, raw);

```

This approach keeps the browser‑side execution lightweight while allowing the host to compose complex queries.

## Integration with the Resolution Pipeline

The locator system spans three key files in the repository:

- **`src/locator‑query.ts`** – Parses `loc=` strings and builds query expressions.
- **`src/element‑resolver.ts`** – Consumes `queryAllExpression` output and resolves selectors to concrete element references.
- **[`src/driver/locator.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/locator.ts)** – Exposes public helpers like `click` and `type` that forward selector strings through the resolver.

This architecture ensures that all public driver methods accept the same unified string format.

## Practical Code Examples

The following patterns demonstrate how agents use `loc=` in production code:

Target a button via CSS:

```javascript
await click('loc=css:#submit-button');

```

Select a link by exact URL path:

```javascript
await click('loc=href:/dashboard');

```

Type into a field using placeholder text:

```javascript
await type('loc=placeholder:"Search items"', 'laptop');

```

Click a checkbox by label with exact matching:

```javascript
await click('loc=label:exact:"Accept terms"');

```

Interact via ARIA role and accessible name:

```javascript
await click('loc=role:button[name:/Submit/i]');

```

Fallback to raw CSS when omitting `loc=`:

```javascript
await click('#logout');  // Treated as plain CSS selector

```

Combine CSS with text filtering:

```javascript
await click('loc=css:.menu-item:has-text("Settings")');

```

## Summary

- **Explicit syntax** – The `loc=` prefix signals structured parsing in `src/locator‑query.ts`, distinguishing high‑level locators from arbitrary JavaScript.
- **Multi‑strategy support** – Supports XPath, CSS, href, text, attributes (label, placeholder, alt, title, testid), and ARIA role selection.
- **Graceful fallback** – Unrecognized strings default to standard CSS selection via `querySelectorAll`.
- **Consistent API** – All driver methods (`click`, `type`, `waitFor`) leverage the same resolution pipeline through `element‑resolver.ts`.

## Frequently Asked Questions

### What happens if I omit the `loc=` prefix in ego‑lite?

When the `loc=` prefix is absent, the selector bypasses the structured parser in `src/locator‑query.ts` and is treated as a raw CSS selector passed directly to `querySelectorAll`. This provides backward compatibility for simple element targeting.

### How does ego‑lite handle ARIA role selectors with accessible names?

The parser extracts the role and optional name from strings like `loc=role:button[name=/Submit/i]`. It uses the `parseRoleLocator()` helper to generate an expression that matches elements by their computed ARIA role and filters by the provided accessible name pattern.

### Can I use XPath expressions with the `loc=` syntax?

Yes. Prefix your selector with `loc=xpath=` to trigger the XPath branch in `queryAllExpression`, which builds a `document.evaluate` call for complex DOM queries that CSS cannot express.

### Where is the `loc=` parsing logic implemented?

All parsing logic resides in **`src/locator‑query.ts`** within the `queryAllExpression` function. This module constructs JavaScript expressions that `src/element‑resolver.ts` executes in the browser context to resolve elements.