From 69902de571af7712e2aca40e1b5e2ade100d622c Mon Sep 17 00:00:00 2001 From: Sergey Suprunenko Date: Sun, 30 Aug 2020 18:43:45 +0200 Subject: [PATCH] Handle hashtags followed by skipped html tags --- CHANGELOG.md | 4 ++++ lib/linkify/parser.ex | 19 +++++++++++++++ test/linkify_test.exs | 55 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5554c8..9d86357 100644 --- 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 index 75717de..a8bcf57 100644 --- a/lib/linkify/parser.ex +++ b/lib/linkify/parser.ex @@ -22,6 +22,8 @@ defmodule Linkify.Parser do @match_hashtag ~r/^(?\#[[:word:]_]*[[:alpha:]_·][[:word:]_·\p{M}]*)/u + @match_skipped_tag ~r/^(?(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({" text, user_acc}, opts, {buffer, acc, :parsing}), do: do_parse({text, user_acc}, opts, {"", accumulate(acc, buffer, "#hello #world" assert MapSet.to_list(tags) == ["#hello", "#world"] + + text = "#cofe
Source" + + {_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
Source" + + {_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 = "#cofeSource" + + {_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 = "#cofefetch()" + + {_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
fetch()
" + + {_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