Quillon.Transform (Quillon v0.1.0)

Copy Markdown View Source

Operations for manipulating rich text content within Quillon documents.

Provides apply_mark/4, remove_mark/4, and toggle_mark/4 for paragraph-level mark manipulation, plus normalization and position utilities.

Example

# Apply bold to characters 0-5
para = {:paragraph, %{}, [{:text, %{text: "Hello world", marks: []}, []}]}
result = Quillon.Transform.apply_mark(para, 0, 5, :bold)
# => {:paragraph, %{}, [
#      {:text, %{text: "Hello", marks: [:bold]}, []},
#      {:text, %{text: " world", marks: []}, []}
#    ]}

Summary

Types

A block node (paragraph or heading)

A mark - either a simple atom or attributed tuple

Types

block()

@type block() :: {:paragraph | :heading, map(), list()}

A block node (paragraph or heading)

mark()

@type mark() :: atom() | {atom(), map()}

A mark - either a simple atom or attributed tuple

Functions

apply_mark(arg, start_offset, end_offset, mark)

@spec apply_mark(block(), non_neg_integer(), non_neg_integer(), mark()) :: block()

Apply a mark to text within a block at the given offset range.

Automatically splits text nodes at boundaries and normalizes after.

Examples

iex> para = {:paragraph, %{}, [{:text, %{text: "Hello", marks: []}, []}]}
iex> Quillon.Transform.apply_mark(para, 0, 5, :bold)
{:paragraph, %{}, [{:text, %{text: "Hello", marks: [:bold]}, []}]}

iex> para = {:paragraph, %{}, [{:text, %{text: "Hello world", marks: []}, []}]}
iex> Quillon.Transform.apply_mark(para, 0, 5, :bold)
{:paragraph, %{}, [
  {:text, %{text: "Hello", marks: [:bold]}, []},
  {:text, %{text: " world", marks: []}, []}
]}

iex> para = {:paragraph, %{}, [{:text, %{text: "link", marks: []}, []}]}
iex> Quillon.Transform.apply_mark(para, 0, 4, {:link, %{href: "/page"}})
{:paragraph, %{}, [{:text, %{text: "link", marks: [{:link, %{href: "/page"}}]}, []}]}

find_node_at_offset(children, offset)

See Quillon.Transform.Split.find_node_at_offset/2.

marks_equal?(marks1, marks2)

See Quillon.Transform.MarkOrder.marks_equal?/2.

nodes_fully_in_range(children, start_offset, end_offset)

See Quillon.Transform.Position.nodes_fully_in_range/3.

nodes_in_range(children, start_offset, end_offset)

See Quillon.Transform.Position.nodes_in_range/3.

normalize(arg)

@spec normalize(block()) :: block()

Normalize a block's children (merge adjacent, remove empty).

Examples

iex> para = {:paragraph, %{}, [
...>   {:text, %{text: "Hello", marks: [:bold]}, []},
...>   {:text, %{text: " world", marks: [:bold]}, []}
...> ]}
iex> Quillon.Transform.normalize(para)
{:paragraph, %{}, [{:text, %{text: "Hello world", marks: [:bold]}, []}]}

normalize_children(children)

See Quillon.Transform.Normalize.normalize/1.

offset_to_position(children, offset)

See Quillon.Transform.Position.offset_to_position/2.

position_to_offset(children, position)

See Quillon.Transform.Position.position_to_offset/2.

range_has_mark?(arg, start_offset, end_offset, mark_type)

@spec range_has_mark?(block(), non_neg_integer(), non_neg_integer(), atom()) ::
  boolean()

Check if all text in the given range has a specific mark.

Examples

iex> para = {:paragraph, %{}, [{:text, %{text: "Hello", marks: [:bold]}, []}]}
iex> Quillon.Transform.range_has_mark?(para, 0, 5, :bold)
true

iex> para = {:paragraph, %{}, [{:text, %{text: "Hello", marks: []}, []}]}
iex> Quillon.Transform.range_has_mark?(para, 0, 5, :bold)
false

iex> para = {:paragraph, %{}, [
...>   {:text, %{text: "Hello", marks: [:bold]}, []},
...>   {:text, %{text: " world", marks: []}, []}
...> ]}
iex> Quillon.Transform.range_has_mark?(para, 0, 11, :bold)
false

remove_mark(arg, start_offset, end_offset, mark_type)

@spec remove_mark(block(), non_neg_integer(), non_neg_integer(), atom()) :: block()

Remove a mark from text within a block at the given offset range.

Automatically splits text nodes at boundaries and normalizes after.

Examples

iex> para = {:paragraph, %{}, [{:text, %{text: "Hello", marks: [:bold]}, []}]}
iex> Quillon.Transform.remove_mark(para, 0, 5, :bold)
{:paragraph, %{}, [{:text, %{text: "Hello", marks: []}, []}]}

iex> para = {:paragraph, %{}, [{:text, %{text: "Hello", marks: [:bold, :italic]}, []}]}
iex> Quillon.Transform.remove_mark(para, 0, 5, :bold)
{:paragraph, %{}, [{:text, %{text: "Hello", marks: [:italic]}, []}]}

sort_marks(marks)

See Quillon.Transform.MarkOrder.sort_marks/1.

split_at_offset(children, offset)

See Quillon.Transform.Split.split_at_offset/2.

split_range(children, start_offset, end_offset)

See Quillon.Transform.Split.split_range/3.

toggle_mark(block, start_offset, end_offset, mark)

@spec toggle_mark(block(), non_neg_integer(), non_neg_integer(), mark()) :: block()

Toggle a mark within a block at the given offset range.

If all text in range has the mark, removes it. Otherwise, adds it.

Examples

iex> para = {:paragraph, %{}, [{:text, %{text: "Hello", marks: []}, []}]}
iex> Quillon.Transform.toggle_mark(para, 0, 5, :bold)
{:paragraph, %{}, [{:text, %{text: "Hello", marks: [:bold]}, []}]}

iex> para = {:paragraph, %{}, [{:text, %{text: "Hello", marks: [:bold]}, []}]}
iex> Quillon.Transform.toggle_mark(para, 0, 5, :bold)
{:paragraph, %{}, [{:text, %{text: "Hello", marks: []}, []}]}

total_length(children)

See Quillon.Transform.Position.total_length/1.