# `Coelho.Schema.NodeSpec`
[🔗](https://github.com/nseaSeb/coelho/blob/main/lib/coelho/schema/node_spec.ex#L1)

Specification of a single node type.

Fields:

  * `:name` — the node name, an atom
  * `:content` — parsed content expression, `nil` for a leaf node
  * `:content_source` — the original expression, kept for JSON export
  * `:group` — group names this node belongs to
  * `:marks` — `:all`, or the list of mark names allowed on its children
  * `:attrs` — map of attribute name to `Coelho.Schema.Attr`
  * `:inline` — whether the node is inline rather than block
  * `:text` — set only on the built-in `text` node
  * `:void` — rendered as a self-closing tag, without children
  * `:class` — a CSS class merged into the rendered element *and* exported
    to the browser, so the editor shows the class the public page will use
  * `:editor_attrs` — extra DOM attributes for the editor only, exported
    with the schema and never emitted server side
  * `:render` — how the node is turned into HTML, see `Coelho.Render`
  * `:render_inline` — how it is turned into HTML where only inline
    elements are legal. A block is unwrapped to its children by default,
    which is right for a paragraph and useless for a node whose block-ness
    lives inside a render function — see `Coelho.Render.to_inline_html/3`
  * `:to_text` — what the node contributes to the plain text extraction,
    when that is not simply its children
  * `:editor_text` — the attribute whose value the editor draws as the
    node's visible text. A void node has no content, so a chip standing for
    a variable, a mention or a date would otherwise draw empty; naming an
    attribute here is what puts words in it, on the browser's side only —
    the server's `:render` decides what the page carries
  * `:parse` — HTML this node is imported from, see `Coelho.HTML`
  * `:attr_keys` — the attribute names as the strings a document is written
    in, derived from `:attrs` when the schema is built. Validation asks
    this of every node instance, and building it there would be a set per
    node of every document.

# `render`

```elixir
@type render() ::
  nil
  | {String.t(),
     [{String.t(), String.t()}] | (map() -&gt; [{String.t(), String.t()}])}
  | (map(), iodata() -&gt; iodata())
```

# `t`

```elixir
@type t() :: %Coelho.Schema.NodeSpec{
  attr_keys: MapSet.t(String.t()) | nil,
  attrs: %{optional(atom()) =&gt; Coelho.Schema.Attr.t()},
  class: String.t() | nil,
  content: Coelho.Schema.ContentExpression.ast() | nil,
  content_source: String.t() | nil,
  editor_attrs: %{optional(String.t()) =&gt; String.t()},
  editor_text: atom() | nil,
  group: [atom()],
  inline: boolean(),
  marks: :all | [atom()],
  name: atom(),
  parse: [Coelho.HTML.rule()],
  render: render(),
  render_inline: render(),
  text: boolean(),
  to_text: String.t() | (map() -&gt; iodata()) | nil,
  void: boolean()
}
```

---

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