Merge pull request 'Manually define PATH for Arch Linux users in systemd unit' (...
[akkoma] / lib / pleroma / formatter.ex
index 02a93a8dc2989e68af9594ad549ba7145c02f2a8..575bf9b2dcb20d3bc0ded04ea0abdb406cb6d0f1 100644 (file)
@@ -1,5 +1,5 @@
 # Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Formatter do
@@ -10,11 +10,15 @@ defmodule Pleroma.Formatter do
   @link_regex ~r"((?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~%:/?#[\]@!\$&'\(\)\*\+,;=.]+)|[0-9a-z+\-\.]+:[0-9a-z$-_.+!*'(),]+"ui
   @markdown_characters_regex ~r/(`|\*|_|{|}|[|]|\(|\)|#|\+|-|\.|!)/
 
-  @auto_linker_config hashtag: true,
-                      hashtag_handler: &Pleroma.Formatter.hashtag_handler/4,
-                      mention: true,
-                      mention_handler: &Pleroma.Formatter.mention_handler/4,
-                      scheme: true
+  defp linkify_opts do
+    Pleroma.Config.get(Pleroma.Formatter) ++
+      [
+        hashtag: true,
+        hashtag_handler: &Pleroma.Formatter.hashtag_handler/4,
+        mention: true,
+        mention_handler: &Pleroma.Formatter.mention_handler/4
+      ]
+  end
 
   def escape_mention_handler("@" <> nickname = mention, buffer, _, _) do
     case User.get_cached_by_nickname(nickname) do
@@ -28,26 +32,29 @@ defmodule Pleroma.Formatter do
     end
   end
 
+  def mention_tag(%User{id: id} = user, nickname, opts \\ []) do
+    user_url = user.uri || user.ap_id
+    nickname_text = get_nickname_text(nickname, opts)
+
+    :span
+    |> Phoenix.HTML.Tag.content_tag(
+      Phoenix.HTML.Tag.content_tag(
+        :a,
+        ["@", Phoenix.HTML.Tag.content_tag(:span, nickname_text)],
+        "data-user": id,
+        class: "u-url mention",
+        href: user_url,
+        rel: "ugc"
+      ),
+      class: "h-card"
+    )
+    |> Phoenix.HTML.safe_to_string()
+  end
+
   def mention_handler("@" <> nickname, buffer, opts, acc) do
     case User.get_cached_by_nickname(nickname) do
-      %User{id: id} = user ->
-        user_url = user.uri || user.ap_id
-        nickname_text = get_nickname_text(nickname, opts)
-
-        link =
-          Phoenix.HTML.Tag.content_tag(
-            :span,
-            Phoenix.HTML.Tag.content_tag(
-              :a,
-              ["@", Phoenix.HTML.Tag.content_tag(:span, nickname_text)],
-              "data-user": id,
-              class: "u-url mention",
-              href: user_url,
-              rel: "ugc"
-            ),
-            class: "h-card"
-          )
-          |> Phoenix.HTML.safe_to_string()
+      %User{id: _id} = user ->
+        link = mention_tag(user, nickname, opts)
 
         {link, %{acc | mentions: MapSet.put(acc.mentions, {"@" <> nickname, user})}}
 
@@ -58,7 +65,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}"
+    url = "#{Pleroma.Web.Endpoint.url()}/tag/#{tag}"
 
     link =
       Phoenix.HTML.Tag.content_tag(:a, tag_text,
@@ -80,19 +87,19 @@ defmodule Pleroma.Formatter do
   @spec linkify(String.t(), keyword()) ::
           {String.t(), [{String.t(), User.t()}], [{String.t(), String.t()}]}
   def linkify(text, options \\ []) do
-    options = options ++ @auto_linker_config
+    options = linkify_opts() ++ options
 
     if options[:safe_mention] && Regex.named_captures(@safe_mention_regex, text) do
       %{"mentions" => mentions, "rest" => rest} = Regex.named_captures(@safe_mention_regex, text)
       acc = %{mentions: MapSet.new(), tags: MapSet.new()}
 
-      {text_mentions, %{mentions: mentions}} = AutoLinker.link_map(mentions, acc, options)
-      {text_rest, %{tags: tags}} = AutoLinker.link_map(rest, acc, options)
+      {text_mentions, %{mentions: mentions}} = Linkify.link_map(mentions, acc, options)
+      {text_rest, %{tags: tags}} = Linkify.link_map(rest, acc, options)
 
       {text_mentions <> text_rest, MapSet.to_list(mentions), MapSet.to_list(tags)}
     else
       acc = %{mentions: MapSet.new(), tags: MapSet.new()}
-      {text, %{mentions: mentions, tags: tags}} = AutoLinker.link_map(text, acc, options)
+      {text, %{mentions: mentions, tags: tags}} = Linkify.link_map(text, acc, options)
 
       {text, MapSet.to_list(mentions), MapSet.to_list(tags)}
     end
@@ -111,12 +118,16 @@ defmodule Pleroma.Formatter do
 
     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)
+      Linkify.link(mentions, options) <> Linkify.link(rest, options)
     else
-      AutoLinker.link(text, options)
+      Linkify.link(text, options)
     end
   end
 
+  def markdown_to_html(text) do
+    Earmark.as_html!(text, %Earmark.Options{compact_output: true})
+  end
+
   def html_escape({text, mentions, hashtags}, type) do
     {html_escape(text, type), mentions, hashtags}
   end
@@ -125,6 +136,11 @@ defmodule Pleroma.Formatter do
     HTML.filter_tags(text)
   end
 
+  def html_escape(text, "text/x.misskeymarkdown") do
+    text
+    |> HTML.filter_tags()
+  end
+
   def html_escape(text, "text/plain") do
     Regex.split(@link_regex, text, include_captures: true)
     |> Enum.map_every(2, fn chunk ->