# `Statifier.Parser.Markup`
[🔗](https://github.com/riddler/statifier-ex/blob/v2.0.0/lib/statifier/parser/markup.ex#L1)

A total, left-to-right scan of an XML source binary that produces the
positions Saxy does not.

Saxy 1.6.1 passes handlers no position data of any kind and has no option
to enable it (`deps/saxy/lib/saxy/handler.ex`), so positions are produced
by this independent scan and zipped against the SAX event stream by index
in `Statifier.Parser.Handler` - the Nth start-tag record this scanner
finds is the Nth `:start_element` Saxy emits.

The scan only ever answers "is this a markup construct, and where does it
start and end". It classifies each `<` by the bytes that follow it -
`<!--` comment (skipped to `-->`), `<![CDATA[` (skipped to `]]>`),
`<!DOCTYPE` (skipped to `>`, honoring an internal `[...]` subset), `<?` PI
or the XML declaration (skipped to `?>`), `</` an end tag, anything else a
start tag - and never interprets content, expands entities, or validates.
A self-closing `<b/>` emits **two** records, a `:start` and an `:end` with
identical spans, so the record stream stays 1:1 with Saxy's element events
by construction.

It is a **total function**: it never raises, on any binary, including
malformed or truncated XML. On a malformed document, Saxy's own error is
what surfaces to `Statifier.Parser.parse/1`; this scanner's only
obligation on such input is to return *a* list without crashing, since a
well-formed document is Saxy's job to reject, not this scanner's.

# `attribute`

```elixir
@type attribute() :: %{
  name: binary(),
  location: Statifier.Parser.Location.t(),
  value_location: Statifier.Parser.Location.t()
}
```

# `t`

```elixir
@type t() :: %Statifier.Parser.Markup{
  attributes: [attribute()],
  kind: :start | :end,
  location: Statifier.Parser.Location.t(),
  name: binary()
}
```

# `scan`

```elixir
@spec scan(source :: binary()) :: [t()]
```

Scans `source` into an ordered list of start/end tag records.

Total over any binary - see the moduledoc. Comments, CDATA sections,
DOCTYPE declarations, and processing instructions (including the XML
declaration) are skipped without producing a record; only start and end
tags do.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
