You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

68 lines
2.1 KiB

  1. defmodule Microformats2.Rels do
  2. def parse(doc, base_url) do
  3. link_rels =
  4. Floki.find(doc, "[rel][href]")
  5. |> Enum.filter(fn element ->
  6. rel = Floki.attribute(element, "rel") |> List.first()
  7. href = Floki.attribute(element, "href") |> List.first()
  8. String.trim(to_string(rel)) != "" and String.trim(to_string(href)) != ""
  9. end)
  10. |> Enum.reduce(%{rels: %{}, rel_urls: %{}}, fn element, acc ->
  11. rel = Microformats2.attr_list(element, "rel")
  12. url = Floki.attribute(element, "href") |> List.first() |> Microformats2.abs_uri(base_url, doc)
  13. acc
  14. |> save_urls_by_rels(rel, url)
  15. |> save_rels_by_urls(rel, url)
  16. |> save_attributes(element, url)
  17. end)
  18. link_rels
  19. end
  20. defp save_urls_by_rels(map, rel, url) do
  21. Enum.reduce(rel, map, fn rel, nmap ->
  22. if nmap[:rels][rel] == nil do
  23. Map.put(nmap, :rels, Map.put(nmap[:rels], rel, [url]))
  24. else
  25. Map.put(nmap, :rels, Map.put(nmap[:rels], rel, Enum.uniq(nmap[:rels][rel] ++ [url])))
  26. end
  27. end)
  28. end
  29. defp save_rels_by_urls(map, rel, url) do
  30. if map[:rel_urls][url] == nil do
  31. Map.put(map, :rel_urls, Map.put(map[:rel_urls], url, %{rels: rel}))
  32. else
  33. Map.put(
  34. map,
  35. :rel_urls,
  36. Map.put(map[:rel_urls], url, Map.put(map[:rel_urls][url], :rels, Enum.uniq(map[:rel_urls][url][:rels] ++ rel)))
  37. )
  38. end
  39. end
  40. defp save_text(map, element, url) do
  41. text = Floki.text(element)
  42. if String.trim(to_string(text)) == "" or map[:rel_urls][url][:text] != nil do
  43. map
  44. else
  45. Map.put(map, :rel_urls, Map.put(map[:rel_urls], url, Map.put(map[:rel_urls][url], :text, text)))
  46. end
  47. end
  48. defp save_attributes(map, element, url) do
  49. Enum.reduce(["hreflang", "media", "title", "type"], save_text(map, element, url), fn att, nmap ->
  50. val = Floki.attribute(element, att) |> List.first()
  51. if String.trim(to_string(val)) == "" or nmap[:rel_urls][url][String.to_atom(att)] != nil do
  52. nmap
  53. else
  54. Map.put(nmap, :rel_urls, Map.put(nmap[:rel_urls], url, Map.put(nmap[:rel_urls][url], String.to_atom(att), val)))
  55. end
  56. end)
  57. end
  58. end