Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F116117
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
23 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/README.md b/README.md
index f2ac3c2..f5feb02 100644
--- a/README.md
+++ b/README.md
@@ -1,47 +1,66 @@
# AutoLinker
[![Build Status](https://travis-ci.org/smpallen99/auto_linker.png?branch=master)](https://travis-ci.org/smpallen99/auto_linker) [![Hex Version][hex-img]][hex] [![License][license-img]][license]
[hex-img]: https://img.shields.io/hexpm/v/auto_linker.svg
[hex]: https://hex.pm/packages/auto_linker
[license-img]: http://img.shields.io/badge/license-MIT-brightgreen.svg
[license]: http://opensource.org/licenses/MIT
-AutoLinker is a basic package for turning website names into links.
+AutoLinker is a basic package for turning website names, and phone numbers into links.
Use this package in your web view to convert web references into click-able links.
This is a very early version. Some of the described options are not yet functional.
## Installation
The package can be installed by adding `auto_linker` to your list of dependencies in `mix.exs`:
```elixir
def deps do
- [{:auto_linker, "~> 0.1"}]
+ [{:auto_linker, "~> 0.2"}]
end
```
## Usage
-```
+The following examples illustrate some examples on how to use the auto linker.
+
iex> AutoLinker.link("google.com")
"<a href='http://google.com' class='auto-linker' target='_blank' rel='noopener noreferrer'>google.com</a>"
iex> AutoLinker.link("google.com", new_window: false, rel: false)
"<a href='http://google.com' class='auto-linker'>google.com</a>"
iex> AutoLinker.link("google.com", new_window: false, rel: false, class: false)
"<a href='http://google.com'>google.com</a>"
-```
+
+iex> AutoLinker.link("call me at x9999")
+~s{call me at <a href="" class="phone-number" data-number="9999">x9999</a>}
+
+iex> AutoLinker.link("or at home on 555.555.5555")
+~s{or at home on <a href="" class="phone-number" data-number="55555555555">555.555.5555</a>}
+
+iex> AutoLinker.link(", work (555) 555-5555")
+~s{, work <a href="" class="phone-number" data-number="5555555555">(555) 555-5555</a>}
See the [Docs](https://hexdocs.pm/auto_linker/) for more examples
+## Configuration
+
+By default, link parsing is enabled and phone parsing is disabled.
+
+```elixir
+# enable phone parsing, and disable link parsing
+config :auto_linker, opts: [phone: true, url: false]
+```
+
+
## License
`auto_linker` is Copyright (c) 2017 E-MetroTel
The source is released under the MIT License.
Check [LICENSE](LICENSE) for more information.
diff --git a/lib/auto_linker.ex b/lib/auto_linker.ex
index 301be8b..721878e 100644
--- a/lib/auto_linker.ex
+++ b/lib/auto_linker.ex
@@ -1,56 +1,50 @@
defmodule AutoLinker do
@moduledoc """
Create url links from text containing urls.
Turns an input string like `"Check out google.com"` into
`Check out "<a href='http://google.com' target='_blank' rel='noopener noreferrer'>google.com</a>"`
## Examples
iex> AutoLinker.link("google.com")
"<a href='http://google.com' class='auto-linker' target='_blank' rel='noopener noreferrer'>google.com</a>"
iex> AutoLinker.link("google.com", new_window: false, rel: false)
"<a href='http://google.com' class='auto-linker'>google.com</a>"
iex> AutoLinker.link("google.com", new_window: false, rel: false, class: false)
"<a href='http://google.com'>google.com</a>"
"""
import AutoLinker.Parser
@doc """
Auto link a string.
Options:
* `class: "auto-linker"` - specify the class to be added to the generated link. false to clear
* `rel: "noopener noreferrer"` - override the rel attribute. false to clear
* `new_window: true` - set to false to remove `target='_blank'` attribute
* `scheme: false` - Set to true to link urls with schema `http://google`
* `truncate: false` - Set to a number to truncate urls longer then the number. Truncated urls will end in `..`
* `strip_prefix: true` - Strip the scheme prefix
* `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
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:
config :auto_linker,
class: false,
new_window: false
Note that passing opts to `link/2` will override the configuration settings.
"""
def link(text, opts \\ []) do
- opts =
- :auto_linker
- |> Application.get_all_env()
- |> Keyword.merge(opts)
-
- parse text, Enum.into(opts, %{})
+ parse text, opts
end
-
end
diff --git a/lib/auto_linker/builder.ex b/lib/auto_linker/builder.ex
index b55d818..00c42be 100644
--- a/lib/auto_linker/builder.ex
+++ b/lib/auto_linker/builder.ex
@@ -1,59 +1,91 @@
defmodule AutoLinker.Builder do
@moduledoc """
Module for building the auto generated link.
"""
@doc """
Create a link.
"""
def create_link(url, opts) do
[]
|> build_attrs(url, opts, :rel)
|> build_attrs(url, opts, :target)
|> build_attrs(url, opts, :class)
|> build_attrs(url, opts, :scheme)
|> format_url(url, opts)
end
defp build_attrs(attrs, _, opts, :rel) do
if rel = Map.get(opts, :rel, "noopener noreferrer"),
do: [{:rel, rel} | attrs], else: attrs
end
defp build_attrs(attrs, _, opts, :target) do
if Map.get(opts, :new_window, true),
do: [{:target, :_blank} | attrs], else: attrs
end
defp build_attrs(attrs, _, opts, :class) do
if cls = Map.get(opts, :class, "auto-linker"),
do: [{:class, cls} | attrs], else: attrs
end
defp build_attrs(attrs, url, _opts, :scheme) do
if String.starts_with?(url, ["http://", "https://"]),
do: [{:href, url} | attrs], else: [{:href, "http://" <> url} | attrs]
end
defp format_url(attrs, url, opts) do
url =
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(" ")
"<a #{attrs}>" <> url <> "</a>"
end
defp truncate(url, false), do: url
defp truncate(url, len) when len < 3, do: url
defp truncate(url, len) do
if String.length(url) > len, do: String.slice(url, 0, len - 2) <> "..", else: url
end
defp strip_prefix(url, true) do
url
|> String.replace(~r/^https?:\/\//, "")
|> String.replace(~r/^www\./, "")
end
defp strip_prefix(url, _), do: url
+
+ def create_phone_link([], buffer, _) do
+ buffer
+ end
+ def create_phone_link([h | t], buffer, opts) do
+ create_phone_link t, format_phone_link(h, buffer, opts), opts
+ end
+
+ def format_phone_link([h | _], buffer, opts) do
+ val =
+ h
+ |> String.replace(~r/[\.\+\- x\(\)]+/, "")
+ |> format_phone_link(h, opts)
+ # val = ~s'<a href="#" class="phone-number" data-phone="#{number}">#{h}</a>'
+ String.replace(buffer, h, val)
+ end
+
+ def format_phone_link(number, original, opts) do
+ tag = opts[:tag] || "a"
+ class = opts[:class] || "phone-number"
+ data_phone = opts[:data_phone] || "data-phone"
+ attrs = format_attributes(opts[:attributes] || [])
+ href = opts[:href] || "#"
+
+ ~s'<#{tag} href="#{href}" class="#{class}" #{data_phone}="#{number}"#{attrs}>#{original}</#{tag}>'
+ end
+
+ defp format_attributes(attrs) do
+ Enum.reduce(attrs, "", fn {name, value}, acc ->
+ acc <> ~s' #{name}="#{value}"'
+ end)
+ end
end
diff --git a/lib/auto_linker/parser.ex b/lib/auto_linker/parser.ex
index 88ecd7a..0c337dd 100644
--- a/lib/auto_linker/parser.ex
+++ b/lib/auto_linker/parser.ex
@@ -1,107 +1,186 @@
defmodule AutoLinker.Parser do
@moduledoc """
Module to handle parsing the the input string.
"""
alias AutoLinker.Builder
@doc """
- Parse the given string.
+ Parse the given string, identifying items to link.
- Parses the string, replacing the matching urls with an html link.
+ Parses the string, replacing the matching urls and phone numbers with an html link.
## Examples
iex> AutoLinker.Parser.parse("Check out google.com")
"Check out <a href='http://google.com' class='auto-linker' target='_blank' rel='noopener noreferrer'>google.com</a>"
+
+ iex> AutoLinker.Parser.parse("call me at x9999", phone: true)
+ ~s{call me at <a href="#" class="phone-number" data-phone="9999">x9999</a>}
+
+ iex> AutoLinker.Parser.parse("or at home on 555.555.5555", phone: true)
+ ~s{or at home on <a href="#" class="phone-number" data-phone="5555555555">555.555.5555</a>}
+
+ iex> AutoLinker.Parser.parse(", work (555) 555-5555", phone: true)
+ ~s{, work <a href="#" class="phone-number" data-phone="5555555555">(555) 555-5555</a>}
"""
- @match_dots ~r/\.\.+/
+ # @invalid_url ~r/\.\.+/
+ @invalid_url ~r/(\.\.+)|(^(\d+\.){1,2}\d+$)/
- @match_url ~r{^[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$}
+ @match_url ~r{^[\w\.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$}
@match_scheme ~r{^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$}
+ @match_phone ~r"((?:\+|00)[17](?:[ \-\.])?|(?:\+|00)[1-9]\d{0,2}(?:[ \-\.])?|(?:\+|00)1[\-\.]\d{3}(?:[ \-\.])?)?(0\d|\([0-9]{3}\)|[1-9]{0,3})(?:((?:[ \-\.])[0-9]{2}){4}|((?:[0-9]{2}){4})|((?:[ \-\.])[0-9]{3}(?:[ \-\.])[0-9]{4})|([0-9]{7}))|(x[0-9][0-9]+)"
+
+ @default_opts ~w(url)a
+
def parse(text, opts \\ %{})
def parse(text, list) when is_list(list), do: parse(text, Enum.into(list, %{}))
def parse(text, opts) do
+ config =
+ :auto_linker
+ |> Application.get_env(:opts, [])
+ |> Enum.into(%{})
+ config =
+ :auto_linker
+ |> Application.get_env(:attributes, [])
+ |> Enum.into(config)
+
+ opts =
+ Enum.reduce @default_opts, opts, fn opt, acc ->
+ if is_nil(opts[opt]) and is_nil(config[opt]) do
+ Map.put acc, opt, true
+ else
+ acc
+ end
+ end
+
+ do_parse text, Map.merge(config, opts)
+ end
+
+ 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, %{phone: _} = opts) do
+ text
+ |> do_parse(false, opts, {"", "", :parsing}, &check_and_link_phone/3)
+ |> do_parse(Map.delete(opts, :phone))
+ end
+
+ defp do_parse(text, %{url: _} = opts) do
if (exclude = Map.get(opts, :exclude_pattern, false)) && String.starts_with?(text, exclude) do
text
else
- parse(text, Map.get(opts, :scheme, false), opts, {"", "", :parsing})
+ do_parse(text, Map.get(opts, :scheme, false), opts, {"", "", :parsing}, &check_and_link/3)
end
+ |> do_parse(Map.delete(opts, :url))
end
+ defp do_parse(text, _), do: text
# state = {buffer, acc, state}
- defp parse("", _scheme, _opts ,{"", acc, _}),
+ defp do_parse("", _scheme, _opts ,{"", acc, _}, _handler),
do: acc
- defp parse("", scheme, opts ,{buffer, acc, _}),
- do: acc <> check_and_link(buffer, scheme, opts)
- defp parse("<" <> text, scheme, opts, {"", acc, :parsing}),
- do: parse(text, scheme, opts, {"<", acc, {:open, 1}})
+ defp do_parse("", scheme, opts ,{buffer, acc, _}, handler),
+ do: acc <> handler.(buffer, scheme, opts)
- defp parse(">" <> text, scheme, opts, {buffer, acc, {:attrs, level}}),
- do: parse(text, scheme, opts, {"", acc <> buffer <> ">", {:html, level}})
+ defp do_parse("<" <> text, scheme, opts, {"", acc, :parsing}, handler),
+ do: do_parse(text, scheme, opts, {"<", acc, {:open, 1}}, handler)
- defp parse(<<ch::8>> <> text, scheme, opts, {"", acc, {:attrs, level}}),
- do: parse(text, scheme, opts, {"", acc <> <<ch::8>>, {:attrs, level}})
+ defp do_parse(">" <> text, scheme, opts, {buffer, acc, {:attrs, level}}, handler),
+ do: do_parse(text, scheme, opts, {"", acc <> buffer <> ">", {:html, level}}, handler)
- defp parse("</" <> text, scheme, opts, {buffer, acc, {:html, level}}),
- do: parse(text, scheme, opts,
- {"", acc <> check_and_link(buffer, scheme, opts) <> "</", {:close, level}})
+ defp do_parse(<<ch::8>> <> text, scheme, opts, {"", acc, {:attrs, level}}, handler),
+ do: do_parse(text, scheme, opts, {"", acc <> <<ch::8>>, {:attrs, level}}, handler)
- defp parse(">" <> text, scheme, opts, {buffer, acc, {:close, 1}}),
- do: parse(text, scheme, opts, {"", acc <> buffer <> ">", :parsing})
+ defp do_parse("</" <> text, scheme, opts, {buffer, acc, {:html, level}}, handler),
+ do: do_parse(text, scheme, opts,
+ {"", acc <> handler.(buffer, scheme, opts) <> "</", {:close, level}}, handler)
- defp parse(">" <> text, scheme, opts, {buffer, acc, {:close, level}}),
- do: parse(text, scheme, opts, {"", acc <> buffer <> ">", {:html, level - 1}})
+ defp do_parse(">" <> text, scheme, opts, {buffer, acc, {:close, 1}}, handler),
+ do: do_parse(text, scheme, opts, {"", acc <> buffer <> ">", :parsing}, handler)
- defp parse(" " <> text, scheme, opts, {buffer, acc, {:open, level}}),
- do: parse(text, scheme, opts, {"", acc <> buffer <> " ", {:attrs, level}})
- defp parse("\n" <> text, scheme, opts, {buffer, acc, {:open, level}}),
- do: parse(text, scheme, opts, {"", acc <> buffer <> "\n", {:attrs, level}})
+ defp do_parse(">" <> text, scheme, opts, {buffer, acc, {:close, level}}, handler),
+ do: do_parse(text, scheme, opts, {"", acc <> buffer <> ">", {:html, level - 1}}, handler)
+
+ defp do_parse(" " <> text, scheme, opts, {buffer, acc, {:open, level}}, handler),
+ do: do_parse(text, scheme, opts, {"", acc <> buffer <> " ", {:attrs, level}}, handler)
+
+ defp do_parse("\n" <> text, scheme, opts, {buffer, acc, {:open, level}}, handler),
+ do: do_parse(text, scheme, opts, {"", acc <> buffer <> "\n", {:attrs, level}}, handler)
# default cases where state is not important
- defp parse(" " <> text, scheme, opts, {buffer, acc, state}),
- do: parse(text, scheme, opts,
- {"", acc <> check_and_link(buffer, scheme, opts) <> " ", state})
- defp parse("\n" <> text, scheme, opts, {buffer, acc, state}),
- do: parse(text, scheme, opts,
- {"", acc <> check_and_link(buffer, scheme, opts) <> "\n", state})
+ defp do_parse(" " <> text, scheme, %{phone: _} = opts, {buffer, acc, state}, handler),
+ do: do_parse(text, scheme, opts, {buffer <> " ", acc, state}, handler)
+
+ defp do_parse(" " <> text, scheme, opts, {buffer, acc, state}, handler),
+ do: do_parse(text, scheme, opts,
+ {"", acc <> handler.(buffer, scheme, opts) <> " ", state}, handler)
- defp parse(<<ch::8>> <> text, scheme, opts, {buffer, acc, state}),
- do: parse(text, scheme, opts, {buffer <> <<ch::8>>, acc, state})
+ defp do_parse("\n" <> text, scheme, opts, {buffer, acc, state}, handler),
+ do: do_parse(text, scheme, opts,
+ {"", acc <> handler.(buffer, scheme, opts) <> "\n", state}, handler)
+ defp do_parse(<<ch::8>>, scheme, opts, {buffer, acc, state}, handler),
+ do: do_parse("", scheme, opts,
+ {"", acc <> handler.(buffer <> <<ch::8>>, scheme, opts), state}, handler)
- defp check_and_link(buffer, scheme, opts) 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)
|> link_url(buffer, opts)
end
+ def check_and_link_phone(buffer, _, opts) do
+ buffer
+ |> match_phone
+ |> link_phone(buffer, opts)
+ end
+
@doc false
def is_url?(buffer, true) do
- if Regex.match? @match_dots, buffer do
+ if Regex.match? @invalid_url, buffer do
false
else
Regex.match? @match_scheme, buffer
end
end
+
def is_url?(buffer, _) do
- if Regex.match? @match_dots, buffer do
+ # IO.puts "..... '#{buffer}'"
+ if Regex.match? @invalid_url, buffer do
false
else
Regex.match? @match_url, buffer
end
end
+ @doc false
+ def match_phone(buffer) do
+ case Regex.scan @match_phone, buffer do
+ [] -> nil
+ other -> other
+ end
+ end
+
+ def link_phone(nil, buffer, _), do: buffer
+
+ def link_phone(list, buffer, opts) do
+ Builder.create_phone_link list, buffer, opts
+ end
+
@doc false
def link_url(true, buffer, opts) do
Builder.create_link(buffer, opts)
end
def link_url(_, buffer, _opts), do: buffer
end
diff --git a/mix.exs b/mix.exs
index 5954486..e7735eb 100644
--- a/mix.exs
+++ b/mix.exs
@@ -1,43 +1,43 @@
defmodule AutoLinker.Mixfile do
use Mix.Project
- @version "0.1.1"
+ @version "0.2.0"
def project do
[
app: :auto_linker,
version: @version,
elixir: "~> 1.4",
build_embedded: Mix.env == :prod,
start_permanent: Mix.env == :prod,
deps: deps(),
docs: [extras: ["README.md"]],
package: package(),
name: "AutoLinker",
description: """
AutoLinker is a basic package for turning website names into links.
"""
]
end
# Configuration for the OTP application
def application do
# Specify extra applications you'll use from Erlang/Elixir
[extra_applications: [:logger]]
end
# Dependencies can be Hex packages:
defp deps do
[
- {:ex_doc, "~> 0.15", only: :dev},
+ {:ex_doc, "~> 0.18", only: :dev},
{:earmark, "~> 1.2", only: :dev, override: true},
]
end
defp package do
[ maintainers: ["Stephen Pallen"],
licenses: ["MIT"],
links: %{ "Github" => "https://github.com/smpallen99/auto_linker" },
files: ~w(lib README.md mix.exs LICENSE)]
end
end
diff --git a/mix.lock b/mix.lock
index 46af344..da8bc52 100644
--- a/mix.lock
+++ b/mix.lock
@@ -1,2 +1,2 @@
-%{"earmark": {:hex, :earmark, "1.2.0", "bf1ce17aea43ab62f6943b97bd6e3dc032ce45d4f787504e3adf738e54b42f3a", [:mix], []},
- "ex_doc": {:hex, :ex_doc, "0.15.0", "e73333785eef3488cf9144a6e847d3d647e67d02bd6fdac500687854dd5c599f", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, optional: false]}]}}
+%{"earmark": {:hex, :earmark, "1.2.3", "206eb2e2ac1a794aa5256f3982de7a76bf4579ff91cb28d0e17ea2c9491e46a4", [:mix], [], "hexpm"},
+ "ex_doc": {:hex, :ex_doc, "0.18.1", "37c69d2ef62f24928c1f4fdc7c724ea04aecfdf500c4329185f8e3649c915baf", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}}
diff --git a/test/auto_linker_test.exs b/test/auto_linker_test.exs
index 15dd8a4..e00bf59 100644
--- a/test/auto_linker_test.exs
+++ b/test/auto_linker_test.exs
@@ -1,6 +1,11 @@
defmodule AutoLinkerTest do
use ExUnit.Case
doctest AutoLinker
+ test "phone number" do
+ assert AutoLinker.link(", work (555) 555-5555", phone: true) ==
+ ~s{, work <a href="#" class="phone-number" data-phone="5555555555">(555) 555-5555</a>}
+ end
+
end
diff --git a/test/builder_test.exs b/test/builder_test.exs
new file mode 100644
index 0000000..7670749
--- /dev/null
+++ b/test/builder_test.exs
@@ -0,0 +1,24 @@
+defmodule AutoLinker.BuilderTest do
+ use ExUnit.Case
+ doctest AutoLinker.Builder
+
+ import AutoLinker.Builder
+
+ describe "create_phone_link" do
+ test "finishes" do
+ assert create_phone_link([], "", []) == ""
+ end
+ test "handles one link" do
+ phrase = "my exten is x888. Call me."
+ expected = ~s'my exten is <a href="#" class="phone-number" data-phone="888">x888</a>. Call me.'
+ assert create_phone_link([["x888", ""]], phrase, []) == expected
+ end
+ test "handles multiple links" do
+ phrase = "555.555.5555 or (555) 888-8888"
+ expected = ~s'<a href="#" class="phone-number" data-phone="5555555555">555.555.5555</a> or ' <>
+ ~s'<a href="#" class="phone-number" data-phone="5558888888">(555) 888-8888</a>'
+ assert create_phone_link([["555.555.5555", ""], ["(555) 888-8888"]], phrase, []) == expected
+ end
+ end
+end
+
diff --git a/test/parser_test.exs b/test/parser_test.exs
index 5c43a10..767a027 100644
--- a/test/parser_test.exs
+++ b/test/parser_test.exs
@@ -1,93 +1,129 @@
defmodule AutoLinker.ParserTest do
use ExUnit.Case
doctest AutoLinker.Parser
import AutoLinker.Parser
-
describe "is_url" do
test "valid scheme true" do
valid_scheme_urls()
|> Enum.each(fn url ->
assert is_url?(url, true)
end)
end
test "invalid scheme true" do
invalid_scheme_urls()
|> Enum.each(fn url ->
refute is_url?(url, true)
end)
end
test "valid scheme false" do
valid_non_scheme_urls()
|> Enum.each(fn url ->
assert is_url?(url, false)
end)
end
test "invalid scheme false" do
invalid_non_scheme_urls()
|> Enum.each(fn url ->
refute is_url?(url, false)
end)
end
end
+ describe "match_phone" do
+ test "valid" do
+ valid_phone_nunbers()
+ |> Enum.each(fn number ->
+ assert number |> match_phone() |> is_list
+ end)
+ end
+
+ test "invalid" do
+ invalid_phone_numbers()
+ |> Enum.each(fn number ->
+ assert number |> match_phone() |> is_nil
+ end)
+ end
+ end
+
+
describe "parse" do
test "does not link attributes" do
text = "Check out <a href='google.com'>google</a>"
assert parse(text) == text
text = "Check out <img src='google.com' alt='google.com'/>"
assert parse(text) == text
text = "Check out <span><img src='google.com' alt='google.com'/></span>"
assert parse(text) == text
end
test "links url inside html" do
text = "Check out <div class='section'>google.com</div>"
expected = "Check out <div class='section'><a href='http://google.com'>google.com</a></div>"
assert parse(text, class: false, rel: false, new_window: false) == expected
end
test "excludes html with specified class" do
text = "```Check out <div class='section'>google.com</div>```"
assert parse(text, exclude_pattern: "```") == text
end
end
def valid_scheme_urls, do: [
"https://www.example.com",
"http://www2.example.com",
"http://home.example-site.com",
"http://blog.example.com",
"http://www.example.com/product",
"http://www.example.com/products?id=1&page=2",
"http://www.example.com#up",
"http://255.255.255.255",
"http://www.site.com:8008"
]
def invalid_scheme_urls, do: [
"http://invalid.com/perl.cgi?key= | http://web-site.com/cgi-bin/perl.cgi?key1=value1&key2",
]
def valid_non_scheme_urls, do: [
"www.example.com",
"www2.example.com",
"www.example.com:2000",
"www.example.com?abc=1",
"example.example-site.com",
"example.com",
"example.ca",
"example.tv",
"example.com:999?one=one",
"255.255.255.255",
"255.255.255.255:3000?one=1&two=2",
]
def invalid_non_scheme_urls, do: [
"invalid.com/perl.cgi?key= | web-site.com/cgi-bin/perl.cgi?key1=value1&key2",
"invalid.",
- "hi..there"
+ "hi..there",
+ "555.555.5555"
+ ]
+
+ def valid_phone_nunbers, do: [
+ "x55",
+ "x555",
+ "x5555",
+ "x12345",
+ "+1 555 555-5555",
+ "555 555-5555",
+ "555.555.5555",
+ "613-555-5555",
+ "1 (555) 555-5555",
+ "(555) 555-5555"
+ ]
+
+ def invalid_phone_numbers, do: [
+ "5555",
+ "x5",
+ "(555) 555-55",
]
end
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Nov 30, 11:43 AM (1 d, 15 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41423
Default Alt Text
(23 KB)
Attached To
Mode
R19 linkify
Attached
Detach File
Event Timeline
Log In to Comment