Browse Source

added support for markdown style links

merge-requests/1/head
Stephen M. Pallen 6 years ago
parent
commit
4d5182ec1f
6 changed files with 60 additions and 9 deletions
  1. +3
    -0
      README.md
  2. +7
    -0
      lib/auto_linker.ex
  3. +24
    -4
      lib/auto_linker/builder.ex
  4. +10
    -4
      lib/auto_linker/parser.ex
  5. +1
    -1
      mix.exs
  6. +15
    -0
      test/auto_linker_test.exs

+ 3
- 0
README.md View File

@ -45,6 +45,9 @@ iex> AutoLinker.link("or at home on 555.555.5555")
iex> AutoLinker.link(", work (555) 555-5555")
~s{, work <a href="" class="phone-number" data-number="5555555555">(555) 555-5555</a>}
iex> AutoLinker.link("[Google Search](http://google.com)", markdown: true)
"<a href='http://google.com' class='auto-linker' target='_blank' rel='noopener noreferrer'>Google Search</a>"
See the [Docs](https://hexdocs.pm/auto_linker/) for more examples
## Configuration


+ 7
- 0
lib/auto_linker.ex View File

@ -15,6 +15,12 @@ defmodule AutoLinker do
iex> AutoLinker.link("google.com", new_window: false, rel: false, class: false)
"<a href='http://google.com'>google.com</a>"
iex> AutoLinker.link("[Google](http://google.com)", markdown: true, new_window: false, rel: false, class: false)
"<a href='http://google.com'>Google</a>"
iex> AutoLinker.link("[Google Search](http://google.com)", markdown: true)
"<a href='http://google.com' class='auto-linker' target='_blank' rel='noopener noreferrer'>Google Search</a>"
"""
import AutoLinker.Parser
@ -33,6 +39,7 @@ defmodule AutoLinker do
* `exclude_class: false` - Set to a class name when you don't want urls auto linked in the html of the give class
* `exclude_id: false` - Set to an element id when you don't want urls auto linked in the html of the give element
* `exclude_patterns: ["```"] - Don't link anything between the the pattern
* `markdown: false` - link markdown style links
Each of the above options can be specified when calling `link(text, opts)`
or can be set in the `:auto_linker's configuration. For example:


+ 24
- 4
lib/auto_linker/builder.ex View File

@ -15,6 +15,14 @@ defmodule AutoLinker.Builder do
|> format_url(url, opts)
end
def create_markdown_links(text, opts) do
[]
|> build_attrs(text, opts, :rel)
|> build_attrs(text, opts, :target)
|> build_attrs(text, opts, :class)
|> format_markdown(text, opts)
end
defp build_attrs(attrs, _, opts, :rel) do
if rel = Map.get(opts, :rel, "noopener noreferrer"),
do: [{:rel, rel} | attrs], else: attrs
@ -37,13 +45,25 @@ defmodule AutoLinker.Builder do
url
|> strip_prefix(Map.get(opts, :strip_prefix, true))
|> truncate(Map.get(opts, :truncate, false))
attrs =
attrs
|> Enum.map(fn {key, value} -> ~s(#{key}='#{value}') end)
|> Enum.join(" ")
attrs = format_attrs(attrs)
"<a #{attrs}>" <> url <> "</a>"
end
defp format_attrs(attrs) do
attrs
|> Enum.map(fn {key, value} -> ~s(#{key}='#{value}') end)
|> Enum.join(" ")
end
defp format_markdown(attrs, text, _opts) do
attrs =
case format_attrs(attrs) do
"" -> ""
attrs -> " " <> attrs
end
Regex.replace(~r/\[(.+?)\]\((.+?)\)/, text, "<a href='\\2'#{attrs}>\\1</a>")
end
defp truncate(url, false), do: url
defp truncate(url, len) when len < 3, do: url
defp truncate(url, len) do


+ 10
- 4
lib/auto_linker/parser.ex View File

@ -62,6 +62,11 @@ defmodule AutoLinker.Parser do
defp do_parse(text, %{phone: false} = opts), do: do_parse(text, Map.delete(opts, :phone))
defp do_parse(text, %{url: false} = opts), do: do_parse(text, Map.delete(opts, :url))
defp do_parse(text, %{markdown: true} = opts) do
text
|> Builder.create_markdown_links(opts)
|> do_parse(Map.delete(opts, :markdown))
end
defp do_parse(text, %{phone: _} = opts) do
text
|> do_parse(false, opts, {"", "", :parsing}, &check_and_link_phone/3)
@ -79,13 +84,16 @@ defmodule AutoLinker.Parser do
defp do_parse(text, _), do: text
# state = {buffer, acc, state}
defp do_parse("", _scheme, _opts ,{"", acc, _}, _handler),
do: acc
defp do_parse("", scheme, opts ,{buffer, acc, _}, handler),
do: acc <> handler.(buffer, scheme, opts)
defp do_parse("<a" <> text, scheme, opts, {buffer, acc, :parsing}, handler),
do: do_parse(text, scheme, opts, {"", acc <> buffer <> "<a", :skip}, handler)
defp do_parse("</a>" <> text, scheme, opts, {buffer, acc, :skip}, handler),
do: do_parse(text, scheme, opts, {"", acc <> buffer <> "</a>", :parsing}, handler)
defp do_parse("<" <> text, scheme, opts, {"", acc, :parsing}, handler),
do: do_parse(text, scheme, opts, {"<", acc, {:open, 1}}, handler)
@ -131,7 +139,6 @@ defmodule AutoLinker.Parser do
defp do_parse(<<ch::8>> <> text, scheme, opts, {buffer, acc, state}, handler),
do: do_parse(text, scheme, opts, {buffer <> <<ch::8>>, acc, state}, handler)
def check_and_link(buffer, scheme, opts) do
buffer
|> is_url?(scheme)
@ -154,7 +161,6 @@ defmodule AutoLinker.Parser do
end
def is_url?(buffer, _) do
# IO.puts "..... '#{buffer}'"
if Regex.match? @invalid_url, buffer do
false
else


+ 1
- 1
mix.exs View File

@ -1,7 +1,7 @@
defmodule AutoLinker.Mixfile do
use Mix.Project
@version "0.2.1"
@version "0.2.2"
def project do
[


+ 15
- 0
test/auto_linker_test.exs View File

@ -8,4 +8,19 @@ defmodule AutoLinkerTest do
~s{, work <a href="#" class="phone-number" data-phone="5555555555">(555) 555-5555</a>}
end
test "default link" do
assert AutoLinker.link("google.com") ==
"<a href='http://google.com' class='auto-linker' target='_blank' rel='noopener noreferrer'>google.com</a>"
end
test "markdown" do
assert AutoLinker.link("[google.com](http://google.com)", markdown: true) ==
"<a href='http://google.com' class='auto-linker' target='_blank' rel='noopener noreferrer'>google.com</a>"
end
test "does on link existing links" do
assert AutoLinker.link("<a href='http://google.com'>google.com</a>") ==
"<a href='http://google.com'>google.com</a>"
end
end

Loading…
Cancel
Save