From e16136f70950c60a879fbd965c871946fedb51bf Mon Sep 17 00:00:00 2001
From: Sergey Suprunenko <suprunenko.s@gmail.com>
Date: Tue, 10 Nov 2020 21:24:50 +0100
Subject: [PATCH 1/3] Do not parse mention if there is something before it

---
 lib/linkify/parser.ex | 2 +-
 test/linkify_test.exs | 6 ++++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/lib/linkify/parser.ex b/lib/linkify/parser.ex
index 1e5c3db..eab5891 100644
--- a/lib/linkify/parser.ex
+++ b/lib/linkify/parser.ex
@@ -15,7 +15,7 @@ defmodule Linkify.Parser do
 
   # @user
   # @user@example.com
-  @match_mention ~r"^@[a-zA-Z\d_-]+@[a-zA-Z0-9_-](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*|@[a-zA-Z\d_-]+"u
+  @match_mention ~r"^@[a-zA-Z\d_-]+@[a-zA-Z0-9_-](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*|^@[a-zA-Z\d_-]+"u
 
   # https://www.w3.org/TR/html5/forms.html#valid-e-mail-address
   @match_email ~r"^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"u
diff --git a/test/linkify_test.exs b/test/linkify_test.exs
index b5059f6..a18dc3c 100644
--- a/test/linkify_test.exs
+++ b/test/linkify_test.exs
@@ -385,6 +385,12 @@ defmodule LinkifyTest do
                mention_prefix: "https://example.com/user/"
              ) == expected
     end
+
+    test "invalid mentions" do
+      text = "hey user@example"
+
+      assert Linkify.link(text, mention: true, mention_prefix: "/users/") == text
+    end
   end
 
   describe "hashtag links" do
-- 
GitLab


From 2a050e1cbe3005bec25cb321f4c60cd656ac7ed9 Mon Sep 17 00:00:00 2001
From: Sergey Suprunenko <suprunenko.s@gmail.com>
Date: Mon, 16 Nov 2020 18:57:01 +0100
Subject: [PATCH 2/3] Ignore non-word chars in the beginning of mentions

---
 CHANGELOG.md          | 1 +
 lib/linkify/parser.ex | 7 ++++---
 test/linkify_test.exs | 9 +++++++++
 3 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index adfc4a7..9cb2132 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@
 - Hashtags followed by HTML tags "a", "code" and "pre" were not detected
 - Incorrect parsing of HTML links inside HTML tags
 - Punctuation marks in the end of urls were included in the html links
+- Incorrect parsing of mentions with symbols before them
 
 ## 0.2.0 - 2020-07-21
 
diff --git a/lib/linkify/parser.ex b/lib/linkify/parser.ex
index eab5891..af826c3 100644
--- a/lib/linkify/parser.ex
+++ b/lib/linkify/parser.ex
@@ -15,7 +15,7 @@ defmodule Linkify.Parser do
 
   # @user
   # @user@example.com
-  @match_mention ~r"^@[a-zA-Z\d_-]+@[a-zA-Z0-9_-](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*|^@[a-zA-Z\d_-]+"u
+  @match_mention ~r/^(?:\W*)?(?<long>@[a-zA-Z\d_-]+@[a-zA-Z0-9_-](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)|^(?:\W*)?(?<short>@[a-zA-Z\d_-]+)/u
 
   # https://www.w3.org/TR/html5/forms.html#valid-e-mail-address
   @match_email ~r"^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"u
@@ -254,8 +254,9 @@ defmodule Linkify.Parser do
   def ip?(buffer), do: Regex.match?(@match_ip, buffer)
 
   def match_mention(buffer) do
-    case Regex.run(@match_mention, buffer) do
-      [mention] -> mention
+    case Regex.run(@match_mention, buffer, capture: [:long, :short]) do
+      [mention, ""] -> mention
+      ["", mention] -> mention
       _ -> nil
     end
   end
diff --git a/test/linkify_test.exs b/test/linkify_test.exs
index a18dc3c..73ff6d0 100644
--- a/test/linkify_test.exs
+++ b/test/linkify_test.exs
@@ -386,6 +386,15 @@ defmodule LinkifyTest do
              ) == expected
     end
 
+    test "mentions with symbols before them" do
+      text = "@@example hey! >@@test@example.com"
+
+      expected =
+        "@<a href=\"/users/example\">@example</a> hey! >@<a href=\"/users/test@example.com\">@test@example.com</a>"
+
+      assert Linkify.link(text, mention: true, mention_prefix: "/users/") == expected
+    end
+
     test "invalid mentions" do
       text = "hey user@example"
 
-- 
GitLab


From 45e970d60465d4d727cd1dec6213a12ada004219 Mon Sep 17 00:00:00 2001
From: Sergey Suprunenko <suprunenko.s@gmail.com>
Date: Mon, 16 Nov 2020 23:18:32 +0100
Subject: [PATCH 3/3] Upgrade credo

---
 lib/linkify/parser.ex | 1 +
 mix.exs               | 2 +-
 mix.lock              | 5 +++--
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/lib/linkify/parser.ex b/lib/linkify/parser.ex
index af826c3..64d08db 100644
--- a/lib/linkify/parser.ex
+++ b/lib/linkify/parser.ex
@@ -15,6 +15,7 @@ defmodule Linkify.Parser do
 
   # @user
   # @user@example.com
+  # credo:disable-for-next-line
   @match_mention ~r/^(?:\W*)?(?<long>@[a-zA-Z\d_-]+@[a-zA-Z0-9_-](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)|^(?:\W*)?(?<short>@[a-zA-Z\d_-]+)/u
 
   # https://www.w3.org/TR/html5/forms.html#valid-e-mail-address
diff --git a/mix.exs b/mix.exs
index 93b7934..f78671d 100644
--- a/mix.exs
+++ b/mix.exs
@@ -30,7 +30,7 @@ defmodule Linkify.Mixfile do
   defp deps do
     [
       {:ex_doc, "~> 0.20", only: :dev, runtime: false},
-      {:credo, "~> 1.4.0", only: [:dev, :test], runtime: false}
+      {:credo, "~> 1.5", only: [:dev, :test], runtime: false}
     ]
   end
 
diff --git a/mix.lock b/mix.lock
index be2b77f..a658f27 100644
--- a/mix.lock
+++ b/mix.lock
@@ -1,10 +1,11 @@
 %{
   "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
-  "credo": {:hex, :credo, "1.4.0", "92339d4cbadd1e88b5ee43d427b639b68a11071b6f73854e33638e30a0ea11f5", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "1fd3b70dce216574ce3c18bdf510b57e7c4c85c2ec9cad4bff854abaf7e58658"},
+  "credo": {:hex, :credo, "1.5.1", "4fe303cc828412b9d21eed4eab60914c401e71f117f40243266aafb66f30d036", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "0b219ca4dcc89e4e7bc6ae7e6539c313e738e192e10b85275fa1e82b5203ecd7"},
   "earmark": {:hex, :earmark, "1.4.10", "bddce5e8ea37712a5bfb01541be8ba57d3b171d3fa4f80a0be9bcf1db417bcaf", [:mix], [{:earmark_parser, ">= 1.4.10", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "12dbfa80810478e521d3ffb941ad9fbfcbbd7debe94e1341b4c4a1b2411c1c27"},
   "earmark_parser": {:hex, :earmark_parser, "1.4.10", "6603d7a603b9c18d3d20db69921527f82ef09990885ed7525003c7fe7dc86c56", [:mix], [], "hexpm", "8e2d5370b732385db2c9b22215c3f59c84ac7dda7ed7e544d7c459496ae519c0"},
   "ex_doc": {:hex, :ex_doc, "0.22.1", "9bb6d51508778193a4ea90fa16eac47f8b67934f33f8271d5e1edec2dc0eee4c", [:mix], [{:earmark, "~> 1.4.0", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "d957de1b75cb9f78d3ee17820733dc4460114d8b1e11f7ee4fd6546e69b1db60"},
-  "jason": {:hex, :jason, "1.2.1", "12b22825e22f468c02eb3e4b9985f3d0cb8dc40b9bd704730efa11abd2708c44", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b659b8571deedf60f79c5a608e15414085fa141344e2716fbd6988a084b5f993"},
+  "file_system": {:hex, :file_system, "0.2.9", "545b9c9d502e8bfa71a5315fac2a923bd060fd9acb797fe6595f54b0f975fd32", [:mix], [], "hexpm", "3cf87a377fe1d93043adeec4889feacf594957226b4f19d5897096d6f61345d8"},
+  "jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
   "makeup": {:hex, :makeup, "1.0.3", "e339e2f766d12e7260e6672dd4047405963c5ec99661abdc432e6ec67d29ef95", [:mix], [{:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "2e9b4996d11832947731f7608fed7ad2f9443011b3b479ae288011265cdd3dad"},
   "makeup_elixir": {:hex, :makeup_elixir, "0.14.1", "4f0e96847c63c17841d42c08107405a005a2680eb9c7ccadfd757bd31dabccfb", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f2438b1a80eaec9ede832b5c41cd4f373b38fd7aa33e3b22d9db79e640cbde11"},
   "nimble_parsec": {:hex, :nimble_parsec, "0.6.0", "32111b3bf39137144abd7ba1cce0914533b2d16ef35e8abc5ec8be6122944263", [:mix], [], "hexpm", "27eac315a94909d4dc68bc07a4a83e06c8379237c5ea528a9acff4ca1c873c52"},
-- 
GitLab