defmodule NPM.Format do @moduledoc """ Formatting utilities for npm CLI output. Shared formatting functions used across Mix tasks for consistent output. """ @doc """ Format a byte size into human-readable string. """ @spec bytes(non_neg_integer()) :: String.t() def bytes(b) when b < 1024, do: "#{b} B" def bytes(b) when b < 1_048_576, do: "#{Float.round(b / 1024, 1)} KB" def bytes(b) when b < 1_073_741_824, do: "#{Float.round(b / 1_048_576, 1)} MB" def bytes(b), do: "#{Float.round(b / 1_073_741_824, 1)} GB" @doc """ Format a duration in microseconds. """ @spec duration(non_neg_integer()) :: String.t() def duration(us) when us < 1_000, do: "#{us}µs" def duration(us) when us < 1_000_000, do: "#{div(us, 1_000)}ms" def duration(us), do: "#{Float.round(us / 1_000_000, 1)}s" @doc """ Format a package name and version. """ @spec package(String.t(), String.t()) :: String.t() def package(name, version), do: "#{name}@#{version}" @doc """ Pluralize a word based on count. """ @spec pluralize(non_neg_integer(), String.t(), String.t()) :: String.t() def pluralize(1, singular, _plural), do: "1 #{singular}" def pluralize(count, _singular, plural), do: "#{count} #{plural}" @doc """ Truncate a string to a maximum length. """ @spec truncate(String.t(), non_neg_integer()) :: String.t() def truncate(str, max) when byte_size(str) <= max, do: str def truncate(str, max), do: String.slice(str, 0, max - 3) <> "..." end