commit: 4d5182ec1febb9d9963fce5825cb16a8f7e6e17d
parent: 6c56eb91efb4293bea185c524808c0a8b34d5d8b
Author: Stephen M. Pallen <smpallen99@yahoo.com>
Date: Mon, 22 Jan 2018 19:46:47 -0500
added support for markdown style links
Diffstat:
6 files changed, 60 insertions(+), 9 deletions(-)
diff --git a/README.md b/README.md
@@ -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
diff --git a/lib/auto_linker.ex b/lib/auto_linker.ex
@@ -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:
diff --git a/lib/auto_linker/builder.ex b/lib/auto_linker/builder.ex
@@ -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
diff --git a/lib/auto_linker/parser.ex b/lib/auto_linker/parser.ex
@@ -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
diff --git a/mix.exs b/mix.exs
@@ -1,7 +1,7 @@
defmodule AutoLinker.Mixfile do
use Mix.Project
- @version "0.2.1"
+ @version "0.2.2"
def project do
[
diff --git a/test/auto_linker_test.exs b/test/auto_linker_test.exs
@@ -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