commit: 7c6cff9f8ca17813f58c84488f06332ed9b6fd88
parent d3d75daff829e7b05fe87547337d4d2808436a75
Author: Alex Gleason <alex@alexgleason.me>
Date: Tue, 23 Jun 2020 18:21:18 -0500
Don't parse mentions inside links
Fixes: https://git.pleroma.social/pleroma/pleroma/-/issues/1656
Diffstat:
4 files changed, 49 insertions(+), 16 deletions(-)
diff --git a/README.md b/README.md
@@ -35,7 +35,7 @@ iex> Linkify.link("google.com", new_window: true, rel: "noopener noreferrer")
See the [Docs](https://hexdocs.pm/linkify/) for more examples
-## Acknowledgements
+## Acknowledgments
This is a fork of [auto_linker](https://github.com/smpallen99/auto_linker) by [Steve Pallen](https://github.com/smpallen99).
diff --git a/lib/linkify/parser.ex b/lib/linkify/parser.ex
@@ -62,19 +62,24 @@ defmodule Linkify.Parser do
def parse(input, opts) do
opts = Map.merge(@default_opts, opts)
-
- Enum.reduce(opts, input, fn
- {type, true}, input when type in @types ->
- do_parse(input, opts, {"", "", :parsing}, type)
-
- _, input ->
- input
+ opts_list = Map.to_list(opts)
+
+ Enum.reduce(@types, input, fn
+ type, input ->
+ if {type, true} in opts_list do
+ do_parse(input, opts, {"", "", :parsing}, type)
+ else
+ input
+ end
end)
end
defp do_parse({"", user_acc}, _opts, {"", acc, _}, _handler),
do: {acc, user_acc}
+ defp do_parse({"@" <> text, user_acc}, opts, {buffer, acc, :skip}, type),
+ do: do_parse({text, user_acc}, opts, {"", acc <> buffer <> "@", :skip}, type)
+
defp do_parse({"<a" <> text, user_acc}, opts, {buffer, acc, :parsing}, type),
do: do_parse({text, user_acc}, opts, {"", acc <> buffer <> "<a", :skip}, type)
diff --git a/mix.lock b/mix.lock
@@ -1,10 +1,10 @@
%{
- "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"},
- "credo": {:hex, :credo, "1.1.0", "e0c07b2fd7e2109495f582430a1bc96b2c71b7d94c59dfad120529f65f19872f", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"},
- "earmark": {:hex, :earmark, "1.3.2", "b840562ea3d67795ffbb5bd88940b1bed0ed9fa32834915125ea7d02e35888a5", [:mix], [], "hexpm"},
- "ex_doc": {:hex, :ex_doc, "0.20.2", "1bd0dfb0304bade58beb77f20f21ee3558cc3c753743ae0ddbb0fd7ba2912331", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
- "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
- "makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
- "makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"},
- "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm"},
+ "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
+ "credo": {:hex, :credo, "1.1.0", "e0c07b2fd7e2109495f582430a1bc96b2c71b7d94c59dfad120529f65f19872f", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "7338d04b30026e30adbcaaedbf0eb7e4d749510d90c2708ff8cc100fa9c8291f"},
+ "earmark": {:hex, :earmark, "1.3.2", "b840562ea3d67795ffbb5bd88940b1bed0ed9fa32834915125ea7d02e35888a5", [:mix], [], "hexpm", "e3be2bc3ae67781db529b80aa7e7c49904a988596e2dbff897425b48b3581161"},
+ "ex_doc": {:hex, :ex_doc, "0.20.2", "1bd0dfb0304bade58beb77f20f21ee3558cc3c753743ae0ddbb0fd7ba2912331", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "8e24fc8ff9a50b9f557ff020d6c91a03cded7e59ac3e0eec8a27e771430c7d27"},
+ "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fdf843bca858203ae1de16da2ee206f53416bbda5dc8c9e78f43243de4bc3afe"},
+ "makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5fbc8e549aa9afeea2847c0769e3970537ed302f93a23ac612602e805d9d1e7f"},
+ "makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "adf0218695e22caeda2820eaba703fa46c91820d53813a2223413da3ef4ba515"},
+ "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm", "5c040b8469c1ff1b10093d3186e2e10dbe483cd73d79ec017993fb3985b8a9b3"},
}
diff --git a/test/linkify_test.exs b/test/linkify_test.exs
@@ -126,6 +126,34 @@ defmodule LinkifyTest do
new_window: true
) == expected
end
+
+ test "mentions handler with hostname/@user links" do
+ text =
+ "hi @user, take a look at this post: https://example.com/@valid_user/posts/9w5AkQp956XIh74apc"
+
+ valid_users = ["user", "valid_user"]
+
+ handler = fn "@" <> user = mention, buffer, _opts, acc ->
+ if Enum.member?(valid_users, user) do
+ link = ~s(<a href="https://example.com/user/#{user}" data-user="#{user}">#{mention}</a>)
+ {link, %{acc | mentions: MapSet.put(acc.mentions, {mention, user})}}
+ else
+ {buffer, acc}
+ end
+ end
+
+ {result_text, %{mentions: mentions}} =
+ Linkify.link_map(text, %{mentions: MapSet.new()},
+ mention: true,
+ mention_handler: handler,
+ new_window: true
+ )
+
+ assert result_text ==
+ "hi <a href=\"https://example.com/user/user\" data-user=\"user\">@user</a>, take a look at this post: <a href=\"https://example.com/@valid_user/posts/9w5AkQp956XIh74apc\" target=\"_blank\">https://example.com/@valid_user/posts/9w5AkQp956XIh74apc</a>"
+
+ assert mentions |> MapSet.to_list() |> Enum.map(&elem(&1, 1)) == ["user"]
+ end
end
describe "mentions" do