PhiaUi.Components.Collab.VersionHelpers (phia_ui v0.1.17)

Copy Markdown View Source

Helper functions for document version history and diffing.

Provides utilities for computing structural diffs between TipTap JSON documents, generating human-readable change summaries, formatting version timestamps, grouping versions by day, and calculating word count deltas.

Summary

Functions

Compute a structural diff between two TipTap JSON documents.

Generate a human-readable summary of changes from a diff result.

Format a version timestamp for display.

Group versions by day for timeline display.

Calculate word count delta between two versions as a display string.

Functions

diff_documents(old_doc, new_doc)

@spec diff_documents(map(), map()) :: [map()]

Compute a structural diff between two TipTap JSON documents.

Compares the top-level "content" arrays node-by-node and returns a list of change maps describing additions, removals, and modifications.

Return shape

[%{type: :added | :removed | :modified, path: [integer()], ...}]

Examples

iex> old = %{"content" => [%{"type" => "paragraph", "text" => "Hello"}]}
iex> new = %{"content" => [%{"type" => "paragraph", "text" => "Hello"}, %{"type" => "paragraph", "text" => "World"}]}
iex> VersionHelpers.diff_documents(old, new)
[%{type: :added, path: [1], content: %{"type" => "paragraph", "text" => "World"}}]

diff_summary(changes)

@spec diff_summary([map()]) :: String.t()

Generate a human-readable summary of changes from a diff result.

Examples

iex> VersionHelpers.diff_summary([%{type: :added}, %{type: :removed}])
"1 added, 1 removed"

iex> VersionHelpers.diff_summary([])
"No changes"

format_version_date(datetime)

@spec format_version_date(DateTime.t() | NaiveDateTime.t() | nil) :: String.t()

Format a version timestamp for display.

Returns a human-readable date string such as "March 19, 2026 at 02:30 PM".

Examples

iex> VersionHelpers.format_version_date(nil)
""

iex> VersionHelpers.format_version_date(~U[2026-03-19 14:30:00Z])
"March 19, 2026 at 02:30 PM"

group_versions_by_day(versions)

@spec group_versions_by_day([map()]) :: [{Date.t(), [map()]}]

Group versions by day for timeline display.

Takes a list of version maps (with :created_at or "created_at" key) and returns a list of {date, versions} tuples sorted by date descending.

Examples

iex> versions = [%{created_at: ~U[2026-03-19 10:00:00Z]}, %{created_at: ~U[2026-03-18 09:00:00Z]}]
iex> VersionHelpers.group_versions_by_day(versions)
[{~D[2026-03-19], [%{created_at: ~U[2026-03-19 10:00:00Z]}]}, {~D[2026-03-18], [%{created_at: ~U[2026-03-18 09:00:00Z]}]}]

word_count_delta(old_count, new_count)

@spec word_count_delta(integer(), integer()) :: String.t()

Calculate word count delta between two versions as a display string.

Examples

iex> VersionHelpers.word_count_delta(100, 120)
"+20"

iex> VersionHelpers.word_count_delta(100, 80)
"-20"

iex> VersionHelpers.word_count_delta(100, 100)
"0"