The behaviour of a node in a Kotoba.Document.
A node is a struct that mirrors one Lexical node in the serialized editor
state. use Kotoba.Node makes the struct and the functions of the
behaviour from a list of fields. The node module then gives the render
callbacks:
defmodule MyApp.Nodes.Pointer do
use Kotoba.Node, type: "pointer", kind: :inline
import Phoenix.Component, only: [sigil_H: 2]
field :ref, :string, required: true
field :excerpt, :string, omit_nil: true
field :tone, :string, key: "toneName", default: "plain", in: ~w(plain loud)
@impl Kotoba.Node
def render_html(node, _opts) do
assigns = %{node: node}
~H"""
<span class="pointer" data-ref={@node.ref} data-tone={@node.tone}>{@node.excerpt}</span>
"""
end
@impl Kotoba.Node
def render_text(node, _opts), do: "[#{node.excerpt}]"
endIn the JSON, the tone field has the key "toneName". When excerpt is
nil, to_json/1 does not write the "excerpt" key.
Options
:type- the Lexical node type, as in the"type"key of the JSON. Required.:kind-:block,:inlineor:decorator. Required.:element- whentrue, the node is a Lexical element node. It gets achildrenlist and the element fieldsdirection,formatandindent. The default isfalse.
Every node gets a version field (default 1) and an extra map. The
extra map keeps the JSON keys that the node does not declare, so
to_json/1 writes them back with no change.
Fields
field/3 declares one attribute. The types are :string, :integer,
:boolean, :map and {:array, type}. The options are:
:key- the JSON key. The default is the field name as a string. Use it for the camelCase keys of Lexical, for examplefield :list_type, :string, key: "listType".:required- whentrue, the value must not benil.:default- the struct default.from_json/1also uses it when the JSON has no value for the key.:in- a list of the permitted values.:omit_nil- whentrue,to_json/1does not write the key when the value isnil. Whenfalse(the default), it writesnull.
The field names :children, :extra, :type and :version are
reserved. The JSON keys "type", "children" and "version" are
reserved too, and two fields cannot have the same JSON key. A module that
breaks one of these rules does not compile.
Generated functions
use Kotoba.Node defines type/0, kind/0, element?/0, fields/0,
validate/1, from_json/1, to_json/1 and a default
render_markdown/2. A node can override validate/1 to add its own
checks, and call super/1 for the field checks. It can override
render_markdown/2; the default calls render_text/2.
from_json/1 reads the attributes of one node. It does not read the
children: Kotoba.Document.parse/2 reads them with the node registry.
Rendering
Kotoba.Renderer calls render_html/2, render_text/2 and
render_markdown/2 for each node, after Kotoba.Sanitizer accepts the
node. A node module must give render_html/2 and render_text/2.
render_html/2 returns safe HTML: {:safe, iodata} from
Phoenix.HTML, or a ~H template. A plain string is escaped. An element
node renders its children with Kotoba.Renderer.html_children/2,
Kotoba.Renderer.text_children/2 and
Kotoba.Renderer.markdown_children/2. The opts are described in
Kotoba.Renderer.
Summary
Callbacks
Returns true when the node is a Lexical element node with children.
Returns the fields of the node, in the order of declaration.
Builds the node from its JSON map. The children are not read.
Returns the kind of the node.
Renders the node as safe HTML, or as a ~H template.
Renders the node as Markdown.
Renders the node as plain text.
Returns the JSON map of the node, with the JSON of its children.
Returns the Lexical node type.
Checks the node. Returns :ok or {:error, messages}.
Functions
Returns the JSON map of any node, Kotoba.Nodes.Unknown included.
Declares a field of the node. See Kotoba.Node.Field for the options.
Builds a node struct of module from a JSON map.
Returns true when module is a module that uses Kotoba.Node.
Returns the JSON map of a node struct, with the JSON of its children.
Checks every field of a node struct against its declaration.
Types
@type kind() :: :block | :inline | :decorator
The kind of a node.
@type t() :: struct()
A node struct.
Callbacks
@callback element?() :: boolean()
Returns true when the node is a Lexical element node with children.
@callback fields() :: [Kotoba.Node.Field.t()]
Returns the fields of the node, in the order of declaration.
Builds the node from its JSON map. The children are not read.
@callback kind() :: kind()
Returns the kind of the node.
@callback render_html(node :: t(), opts :: keyword()) :: Phoenix.HTML.safe() | Phoenix.LiveView.Rendered.t()
Renders the node as safe HTML, or as a ~H template.
Renders the node as Markdown.
Renders the node as plain text.
Returns the JSON map of the node, with the JSON of its children.
@callback type() :: String.t()
Returns the Lexical node type.
Checks the node. Returns :ok or {:error, messages}.
Functions
Returns the JSON map of any node, Kotoba.Nodes.Unknown included.
Declares a field of the node. See Kotoba.Node.Field for the options.
Builds a node struct of module from a JSON map.
The generated from_json/1 calls this function. A declared key that is
not in the map gets the field default. The keys that the node does not
declare go into extra. For an element node, the "children" key is not
read and the struct gets no children.
Returns true when module is a module that uses Kotoba.Node.
Returns the JSON map of a node struct, with the JSON of its children.
The generated to_json/1 calls this function.
Checks every field of a node struct against its declaration.
The generated validate/1 calls this function.