diff --git a/lib/hexdocs/queue.ex b/lib/hexdocs/queue.ex index 8d0a46f..e047161 100644 --- a/lib/hexdocs/queue.ex +++ b/lib/hexdocs/queue.ex @@ -268,36 +268,82 @@ defmodule Hexdocs.Queue do end defp find_search_items(package, version, files) do - search_data_json = + search_data = Enum.find_value(files, fn {path, content} -> case Path.basename(path) do - "search_data-" <> _digest -> - "searchData=" <> json = content - json - - _other -> - nil + "search_data-" <> _digest -> {:elixir, content} + "search-data.js" -> {:gleam, content} + _other -> nil end end) - unless search_data_json do - Logger.info("Failed to find search data for #{package} #{version}") + case search_data do + {:elixir, content} -> + extract_elixir_search_items(package, version, content) + + {:gleam, content} -> + extract_gleam_search_items(package, version, content) + + nil -> + Logger.info("Failed to find search data for #{package} #{version}") + nil + end + end + + defp extract_gleam_search_items(package, version, search_data) do + "window.Gleam.initSearch(" <> search_items_js = search_data + + search_items = + case Jason.decode(search_items_js) do + {:ok, search_items} -> + search_items + + {:error, %Jason.DecodeError{position: position}} -> + case Jason.decode(:binary.part(search_items_js, 0, position)) do + {:ok, search_items} -> + search_items + + {:error, error} -> + Logger.error( + "Failed to decode search data json for #{package} #{version}: " <> + Exception.message(error) + ) + + nil + end + end + + case search_items do + items when is_list(items) -> + Enum.map(items, fn item -> + %{"content" => doc, "doc" => _, "title" => title, "url" => ref} = item + %{"doc" => doc, "title" => title, "ref" => ref} + end) + + nil -> + nil + + _ -> + Logger.error("Failed to extract search items from search data for #{package} #{version}") + nil end + end + + defp extract_elixir_search_items(package, version, search_data) do + "searchData=" <> search_data_json = search_data search_data = - if search_data_json do - case Jason.decode(search_data_json) do - {:ok, search_data} -> - search_data - - {:error, error} -> - Logger.error( - "Failed to decode search data json for #{package} #{version}: " <> - Exception.message(error) - ) + case Jason.decode(search_data_json) do + {:ok, search_data} -> + search_data - nil - end + {:error, error} -> + Logger.error( + "Failed to decode search data json for #{package} #{version}: " <> + Exception.message(error) + ) + + nil end case search_data do