Position mapping between flat offsets and node paths.
Converts between:
- Flat offset: single integer counting characters from start
- Node position:
{node_index, offset_within_node}tuple
Summary
Types
List of inline children (text nodes)
Position as {node_index, offset_within_node}
A text node tuple
Functions
Get the text length of a single text node.
Get nodes fully contained within a given offset range.
Get all text nodes that overlap with a given offset range.
Convert a flat offset to a node position {node_index, offset_within_node}.
Convert a node position to a flat offset.
Calculate the total text length of a list of text nodes.
Types
@type children() :: [text_node()]
List of inline children (text nodes)
@type position() :: {non_neg_integer(), non_neg_integer()}
Position as {node_index, offset_within_node}
A text node tuple
Functions
@spec node_length(text_node()) :: non_neg_integer()
Get the text length of a single text node.
Examples
iex> Quillon.Transform.Position.node_length({:text, %{text: "Hello", marks: []}, []})
5
iex> Quillon.Transform.Position.node_length({:text, %{text: "", marks: []}, []})
0
@spec nodes_fully_in_range(children(), non_neg_integer(), non_neg_integer()) :: children()
Get nodes fully contained within a given offset range.
A node is fully contained if its entire text falls within [start_offset, end_offset].
Examples
iex> children = [
...> {:text, %{text: "Hello", marks: []}, []},
...> {:text, %{text: " ", marks: []}, []},
...> {:text, %{text: "world", marks: []}, []}
...> ]
iex> Quillon.Transform.Position.nodes_fully_in_range(children, 5, 6)
[{:text, %{text: " ", marks: []}, []}]
iex> children = [
...> {:text, %{text: "Hello", marks: []}, []},
...> {:text, %{text: " ", marks: []}, []},
...> {:text, %{text: "world", marks: []}, []}
...> ]
iex> Quillon.Transform.Position.nodes_fully_in_range(children, 0, 11)
[
{:text, %{text: "Hello", marks: []}, []},
{:text, %{text: " ", marks: []}, []},
{:text, %{text: "world", marks: []}, []}
]
@spec nodes_in_range(children(), non_neg_integer(), non_neg_integer()) :: children()
Get all text nodes that overlap with a given offset range.
A node overlaps if any part of it falls within [start_offset, end_offset).
Examples
iex> children = [
...> {:text, %{text: "Hello", marks: []}, []},
...> {:text, %{text: " ", marks: []}, []},
...> {:text, %{text: "world", marks: [:bold]}, []}
...> ]
iex> Quillon.Transform.Position.nodes_in_range(children, 5, 6)
[{:text, %{text: " ", marks: []}, []}]
iex> children = [
...> {:text, %{text: "Hello", marks: []}, []},
...> {:text, %{text: " world", marks: []}, []}
...> ]
iex> Quillon.Transform.Position.nodes_in_range(children, 3, 8)
[
{:text, %{text: "Hello", marks: []}, []},
{:text, %{text: " world", marks: []}, []}
]
@spec offset_to_position(children(), non_neg_integer()) :: position()
Convert a flat offset to a node position {node_index, offset_within_node}.
If offset is at a node boundary, returns the end of the previous node. If offset is beyond content, returns the end of the last node.
Examples
iex> children = [
...> {:text, %{text: "Hello", marks: []}, []},
...> {:text, %{text: " world", marks: []}, []}
...> ]
iex> Quillon.Transform.Position.offset_to_position(children, 0)
{0, 0}
iex> children = [
...> {:text, %{text: "Hello", marks: []}, []},
...> {:text, %{text: " world", marks: []}, []}
...> ]
iex> Quillon.Transform.Position.offset_to_position(children, 3)
{0, 3}
iex> children = [
...> {:text, %{text: "Hello", marks: []}, []},
...> {:text, %{text: " world", marks: []}, []}
...> ]
iex> Quillon.Transform.Position.offset_to_position(children, 7)
{1, 2}
@spec position_to_offset(children(), position()) :: non_neg_integer()
Convert a node position to a flat offset.
Examples
iex> children = [
...> {:text, %{text: "Hello", marks: []}, []},
...> {:text, %{text: " world", marks: []}, []}
...> ]
iex> Quillon.Transform.Position.position_to_offset(children, {0, 3})
3
iex> children = [
...> {:text, %{text: "Hello", marks: []}, []},
...> {:text, %{text: " world", marks: []}, []}
...> ]
iex> Quillon.Transform.Position.position_to_offset(children, {1, 2})
7
@spec total_length(children()) :: non_neg_integer()
Calculate the total text length of a list of text nodes.
Examples
iex> children = [
...> {:text, %{text: "Hello", marks: []}, []},
...> {:text, %{text: " world", marks: []}, []}
...> ]
iex> Quillon.Transform.Position.total_length(children)
11
iex> Quillon.Transform.Position.total_length([])
0