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.

156 lines
4.0 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
  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(text, opts) do
  9. url = add_scheme(text)
  10. []
  11. |> build_attrs(url, opts, :rel)
  12. |> build_attrs(url, opts, :target)
  13. |> build_attrs(url, opts, :class)
  14. |> build_attrs(url, opts, :href)
  15. |> format_url(text, opts)
  16. end
  17. defp build_attrs(attrs, uri, %{rel: get_rel}, :rel) when is_function(get_rel, 1) do
  18. case get_rel.(uri) do
  19. nil -> attrs
  20. rel -> [{:rel, rel} | attrs]
  21. end
  22. end
  23. defp build_attrs(attrs, _, opts, :rel) do
  24. case Map.get(opts, :rel) do
  25. rel when is_binary(rel) -> [{:rel, rel} | attrs]
  26. _ -> attrs
  27. end
  28. end
  29. defp build_attrs(attrs, _, opts, :target) do
  30. if Map.get(opts, :new_window), do: [{:target, :_blank} | attrs], else: attrs
  31. end
  32. defp build_attrs(attrs, _, opts, :class) do
  33. case Map.get(opts, :class) do
  34. cls when is_binary(cls) -> [{:class, cls} | attrs]
  35. _ -> attrs
  36. end
  37. end
  38. defp build_attrs(attrs, url, _opts, :href) do
  39. [{:href, url} | attrs]
  40. end
  41. defp add_scheme("http://" <> _ = url), do: url
  42. defp add_scheme("https://" <> _ = url), do: url
  43. defp add_scheme(url), do: "http://" <> url
  44. defp format_url(attrs, url, opts) do
  45. url =
  46. url
  47. |> strip_prefix(Map.get(opts, :strip_prefix, false))
  48. |> truncate(Map.get(opts, :truncate, false))
  49. attrs = format_attrs(attrs)
  50. "<a #{attrs}>#{url}</a>"
  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 create_youtube(text, _opts) do
  103. id = get_video_id(text)
  104. "<div class=\"embed-responsive embed-responsive-16by9\"><iframe class=\"embed-responsive-item\" src=\"https://www.youtube.com/embed/#{id}\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe></div>"
  105. end
  106. Enum.each(["", "http://", "https://"], fn protocol ->
  107. Enum.each(["youtu.be/", "www.youtube.com/watch?v=", "www.youtube.com/?v="], fn prefix ->
  108. def get_video_id(unquote(protocol <> prefix) <> id), do: id
  109. end)
  110. end)
  111. def format_mention(attrs, name, _opts) do
  112. attrs = format_attrs(attrs)
  113. "<a #{attrs}>@#{name}</a>"
  114. end
  115. def format_hashtag(attrs, tag, _opts) do
  116. attrs = format_attrs(attrs)
  117. "<a #{attrs}>##{tag}</a>"
  118. end
  119. def format_email(attrs, email, _opts) do
  120. attrs = format_attrs(attrs)
  121. ~s(<a #{attrs}>#{email}</a>)
  122. end
  123. def format_extra(attrs, uri, _opts) do
  124. attrs = format_attrs(attrs)
  125. ~s(<a #{attrs}>#{uri}</a>)
  126. end
  127. end