builder.ex (4111B)
1 defmodule AutoLinker.Builder do 2 @moduledoc """ 3 Module for building the auto generated link. 4 """ 5 6 @doc """ 7 Create a link. 8 """ 9 def create_link(url, opts) do 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(url, opts) 16 end 17 18 def create_markdown_links(text, opts) do 19 [] 20 |> build_attrs(text, opts, :rel) 21 |> build_attrs(text, opts, :target) 22 |> build_attrs(text, opts, :class) 23 |> format_markdown(text, opts) 24 end 25 26 defp build_attrs(attrs, uri, %{rel: get_rel}, :rel) when is_function(get_rel, 1) do 27 case get_rel.(uri) do 28 nil -> attrs 29 rel -> [{:rel, rel} | attrs] 30 end 31 end 32 33 defp build_attrs(attrs, _, opts, :rel) do 34 if rel = Map.get(opts, :rel, "noopener noreferrer"), do: [{:rel, rel} | attrs], else: attrs 35 end 36 37 defp build_attrs(attrs, _, opts, :target) do 38 if Map.get(opts, :new_window, true), do: [{:target, :_blank} | attrs], else: attrs 39 end 40 41 defp build_attrs(attrs, _, opts, :class) do 42 if cls = Map.get(opts, :class, "auto-linker"), do: [{:class, cls} | attrs], else: attrs 43 end 44 45 defp build_attrs(attrs, url, _opts, :href) do 46 [{:href, url} | attrs] 47 end 48 49 defp format_url(attrs, url, _opts) do 50 attrs = format_attrs(attrs) 51 "<a #{attrs}>#{url}</a>" 52 end 53 54 defp format_attrs(attrs) do 55 attrs 56 |> Enum.map(fn {key, value} -> ~s(#{key}="#{value}") end) 57 |> Enum.join(" ") 58 end 59 60 defp format_markdown(attrs, text, _opts) do 61 attrs = 62 case format_attrs(attrs) do 63 "" -> "" 64 attrs -> " " <> attrs 65 end 66 67 Regex.replace(~r/\[(.+?)\]\((.+?)\)/, text, "<a href='\\2'#{attrs}>\\1</a>") 68 end 69 70 defp truncate(url, false), do: url 71 defp truncate(url, len) when len < 3, do: url 72 73 defp truncate(url, len) do 74 if String.length(url) > len, do: String.slice(url, 0, len - 2) <> "...", else: url 75 end 76 77 def create_phone_link([], buffer, _), do: buffer 78 79 def create_phone_link([h | t], buffer, opts) do 80 create_phone_link(t, format_phone_link(h, buffer, opts), opts) 81 end 82 83 def format_phone_link([h | _], buffer, opts) do 84 val = 85 h 86 |> String.replace(~r/[\.\+\- x\(\)]+/, "") 87 |> format_phone_link(h, opts) 88 89 # val = ~s'<a href="#" class="phone-number" data-phone="#{number}">#{h}</a>' 90 String.replace(buffer, h, val) 91 end 92 93 def format_phone_link(number, original, opts) do 94 tag = opts[:tag] || "a" 95 class = opts[:class] || "phone-number" 96 data_phone = opts[:data_phone] || "data-phone" 97 attrs = format_attributes(opts[:attributes] || []) 98 href = opts[:href] || "#" 99 100 ~s'<#{tag} href="#{href}" class="#{class}" #{data_phone}="#{number}"#{attrs}>#{original}</#{ 101 tag 102 }>' 103 end 104 105 def create_mention_link("@" <> name, _buffer, opts) do 106 mention_prefix = opts[:mention_prefix] 107 108 url = mention_prefix <> name 109 110 [] 111 |> build_attrs(url, opts, :rel) 112 |> build_attrs(url, opts, :target) 113 |> build_attrs(url, opts, :class) 114 |> build_attrs(url, opts, :href) 115 |> format_mention(name, opts) 116 end 117 118 def create_hashtag_link("#" <> tag, _buffer, opts) do 119 hashtag_prefix = opts[:hashtag_prefix] 120 121 url = hashtag_prefix <> tag 122 123 [] 124 |> build_attrs(url, opts, :rel) 125 |> build_attrs(url, opts, :target) 126 |> build_attrs(url, opts, :class) 127 |> build_attrs(url, opts, :href) 128 |> format_hashtag(tag, opts) 129 end 130 131 def create_email_link(email, opts) do 132 [] 133 |> build_attrs(email, opts, :class) 134 |> build_attrs("mailto:#{email}", opts, :href) 135 |> format_email(email, opts) 136 end 137 138 def format_mention(attrs, name, _opts) do 139 attrs = format_attrs(attrs) 140 "<a #{attrs}>@#{name}</a>" 141 end 142 143 def format_hashtag(attrs, tag, _opts) do 144 attrs = format_attrs(attrs) 145 "<a #{attrs}>##{tag}</a>" 146 end 147 148 def format_email(attrs, email, _opts) do 149 attrs = format_attrs(attrs) 150 ~s(<a #{attrs}>#{email}</a>) 151 end 152 153 defp format_attributes(attrs) do 154 Enum.reduce(attrs, "", fn {name, value}, acc -> 155 acc <> ~s' #{name}="#{value}"' 156 end) 157 end 158 end