# `Kotoba.Document`
[🔗](https://github.com/hattoriai/kotoba/blob/v0.5.0/lib/kotoba/document.ex#L1)

A rich text document in memory.

The stored form of a document is an envelope around the serialized
editor state of Lexical:

    %{"kotoba" => 1, "lexical" => "0.51", "root" => root_node_json}

`parse/2` reads the envelope into a tree of node structs (see
`Kotoba.Node`) and checks each node. `to_json/1` writes the envelope
again. For the nodes in the registry, `to_json/1` writes the same JSON
that `parse/2` read, when that JSON has all the keys that Lexical writes.
A node of a type that is not in the registry becomes a
`Kotoba.Nodes.Unknown` node, and `to_json/1` writes its JSON with no
change.

# `t`

```elixir
@type t() :: %Kotoba.Document{
  lexical: String.t(),
  root: Kotoba.Nodes.Root.t(),
  version: pos_integer()
}
```

# `attachments`

```elixir
@spec attachments(t()) :: [Kotoba.Nodes.Attachment.t()]
```

Returns the attachment nodes of the document, in document order.

# `empty?`

```elixir
@spec empty?(t()) :: boolean()
```

Returns `true` when the document has no text other than white space and
no node other than element, text and line break nodes.

# `map`

```elixir
@spec map(t(), (Kotoba.Node.t() -&gt; Kotoba.Node.t())) :: t()
```

Returns a document with `fun` applied to each node, depth first.

`fun` gets the parent before its children, and Kotoba then maps the
children of the node that `fun` returns. `fun` gets the root node too,
and must return a `Kotoba.Nodes.Root` for it.

# `mentions`

```elixir
@spec mentions(t()) :: [Kotoba.Nodes.Mention.t()]
```

Returns the mention nodes of the document, in document order.

# `parse`

```elixir
@spec parse(map() | String.t(), keyword()) :: {:ok, t()} | {:error, [String.t()]}
```

Reads a document from its envelope, as a map or as a JSON string.

Returns `{:ok, document}`, or `{:error, messages}` with one message for
each problem.

## Options

  * `:nodes` - a list of extra `Kotoba.Node` modules for the registry. See
    `Kotoba.Nodes.registry/1`.

## Examples

    iex> {:ok, doc} =
    ...>   Kotoba.Document.parse(%{
    ...>     "kotoba" => 1,
    ...>     "lexical" => "0.51",
    ...>     "root" => %{"type" => "root", "children" => []}
    ...>   })
    iex> Kotoba.Document.empty?(doc)
    true

# `reduce`

```elixir
@spec reduce(t(), acc, (Kotoba.Node.t(), acc -&gt; acc)) :: acc when acc: term()
```

Reduces the nodes of the document, depth first, the parent before its
children.

## Examples

    iex> {:ok, doc} = Kotoba.Document.parse(%{"kotoba" => 1, "lexical" => "0.51", "root" => %{"type" => "root"}})
    iex> Kotoba.Document.reduce(doc, 0, fn _node, count -> count + 1 end)
    1

# `text`

```elixir
@spec text(t()) :: String.t()
```

Returns the plain text of the document, with the `:default` render
policy.

Delegates to `Kotoba.Renderer.to_text/2`, so the two always agree: a
root-level decorator with no text (for example a horizontal rule) gives
no blank line, and a node that `Kotoba.Sanitizer` refuses (for example
a node nested where it is not valid) gives no text either, the same as
an unknown node.

# `to_json`

```elixir
@spec to_json(t()) :: map()
```

Returns the envelope of the document as a map.

# `walk`

```elixir
@spec walk(t(), (Kotoba.Node.t() -&gt; term())) :: :ok
```

Calls `fun` on each node of the document, depth first, the parent before
its children. Returns `:ok`.

---

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