logo

auto_linker

AutoLinker-shim, based on https://git.pleroma.social/pleroma/auto_linker git clone https://anongit.hacktivis.me/git/auto_linker.git/

builder.ex (3804B)


  1. defmodule Linkify.Builder do
  2. @moduledoc """
  3. Module for building the auto generated link.
  4. """
  5. @doc """
  6. Create a link.
  7. """
  8. def create_link(url, opts) do
  9. []
  10. |> build_attrs(url, opts, :rel)
  11. |> build_attrs(url, opts, :target)
  12. |> build_attrs(url, opts, :class)
  13. |> build_attrs(url, opts, :href)
  14. |> format_url(url, opts)
  15. end
  16. defp build_attrs(attrs, uri, %{rel: get_rel}, :rel) when is_function(get_rel, 1) do
  17. case get_rel.(uri) do
  18. nil -> attrs
  19. rel -> [{:rel, rel} | attrs]
  20. end
  21. end
  22. defp build_attrs(attrs, _, opts, :rel) do
  23. case Map.get(opts, :rel) do
  24. rel when is_binary(rel) -> [{:rel, rel} | attrs]
  25. _ -> attrs
  26. end
  27. end
  28. defp build_attrs(attrs, _, opts, :target) do
  29. if Map.get(opts, :new_window), do: [{:target, :_blank} | attrs], else: attrs
  30. end
  31. defp build_attrs(attrs, _, opts, :class) do
  32. case Map.get(opts, :class) do
  33. cls when is_binary(cls) -> [{:class, cls} | attrs]
  34. _ -> attrs
  35. end
  36. end
  37. defp build_attrs(attrs, url, opts, :href) do
  38. case Map.get(opts, :href_handler) do
  39. handler when is_function(handler) -> [{:href, handler.(url)} | attrs]
  40. _ -> [{:href, url} | attrs]
  41. end
  42. end
  43. defp format_url(attrs, url, opts) do
  44. url =
  45. url
  46. |> strip_prefix(Map.get(opts, :strip_prefix, false))
  47. |> truncate(Map.get(opts, :truncate, false))
  48. attrs
  49. |> format_attrs()
  50. |> format_tag(url, opts)
  51. end
  52. defp format_attrs(attrs) do
  53. attrs
  54. |> Enum.map(fn {key, value} -> ~s(#{key}="#{value}") end)
  55. |> Enum.join(" ")
  56. end
  57. defp truncate(url, false), do: url
  58. defp truncate(url, len) when len < 3, do: url
  59. defp truncate(url, len) do
  60. if String.length(url) > len, do: String.slice(url, 0, len - 2) <> "...", else: url
  61. end
  62. defp strip_prefix(url, true) do
  63. url
  64. |> String.replace(~r/^https?:\/\//, "")
  65. |> String.replace(~r/^www\./, "")
  66. end
  67. defp strip_prefix(url, _), do: url
  68. def create_mention_link("@" <> name, _buffer, opts) do
  69. mention_prefix = opts[:mention_prefix]
  70. url = mention_prefix <> name
  71. []
  72. |> build_attrs(url, opts, :rel)
  73. |> build_attrs(url, opts, :target)
  74. |> build_attrs(url, opts, :class)
  75. |> build_attrs(url, opts, :href)
  76. |> format_mention(name, opts)
  77. end
  78. def create_hashtag_link("#" <> tag, _buffer, opts) do
  79. hashtag_prefix = opts[:hashtag_prefix]
  80. url = hashtag_prefix <> tag
  81. []
  82. |> build_attrs(url, opts, :rel)
  83. |> build_attrs(url, opts, :target)
  84. |> build_attrs(url, opts, :class)
  85. |> build_attrs(url, opts, :href)
  86. |> format_hashtag(tag, opts)
  87. end
  88. def create_email_link(email, opts) do
  89. []
  90. |> build_attrs(email, opts, :class)
  91. |> build_attrs("mailto:#{email}", opts, :href)
  92. |> format_email(email, opts)
  93. end
  94. def create_extra_link(uri, opts) do
  95. []
  96. |> build_attrs(uri, opts, :class)
  97. |> build_attrs(uri, opts, :rel)
  98. |> build_attrs(uri, opts, :target)
  99. |> build_attrs(uri, opts, :href)
  100. |> format_extra(uri, opts)
  101. end
  102. def format_mention(attrs, name, opts) do
  103. attrs
  104. |> format_attrs()
  105. |> format_tag("@#{name}", opts)
  106. end
  107. def format_hashtag(attrs, tag, opts) do
  108. attrs
  109. |> format_attrs()
  110. |> format_tag("##{tag}", opts)
  111. end
  112. def format_email(attrs, email, opts) do
  113. attrs
  114. |> format_attrs()
  115. |> format_tag(email, opts)
  116. end
  117. def format_extra(attrs, uri, opts) do
  118. attrs
  119. |> format_attrs()
  120. |> format_tag(uri, opts)
  121. end
  122. def format_tag(attrs, content, %{iodata: true}) do
  123. ["<a ", attrs, ">", content, "</a>"]
  124. end
  125. def format_tag(attrs, content, %{iodata: :safe}) do
  126. [{:safe, ["<a ", attrs, ">"]}, content, {:safe, "</a>"}]
  127. end
  128. def format_tag(attrs, content, _opts) do
  129. "<a #{attrs}>#{content}</a>"
  130. end
  131. end