Normalization operations for text nodes.
Normalizes content by:
- Removing empty text nodes
- Merging adjacent text nodes with identical marks
Summary
Functions
Check if a text node is empty.
Merge adjacent text nodes with identical marks.
Check if two text nodes can be merged (same marks).
Normalize a list of text nodes.
Normalize a paragraph or heading node.
Remove empty text nodes from a list.
Types
Any node these predicates may be handed.
Children lists normally hold text nodes, but a consumer may introduce a custom node type - a scanned line carrying a bounding box, say - and normalization has to pass it through rather than raise on it.
@type children() :: [any_node()]
List of inline children
A text node tuple
Functions
Check if a text node is empty.
Only a text node can be empty. Any other node — including a custom node type a consumer has introduced — is reported as non-empty so that normalization leaves it alone rather than discarding it.
Examples
iex> Quillon.Transform.Normalize.empty_text?({:text, %{text: "", marks: []}, []})
true
iex> Quillon.Transform.Normalize.empty_text?({:text, %{text: "Hi", marks: []}, []})
false
iex> Quillon.Transform.Normalize.empty_text?({:line, %{page: 2}, [Quillon.text("Hi")]})
false
Merge adjacent text nodes with identical marks.
Uses loose equality (compares marks only, ignores text content).
Examples
iex> children = [
...> {:text, %{text: "A", marks: []}, []},
...> {:text, %{text: "B", marks: []}, []},
...> {:text, %{text: "C", marks: []}, []}
...> ]
iex> Quillon.Transform.Normalize.merge_adjacent(children)
[{:text, %{text: "ABC", marks: []}, []}]
iex> children = [
...> {:text, %{text: "Hello", marks: [:bold]}, []},
...> {:text, %{text: " world", marks: []}, []}
...> ]
iex> Quillon.Transform.Normalize.merge_adjacent(children)
[
{:text, %{text: "Hello", marks: [:bold]}, []},
{:text, %{text: " world", marks: []}, []}
]
Check if two text nodes can be merged (same marks).
Examples
iex> n1 = {:text, %{text: "Hello", marks: [:bold, :italic]}, []}
iex> n2 = {:text, %{text: " world", marks: [:italic, :bold]}, []}
iex> Quillon.Transform.Normalize.mergeable?(n1, n2)
true
iex> n1 = {:text, %{text: "Hello", marks: [:bold]}, []}
iex> n2 = {:text, %{text: " world", marks: []}, []}
iex> Quillon.Transform.Normalize.mergeable?(n1, n2)
false
iex> n1 = {:text, %{text: "Hello", marks: []}, []}
iex> n2 = {:line, %{page: 2}, [Quillon.text(" world")]}
iex> Quillon.Transform.Normalize.mergeable?(n1, n2)
false
Normalize a list of text nodes.
Removes empty text nodes and merges adjacent nodes with identical marks.
Examples
iex> children = [
...> {:text, %{text: "Hello", marks: [:bold]}, []},
...> {:text, %{text: " world", marks: [:bold]}, []},
...> {:text, %{text: "", marks: []}, []}
...> ]
iex> Quillon.Transform.Normalize.normalize(children)
[{:text, %{text: "Hello world", marks: [:bold]}, []}]
iex> Quillon.Transform.Normalize.normalize([])
[]
Normalize a paragraph or heading node.
Accepts only :paragraph and :heading, and raises otherwise. Those are the
block types whose children are inline text; a container node holds blocks, and
merging those is a different operation this function does not perform.
Examples
iex> para = {:paragraph, %{}, [
...> {:text, %{text: "Hello", marks: [:bold]}, []},
...> {:text, %{text: " world", marks: [:bold]}, []}
...> ]}
iex> Quillon.Transform.Normalize.normalize_block(para)
{:paragraph, %{}, [{:text, %{text: "Hello world", marks: [:bold]}, []}]}
Remove empty text nodes from a list.
Examples
iex> children = [
...> {:text, %{text: "Hello", marks: []}, []},
...> {:text, %{text: "", marks: []}, []},
...> {:text, %{text: "world", marks: []}, []}
...> ]
iex> Quillon.Transform.Normalize.remove_empty(children)
[
{:text, %{text: "Hello", marks: []}, []},
{:text, %{text: "world", marks: []}, []}
]