Merge branch 'fix-hashtag-in-text' into 'master'
Extract tag parsing to own code, because linkify doesn't handle tag into HTML Closes #639 See merge request framasoft/mobilizon!871
This commit is contained in:
commit
eea9b9b35d
|
@ -66,7 +66,15 @@ defmodule Mobilizon.Service.Formatter do
|
||||||
def hashtag_handler("#" <> tag = tag_text, _buffer, _opts, acc) do
|
def hashtag_handler("#" <> tag = tag_text, _buffer, _opts, acc) do
|
||||||
tag = String.downcase(tag)
|
tag = String.downcase(tag)
|
||||||
url = "#{Endpoint.url()}/tag/#{tag}"
|
url = "#{Endpoint.url()}/tag/#{tag}"
|
||||||
link = "<a class='hashtag' data-tag='#{tag}' href='#{url}' rel='tag'>#{tag_text}</a>"
|
|
||||||
|
link =
|
||||||
|
Tag.content_tag(:a, tag_text,
|
||||||
|
class: "hashtag",
|
||||||
|
"data-tag": tag,
|
||||||
|
href: url,
|
||||||
|
rel: "tag ugc"
|
||||||
|
)
|
||||||
|
|> Phoenix.HTML.safe_to_string()
|
||||||
|
|
||||||
{link, %{acc | tags: MapSet.put(acc.tags, {tag_text, tag})}}
|
{link, %{acc | tags: MapSet.put(acc.tags, {tag_text, tag})}}
|
||||||
end
|
end
|
||||||
|
@ -81,7 +89,8 @@ defmodule Mobilizon.Service.Formatter do
|
||||||
options = linkify_opts() ++ options
|
options = linkify_opts() ++ options
|
||||||
|
|
||||||
acc = %{mentions: MapSet.new(), tags: MapSet.new()}
|
acc = %{mentions: MapSet.new(), tags: MapSet.new()}
|
||||||
{text, %{mentions: mentions, tags: tags}} = Linkify.link_map(text, acc, options)
|
{text, %{mentions: mentions}} = Linkify.link_map(text, acc, options)
|
||||||
|
{text, tags} = extract_tags(text)
|
||||||
|
|
||||||
{text, MapSet.to_list(mentions), MapSet.to_list(tags)}
|
{text, MapSet.to_list(mentions), MapSet.to_list(tags)}
|
||||||
end
|
end
|
||||||
|
@ -135,10 +144,45 @@ defmodule Mobilizon.Service.Formatter do
|
||||||
defp linkify_opts do
|
defp linkify_opts do
|
||||||
Mobilizon.Config.get(__MODULE__) ++
|
Mobilizon.Config.get(__MODULE__) ++
|
||||||
[
|
[
|
||||||
hashtag: true,
|
hashtag: false,
|
||||||
hashtag_handler: &__MODULE__.hashtag_handler/4,
|
|
||||||
mention: true,
|
mention: true,
|
||||||
mention_handler: &__MODULE__.mention_handler/4
|
mention_handler: &__MODULE__.mention_handler/4
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@match_hashtag ~r/(?:^|[^\p{L}\p{M}\p{Nd}\)])(?<tag>\#[[: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
|
||||||
|
|
||||||
|
defp tag_text_strip(tag), do: tag |> String.trim("#") |> String.downcase()
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,7 +13,7 @@ defmodule Mobilizon.Service.FormatterTest do
|
||||||
text = "I love #cofe and #2hu"
|
text = "I love #cofe and #2hu"
|
||||||
|
|
||||||
expected_text =
|
expected_text =
|
||||||
"I love <a class='hashtag' data-tag='cofe' href='http://mobilizon.test/tag/cofe' rel='tag'>#cofe</a> and <a class='hashtag' data-tag='2hu' href='http://mobilizon.test/tag/2hu' rel='tag'>#2hu</a>"
|
"I love <a class=\"hashtag\" data-tag=\"cofe\" href=\"http://mobilizon.test/tag/cofe\" rel=\"tag ugc\">#cofe</a> and <a class=\"hashtag\" data-tag=\"2hu\" href=\"http://mobilizon.test/tag/2hu\" rel=\"tag ugc\">#2hu</a>"
|
||||||
|
|
||||||
assert {^expected_text, [], _tags} = Formatter.linkify(text)
|
assert {^expected_text, [], _tags} = Formatter.linkify(text)
|
||||||
end
|
end
|
||||||
|
@ -22,7 +22,7 @@ defmodule Mobilizon.Service.FormatterTest do
|
||||||
text = "#fact_3: pleroma does what mastodon't"
|
text = "#fact_3: pleroma does what mastodon't"
|
||||||
|
|
||||||
expected_text =
|
expected_text =
|
||||||
"<a class='hashtag' data-tag='fact_3' href='http://mobilizon.test/tag/fact_3' rel='tag'>#fact_3</a>: pleroma does what mastodon't"
|
"<a class=\"hashtag\" data-tag=\"fact_3\" href=\"http://mobilizon.test/tag/fact_3\" rel=\"tag ugc\">#fact_3</a>: pleroma does what mastodon't"
|
||||||
|
|
||||||
assert {^expected_text, [], _tags} = Formatter.linkify(text)
|
assert {^expected_text, [], _tags} = Formatter.linkify(text)
|
||||||
end
|
end
|
||||||
|
@ -174,6 +174,12 @@ defmodule Mobilizon.Service.FormatterTest do
|
||||||
|
|
||||||
assert {_text, [], ^expected_tags} = Formatter.linkify(text)
|
assert {_text, [], ^expected_tags} = Formatter.linkify(text)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "parses tags in HTML" do
|
||||||
|
text = "<p><i>Hello #there</i></p>"
|
||||||
|
|
||||||
|
assert {_text, [], [{"#there", "there"}]} = Formatter.linkify(text)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it can parse mentions and return the relevant users" do
|
test "it can parse mentions and return the relevant users" do
|
||||||
|
|
Loading…
Reference in a new issue