X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fformatter.ex;h=19b9af46cc3bb48613c3e5e52b1d9f32f591c041;hb=791bcfd90f41da9d77ab5a5ad6eec22ae8050b8a;hp=8ea9dbd38f2eff4b5b23766a314f11cd23986838;hpb=fd45cab9eccecc835dde457d72ba38bd31c8f7f6;p=akkoma diff --git a/lib/pleroma/formatter.ex b/lib/pleroma/formatter.ex index 8ea9dbd38..19b9af46c 100644 --- a/lib/pleroma/formatter.ex +++ b/lib/pleroma/formatter.ex @@ -3,31 +3,40 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Formatter do - alias Pleroma.Emoji alias Pleroma.HTML alias Pleroma.User - alias Pleroma.Web.MediaProxy - @safe_mention_regex ~r/^(\s*(?@.+?\s+)+)(?.*)/ + @safe_mention_regex ~r/^(\s*(?(@.+?\s+){1,})+)(?.*)/s + @link_regex ~r"((?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~%:/?#[\]@!\$&'\(\)\*\+,;=.]+)|[0-9a-z+\-\.]+:[0-9a-z$-_.+!*'(),]+"ui @markdown_characters_regex ~r/(`|\*|_|{|}|[|]|\(|\)|#|\+|-|\.|!)/ - @link_regex ~r{((?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~%:/?#[\]@!\$&'\(\)\*\+,;=.]+)|[0-9a-z+\-\.]+:[0-9a-z$-_.+!*'(),]+}ui - # credo:disable-for-previous-line Credo.Check.Readability.MaxLineLength @auto_linker_config hashtag: true, hashtag_handler: &Pleroma.Formatter.hashtag_handler/4, mention: true, mention_handler: &Pleroma.Formatter.mention_handler/4 + def escape_mention_handler("@" <> nickname = mention, buffer, _, _) do + case User.get_cached_by_nickname(nickname) do + %User{} -> + # escape markdown characters with `\\` + # (we don't want something like @user__name to be parsed by markdown) + String.replace(mention, @markdown_characters_regex, "\\\\\\1") + + _ -> + buffer + end + end + def mention_handler("@" <> nickname, buffer, opts, acc) do case User.get_cached_by_nickname(nickname) do %User{id: id} = user -> ap_id = get_ap_id(user) - nickname_text = get_nickname_text(nickname, opts) |> maybe_escape(opts) + nickname_text = get_nickname_text(nickname, opts) link = - "@#{ + ~s(@#{ nickname_text - }" + }) {link, %{acc | mentions: MapSet.put(acc.mentions, {"@" <> nickname, user})}} @@ -39,7 +48,7 @@ defmodule Pleroma.Formatter do def hashtag_handler("#" <> tag = tag_text, _buffer, _opts, acc) do tag = String.downcase(tag) url = "#{Pleroma.Web.base_url()}/tag/#{tag}" - link = "" + link = ~s(#{tag_text}) {link, %{acc | tags: MapSet.put(acc.tags, {tag_text, tag})}} end @@ -70,42 +79,25 @@ defmodule Pleroma.Formatter do end end - def emojify(text) do - emojify(text, Emoji.get_all()) - end - - def emojify(text, nil), do: text - - def emojify(text, emoji, strip \\ false) do - Enum.reduce(emoji, text, fn emoji_data, text -> - emoji = HTML.strip_tags(elem(emoji_data, 0)) - file = HTML.strip_tags(elem(emoji_data, 1)) - - html = - if not strip do - "#{emoji}" - else - "" - end - - String.replace(text, ":#{emoji}:", html) |> HTML.filter_tags() - end) - end - - def demojify(text) do - emojify(text, Emoji.get_all(), true) - end - - def demojify(text, nil), do: text + @doc """ + Escapes a special characters in mention names. + """ + def mentions_escape(text, options \\ []) do + options = + Keyword.merge(options, + mention: true, + url: false, + mention_handler: &Pleroma.Formatter.escape_mention_handler/4 + ) - def get_emoji(text) when is_binary(text) do - Enum.filter(Emoji.get_all(), fn {emoji, _, _} -> String.contains?(text, ":#{emoji}:") end) + if options[:safe_mention] && Regex.named_captures(@safe_mention_regex, text) do + %{"mentions" => mentions, "rest" => rest} = Regex.named_captures(@safe_mention_regex, text) + AutoLinker.link(mentions, options) <> AutoLinker.link(rest, options) + else + AutoLinker.link(text, options) + end end - def get_emoji(_), do: [] - def html_escape({text, mentions, hashtags}, type) do {html_escape(text, type), mentions, hashtags} end @@ -135,15 +127,9 @@ defmodule Pleroma.Formatter do end end - defp get_ap_id(%User{info: %{source_data: %{"url" => url}}}) when is_binary(url), do: url + defp get_ap_id(%User{source_data: %{"url" => url}}) when is_binary(url), do: url defp get_ap_id(%User{ap_id: ap_id}), do: ap_id defp get_nickname_text(nickname, %{mentions_format: :full}), do: User.full_nickname(nickname) defp get_nickname_text(nickname, _), do: User.local_nickname(nickname) - - defp maybe_escape(str, %{mentions_escape: true}) do - String.replace(str, @markdown_characters_regex, "\\\\\\1") - end - - defp maybe_escape(str, _), do: str end