# Selectors

## Listen to the Stream

Wasot implements a composite pattern. A document consists of [elements](./ast.md).
An `Element` is either a `Text` or a `Block`, which has other elements as children.
To represent the tree on disc or in transit, it is serialized depth first into [events](./architecture.md).
See the `events.rs` for the three events: Block started event, Block finished event, Text event.

The selectors need to observe and select such an event stream. For the implementation details, see the [StackFrameCollector](./stack_frame_collector.md) which tracks selector state.

## Inspired by CSS

Selectors are heavily inspired by CSS Selectors.
In fact, XML and Wasot are equivalent, see [the data model](./wasot_and_xml.md).
CSS Selectors work with XHTML, HTML+XML, Wasot selectors work with wasot.
When multiple selectors match, [specificity](./specificity.md) determines which one wins.
So which types of selectors do we have to implement?

## Types of selectors

### Basic Selectors

- `*` Universal: Selects all elements.
- `type-name`: Type: Selects all block of this type.
- `.class` Class: Selects all blocks with this class, note: classes are not implemented yet, so we can skip this one for now.
- `#id` ID: Selects the block with this id. IDs are normally unique, but duplicate IDs can happen.

A note on classes: Classes are just positional arguments, which start with a dot.


### Argument selectors

Wasot meta-lines can have positional arguments and keyword arguments.
These are equivalent to attributes in HTML and the CSS selectors.
Thus, when you read argument selectors, think attribute selectors in CSS.

- `[argument]` Selects all blocks, that have this argument, either positional or keyword.
- `[!argument]` Selects all  blocks witch don't have this argument (either positional or keyword)
- `[key="value"]` Selects all keyword arguments with the key  `key` and the value `value`
- `[~argument]` (has not), `[key~="value"]` (has key, not value), `[key^="value"]` (starts with),
- `[key$="value"]` (ends with), `[key*="value"]` (contains), a regex matcher, a callback matcher.

### Child Selectors

Inspired by CSS pseudo-class selectors.
Note: children are elements, a element is either a block or a text.
If you call any child operator on a text, it never matches as it has no children.

- `:first-child`, the first child, either text or block
- `:first-block`, first block, not text
- `:first-text`, first text, not
- `:last-child`, last child, either block or text
- `:last-block`, last child in the children  list of a block
- `:last-text`, last text
- `:nth-child(n)`, the child-element at this position
- `nth-block(n)`, the nth block (texts are ignored when counting)
- `nth-text(n)`, same with text, blocks are ignored when counting.
- `:not(selector)`, negate any other selector.

### Combinators (And-selectors) 

Semantics like CSS.

- `<space>` Descendant: e.g. `paragraph quote` selects all blocks of type `quote` witch are a descendant of `paragraph`.
- `>` Child: `paragraph > quote` Selects all blocks of type `quote` that are a direct child of `paragraph`
- `+`: Adjacent Sibling: like `paragraph + idea` selects the first block of type `idea` that is immediately preceded by a block of type `paragraph`
- `~`: General Sibling: Like `paragraph ~ idea`, which selects all `idea`-blocks, which are siblings of and come after (not only directly) an `idea`-block. A more general version of `+`

### Or-selectors

These are like the Grouping selector in CSS, where you can separate selector-expressions with a comma.
In our case, if one matches, the complete expression is a match.

- `,`, e.g. `paragraph, idea:first-child > note` and so on. Just separated by comma





