commit: 86afaf49e5eceaaa2b2b72f1e290eeb6236ca020
parent 4764e1819e67774f063b9d19542d4611de654d09
Author: rinpatch <rinpatch@sdf.org>
Date: Tue, 6 Oct 2020 19:39:23 +0000
Merge branch 'fix/hashtag-link-parsing' into 'master'
Handle hashtags followed by skipped html tags (a, pre, code)
Closes #22
See merge request pleroma/elixir-libraries/linkify!25
Diffstat:
3 files changed, 78 insertions(+), 0 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
@@ -2,6 +2,10 @@
## [Unreleased]
+### Fixed
+
+- Hashtags followed by HTML tags "a", "code" and "pre" were not detected
+
## 0.2.0 - 2020-07-21
### Added
diff --git a/lib/linkify/parser.ex b/lib/linkify/parser.ex
@@ -22,6 +22,8 @@ defmodule Linkify.Parser do
@match_hashtag ~r/^(?<tag>\#[[:word:]_]*[[:alpha:]_·][[:word:]_·\p{M}]*)/u
+ @match_skipped_tag ~r/^(?<tag>(a|code|pre)).*>*/
+
@prefix_extra [
"magnet:?",
"dweb://",
@@ -84,6 +86,23 @@ defmodule Linkify.Parser do
defp do_parse({"@" <> text, user_acc}, opts, {buffer, acc, :skip}),
do: do_parse({text, user_acc}, opts, {"", accumulate(acc, buffer, "@"), :skip})
+ defp do_parse(
+ {"<" <> text, user_acc},
+ %{hashtag: true} = opts,
+ {"#" <> _ = buffer, acc, :parsing}
+ ) do
+ {buffer, user_acc} = link(buffer, opts, user_acc)
+
+ case Regex.run(@match_skipped_tag, text, capture: [:tag]) do
+ [tag] ->
+ text = String.trim_leading(text, tag)
+ do_parse({text, user_acc}, opts, {"", accumulate(acc, buffer, "<#{tag}"), :skip})
+
+ nil ->
+ do_parse({text, user_acc}, opts, {"<", acc, {:open, 1}})
+ end
+ end
+
defp do_parse({"<a" <> text, user_acc}, opts, {buffer, acc, :parsing}),
do: do_parse({text, user_acc}, opts, {"", accumulate(acc, buffer, "<a"), :skip})
diff --git a/test/linkify_test.exs b/test/linkify_test.exs
@@ -178,6 +178,61 @@ defmodule LinkifyTest do
"<a href=\"https://example.com/user/hello\">#hello</a> <a href=\"https://example.com/user/world\">#world</a>"
assert MapSet.to_list(tags) == ["#hello", "#world"]
+
+ text = "#cofe <br><a href=\"https://pleroma.social/\">Source</a>"
+
+ {_result_text, %{tags: tags}} =
+ Linkify.link_map(text, %{tags: MapSet.new()},
+ hashtag: true,
+ hashtag_handler: handler,
+ hashtag_prefix: "https://example.com/tag/"
+ )
+
+ assert MapSet.to_list(tags) == ["#cofe"]
+
+ text = "#cofe<br><a href=\"https://pleroma.social/\">Source</a>"
+
+ {_result_text, %{tags: tags}} =
+ Linkify.link_map(text, %{tags: MapSet.new()},
+ hashtag: true,
+ hashtag_handler: handler,
+ hashtag_prefix: "https://example.com/tag/"
+ )
+
+ assert MapSet.to_list(tags) == ["#cofe"]
+
+ text = "#cofe<a href=\"https://pleroma.social/\">Source</a>"
+
+ {_result_text, %{tags: tags}} =
+ Linkify.link_map(text, %{tags: MapSet.new()},
+ hashtag: true,
+ hashtag_handler: handler,
+ hashtag_prefix: "https://example.com/tag/"
+ )
+
+ assert MapSet.to_list(tags) == ["#cofe"]
+
+ text = "#cofe<code>fetch()</code>"
+
+ {_result_text, %{tags: tags}} =
+ Linkify.link_map(text, %{tags: MapSet.new()},
+ hashtag: true,
+ hashtag_handler: handler,
+ hashtag_prefix: "https://example.com/tag/"
+ )
+
+ assert MapSet.to_list(tags) == ["#cofe"]
+
+ text = "#cofe<pre>fetch()</pre>"
+
+ {_result_text, %{tags: tags}} =
+ Linkify.link_map(text, %{tags: MapSet.new()},
+ hashtag: true,
+ hashtag_handler: handler,
+ hashtag_prefix: "https://example.com/tag/"
+ )
+
+ assert MapSet.to_list(tags) == ["#cofe"]
end
test "mention handler and hashtag prefix" do