towerops/lib/towerops_web/changelog_parser.ex
Graham McIntire 348975dcc9 Rewrite polling_offset, changelog_parser, and user_agent_parser in Gleam (#103)
Migrate three pure-function modules from Elixir to Gleam:

- polling_offset: deterministic hash-based polling offset (pure Gleam, no FFI)
- changelog_parser: text parsing logic in Gleam, thin Elixir wrapper for File I/O
- user_agent_parser: regex-based UA parsing in Gleam with Erlang FFI for
  atom-keyed map conversion

Add gleam_regexp dependency for regex support in Gleam modules.
Update all call sites and tests to use Gleam module atoms.

Reviewed-on: graham/towerops-web#103
2026-03-21 10:11:06 -05:00

33 lines
883 B
Elixir

defmodule ToweropsWeb.ChangelogParser do
@moduledoc """
Reads and parses priv/static/changelog.txt into structured entries.
File I/O and Date conversion happen here; pure parsing logic is in Gleam.
"""
@doc "Returns a list of %{date: Date.t(), title: String.t() | nil, items: [String.t()]}"
def parse do
path = Application.app_dir(:towerops, "priv/static/changelog.txt")
case File.read(path) do
{:ok, content} ->
content
|> :towerops_web@changelog_parser.parse_content()
|> Enum.map(&convert_entry/1)
{:error, _} ->
[]
end
end
defp convert_entry({:changelog_entry, date_str, title_opt, items}) do
%{
date: Date.from_iso8601!(date_str),
title: unwrap_option(title_opt),
items: items
}
end
defp unwrap_option({:some, value}), do: value
defp unwrap_option(:none), do: nil
end