From c8735e58378bef65f534c30253b3f5e689950933 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Tue, 18 Jan 2022 12:46:33 +0100 Subject: [PATCH] Fix parsing links with hashtag characters Closes #1008 Signed-off-by: Thomas Citharel --- lib/service/formatter/formatter.ex | 43 ++--------------------- test/service/formatter/formatter_test.exs | 14 ++++++++ 2 files changed, 17 insertions(+), 40 deletions(-) diff --git a/lib/service/formatter/formatter.ex b/lib/service/formatter/formatter.ex index 32f515ffa..bf1e623b9 100644 --- a/lib/service/formatter/formatter.ex +++ b/lib/service/formatter/formatter.ex @@ -94,8 +94,7 @@ defmodule Mobilizon.Service.Formatter do options = linkify_opts() ++ options acc = %{mentions: MapSet.new(), tags: MapSet.new()} - {text, %{mentions: mentions}} = Linkify.link_map(text, acc, options) - {text, tags} = extract_tags(text) + {text, %{mentions: mentions, tags: tags}} = Linkify.link_map(text, acc, options) {text, MapSet.to_list(mentions), MapSet.to_list(tags)} end @@ -157,46 +156,10 @@ defmodule Mobilizon.Service.Formatter do defp linkify_opts do Mobilizon.Config.get(__MODULE__) ++ [ - hashtag: false, + hashtag: true, + hashtag_handler: &__MODULE__.hashtag_handler/4, mention: true, mention_handler: &__MODULE__.mention_handler/4 ] end - - @match_hashtag ~r/(?:^|[^\p{L}\p{M}\p{Nd}\)])(?\#[[:word:]_]*[[:alpha:]_·][[:word:]_·\p{M}]*)/u - - @spec extract_tags(String.t()) :: {String.t(), MapSet.t()} - def extract_tags(text) do - matches = - @match_hashtag - |> Regex.scan(text, capture: [:tag]) - |> Enum.map(&hd/1) - |> Enum.map(&{&1, tag_text_strip(&1)}) - |> MapSet.new() - - text = - @match_hashtag - |> Regex.replace(text, &generate_tag_link/2) - |> String.trim() - - {text, matches} - end - - @spec generate_tag_link(String.t(), String.t()) :: String.t() - defp generate_tag_link(_, tag_text) do - tag = tag_text_strip(tag_text) - url = "#{Endpoint.url()}/tag/#{tag}" - - Tag.content_tag(:a, tag_text, - class: "hashtag", - "data-tag": tag, - href: url, - rel: "tag ugc" - ) - |> Phoenix.HTML.safe_to_string() - |> (&" #{&1}").() - end - - @spec tag_text_strip(String.t()) :: String.t() - defp tag_text_strip(tag), do: tag |> String.trim("#") |> String.downcase() end diff --git a/test/service/formatter/formatter_test.exs b/test/service/formatter/formatter_test.exs index 3a5451354..556ea8dfb 100644 --- a/test/service/formatter/formatter_test.exs +++ b/test/service/formatter/formatter_test.exs @@ -112,6 +112,20 @@ defmodule Mobilizon.Service.FormatterTest do "#{text}" assert {^expected, [], []} = Formatter.linkify(text) + + text = "https://example.org/#foobar" + + expected = + "#{text}" + + assert {^expected, [], []} = Formatter.linkify(text) + + text = "

An article tagged with a #tag.

" + + expected = + "

An article tagged with a #tag.

" + + assert {^expected, [], [{"#tag", "tag"}]} = Formatter.linkify(text) end end