diff --git a/lib/philomena/markdown.ex b/lib/philomena/markdown.ex index cc609f94..a4f3cfa7 100644 --- a/lib/philomena/markdown.ex +++ b/lib/philomena/markdown.ex @@ -3,7 +3,9 @@ defmodule Philomena.Markdown do # When your NIF is loaded, it will override this function. def to_html(text, replacements), do: Philomena.Native.markdown_to_html(text, replacements) - def to_html_unsafe(text, replacements), do: Philomena.Native.markdown_to_html_unsafe(text, replacements) + + def to_html_unsafe(text, replacements), + do: Philomena.Native.markdown_to_html_unsafe(text, replacements) def escape_markdown(text) do @markdown_chars diff --git a/lib/philomena/textile/lexer.ex b/lib/philomena/textile/lexer.ex index f6b2cef7..7fe65347 100644 --- a/lib/philomena/textile/lexer.ex +++ b/lib/philomena/textile/lexer.ex @@ -2,9 +2,9 @@ defmodule Philomena.Textile.Lexer do import NimbleParsec token_list = - Enum.to_list(0x01..0x29) - ++ Enum.to_list(0x2b..0x2f) - ++ ':;<=>?[]\\^`~|' + Enum.to_list(0x01..0x29) ++ + Enum.to_list(0x2B..0x2F) ++ + ':;<=>?[]\\^`~|' space_list = '\f \r\t\u00a0\u1680\u180e\u202f\u205f\u3000' ++ Enum.to_list(0x2000..0x200A) space = utf8_char(space_list) diff --git a/lib/philomena/textile/parser_markdown.ex b/lib/philomena/textile/parser_markdown.ex index 40731ab9..6d4854fa 100644 --- a/lib/philomena/textile/parser_markdown.ex +++ b/lib/philomena/textile/parser_markdown.ex @@ -87,21 +87,44 @@ defmodule Philomena.Textile.ParserMarkdown do # # open_token callback* close_token # - defp simple_recursive(:bq_open, :bq_close, open_tag, close_tag, callback, parser, [ - {:bq_open, open} | r_tokens - ], level) do + defp simple_recursive( + :bq_open, + :bq_close, + open_tag, + close_tag, + callback, + parser, + [ + {:bq_open, open} | r_tokens + ], + level + ) do case repeat(callback, parser, r_tokens, true, level) do {:ok, tree, [{:bq_close, _} | r2_tokens], level} -> - {:ok, [{:markup, "\n" <> String.duplicate(open_tag, level)}, tree, {:markup, "\n" <> String.duplicate(close_tag, level - 1)}], r2_tokens} + {:ok, + [ + {:markup, "\n" <> String.duplicate(open_tag, level)}, + tree, + {:markup, "\n" <> String.duplicate(close_tag, level - 1)} + ], r2_tokens} {:ok, tree, r2_tokens, level} -> {:ok, [{:text, open}, tree], r2_tokens} end end - defp simple_recursive(open_token, close_token, open_tag, close_tag, callback, parser, [ - {open_token, open} | r_tokens - ], level) do + defp simple_recursive( + open_token, + close_token, + open_tag, + close_tag, + callback, + parser, + [ + {open_token, open} | r_tokens + ], + level + ) do case repeat(callback, parser, r_tokens, false, level) do {:ok, tree, [{^close_token, _} | r2_tokens]} -> {:ok, [{:markup, open_tag}, tree, {:markup, close_tag}], r2_tokens} @@ -152,8 +175,7 @@ defmodule Philomena.Textile.ParserMarkdown do _ -> case repeat(callback, put_state(parser, state), r_tokens, false, level) do {:ok, tree, [{^close_token, close}, {^lookahead_not, ln} | r2_tokens]} -> - {:ok, [{:text, open}, tree, {:text, close}], - [{lookahead_not, ln} | r2_tokens]} + {:ok, [{:text, open}, tree, {:text, close}], [{lookahead_not, ln} | r2_tokens]} {:ok, tree, [{^close_token, _} | r2_tokens]} -> {:ok, [{:markup, open_tag}, tree, {:markup, close_tag}], r2_tokens} @@ -261,9 +283,7 @@ defmodule Philomena.Textile.ParserMarkdown do {:ok, tree, [{:unbracketed_link_url, <<"\":", url::binary>>} | r2_tokens]} -> href = url - {:ok, - [{:markup, "["}, tree, {:markup, "]("}, {:markup, href}, {:markup, ")"}], - r2_tokens} + {:ok, [{:markup, "["}, tree, {:markup, "]("}, {:markup, href}, {:markup, ")"}], r2_tokens} {:ok, tree, r2_tokens} -> {:ok, [{:text, open}, tree], r2_tokens} @@ -275,19 +295,21 @@ defmodule Philomena.Textile.ParserMarkdown do {:ok, tree, [{:bracketed_link_url, <<"\":", url::binary>>} | r2_tokens]} -> href = url - {:ok, - [{:markup, "["}, tree, {:markup, "]("}, {:markup, href}, {:markup, ")"}], - r2_tokens} + {:ok, [{:markup, "["}, tree, {:markup, "]("}, {:markup, href}, {:markup, ")"}], r2_tokens} {:ok, tree, r2_tokens} -> {:ok, [{:text, open}, tree], r2_tokens} end end - defp inner_inline_textile_element(parser, [ - {token, img}, - {:unbracketed_image_url, <<":", url::binary>>} | r_tokens - ], level) + defp inner_inline_textile_element( + parser, + [ + {token, img}, + {:unbracketed_image_url, <<":", url::binary>>} | r_tokens + ], + level + ) when token in [:unbracketed_image, :bracketed_image] do img = parser.image_transform.(img) @@ -372,8 +394,7 @@ defmodule Philomena.Textile.ParserMarkdown do # defp inline_textile_element_not_opening_markup(_parser, [{:literal, lit} | r_tokens], level) do - {:ok, [{:markup, Markdown.escape_markdown(lit)},], - r_tokens} + {:ok, [{:markup, Markdown.escape_markdown(lit)}], r_tokens} end defp inline_textile_element_not_opening_markup(_parser, [{:space, _} | r_tokens], level) do @@ -385,11 +406,15 @@ defmodule Philomena.Textile.ParserMarkdown do {:ok, [{:text, binary}], r2_tokens} end - defp inline_textile_element_not_opening_markup(_parser, [ - {:quicktxt, q1}, - {token, t}, - {:quicktxt, q2} | r_tokens - ], level) + defp inline_textile_element_not_opening_markup( + _parser, + [ + {:quicktxt, q1}, + {token, t}, + {:quicktxt, q2} | r_tokens + ], + level + ) when token in [ :b_delim, :i_delim, @@ -400,15 +425,18 @@ defmodule Philomena.Textile.ParserMarkdown do :del_delim, :sub_delim ] do - {:ok, [{:text, <>}, {:text, t}, {:text, <>}], - r_tokens} + {:ok, [{:text, <>}, {:text, t}, {:text, <>}], r_tokens} end defp inline_textile_element_not_opening_markup(_parser, [{:quicktxt, lit} | r_tokens], level) do {:ok, [{:text, <>}], r_tokens} end - defp inline_textile_element_not_opening_markup(parser, [{:bq_cite_start, start} | r_tokens], level) do + defp inline_textile_element_not_opening_markup( + parser, + [{:bq_cite_start, start} | r_tokens], + level + ) do case repeat(&bq_cite_text/3, parser, r_tokens, false, level) do {:ok, tree, [{:bq_cite_open, open} | r2_tokens]} -> case repeat(&block_textile_element/4, parser, r2_tokens, true, level + 1) do @@ -437,7 +465,11 @@ defmodule Philomena.Textile.ParserMarkdown do end end - defp inline_textile_element_not_opening_markup(_parser, [{:bq_cite_open, tok} | r_tokens], level) do + defp inline_textile_element_not_opening_markup( + _parser, + [{:bq_cite_open, tok} | r_tokens], + level + ) do {:ok, [{:text, tok}], r_tokens} end @@ -495,7 +527,8 @@ defmodule Philomena.Textile.ParserMarkdown do # double_newline | newline | inline_textile_element; # - defp block_textile_element(_parser, [{:double_newline, _} | r_tokens], bq, level) when bq == true do + defp block_textile_element(_parser, [{:double_newline, _} | r_tokens], bq, level) + when bq == true do one = "\n" <> String.duplicate("> ", level) {:ok, [{:markup, String.duplicate(one, 2)}], r_tokens} end diff --git a/lib/philomena_web/controllers/image/description_controller.ex b/lib/philomena_web/controllers/image/description_controller.ex index 7e508567..55c8191a 100644 --- a/lib/philomena_web/controllers/image/description_controller.ex +++ b/lib/philomena_web/controllers/image/description_controller.ex @@ -34,7 +34,8 @@ defmodule PhilomenaWeb.Image.DescriptionController do Images.reindex_image(image) - body = TextRenderer.render_one(%{body: image.description, body_md: image.description_md}, conn) + body = + TextRenderer.render_one(%{body: image.description, body_md: image.description_md}, conn) conn |> put_view(PhilomenaWeb.ImageView) diff --git a/lib/philomena_web/controllers/profile_controller.ex b/lib/philomena_web/controllers/profile_controller.ex index b0cb6a2d..9d35f491 100644 --- a/lib/philomena_web/controllers/profile_controller.ex +++ b/lib/philomena_web/controllers/profile_controller.ex @@ -134,9 +134,11 @@ defmodule PhilomenaWeb.ProfileController do |> TextRenderer.render_collection(conn) |> Enum.zip(recent_comments) - about_me = TextRenderer.render_one(%{body_md: user.description_md, body: user.description || ""}, conn) + about_me = + TextRenderer.render_one(%{body_md: user.description_md, body: user.description || ""}, conn) - scratchpad = TextRenderer.render_one(%{body_md: user.scratchpad_md, body: user.scratchpad || ""}, conn) + scratchpad = + TextRenderer.render_one(%{body_md: user.scratchpad_md, body: user.scratchpad || ""}, conn) commission_information = commission_info(user.commission, conn) @@ -214,8 +216,9 @@ defmodule PhilomenaWeb.ProfileController do defp map_fetch(nil, _field_name), do: nil defp map_fetch(map, field_name), do: Map.get(map, field_name) - defp commission_info(%{information: info, information_md: info_md}, conn) when info not in [nil, ""], - do: TextRenderer.render_one(%{body: info, body_md: info_md}, conn) + defp commission_info(%{information: info, information_md: info_md}, conn) + when info not in [nil, ""], + do: TextRenderer.render_one(%{body: info, body_md: info_md}, conn) defp commission_info(_commission, _conn), do: "" diff --git a/lib/philomena_web/controllers/tag_controller.ex b/lib/philomena_web/controllers/tag_controller.ex index ee4c6f3b..5713c61b 100644 --- a/lib/philomena_web/controllers/tag_controller.ex +++ b/lib/philomena_web/controllers/tag_controller.ex @@ -61,7 +61,8 @@ defmodule PhilomenaWeb.TagController do interactions = Interactions.user_interactions(images, user) - body = TextRenderer.render_one(%{body_md: tag.description_md, body: tag.description || ""}, conn) + body = + TextRenderer.render_one(%{body_md: tag.description_md, body: tag.description || ""}, conn) dnp_bodies = TextRenderer.render_collection( diff --git a/lib/philomena_web/image_loader.ex b/lib/philomena_web/image_loader.ex index 914404e6..86b0c3b9 100644 --- a/lib/philomena_web/image_loader.ex +++ b/lib/philomena_web/image_loader.ex @@ -139,7 +139,8 @@ defmodule PhilomenaWeb.ImageLoader do dnp_entries = Enum.zip(dnp_bodies, tag.dnp_entries) - description = TextRenderer.render_one(%{body_md: tag.description_md, body: tag.description || ""}, conn) + description = + TextRenderer.render_one(%{body_md: tag.description_md, body: tag.description || ""}, conn) [{tag, description, dnp_entries}] end diff --git a/lib/philomena_web/markdown_renderer.ex b/lib/philomena_web/markdown_renderer.ex index 4ec85c6f..bf4259db 100644 --- a/lib/philomena_web/markdown_renderer.ex +++ b/lib/philomena_web/markdown_renderer.ex @@ -17,7 +17,9 @@ defmodule PhilomenaWeb.MarkdownRenderer do defp find_images(text) do Regex.scan(~r/>>(\d+)([tsp])?/, text, capture: :all_but_first) - |> Enum.map(fn matches -> [Enum.at(matches, 0) |> String.to_integer(), Enum.at(matches, 1) || ""] end) + |> Enum.map(fn matches -> + [Enum.at(matches, 0) |> String.to_integer(), Enum.at(matches, 1) || ""] + end) |> Enum.filter(fn m -> Enum.at(m, 0) < 2_147_483_647 end) end @@ -52,42 +54,50 @@ defmodule PhilomenaWeb.MarkdownRenderer do img = loaded_images[Enum.at(group, 0)] text = "#{Enum.at(group, 0)}#{Enum.at(group, 1)}" - rendered = cond do - img != nil -> - case group do - [_id, "p"] when not img.hidden_from_users -> - Phoenix.View.render(@image_view, "_image_target.html", - image: img, - size: :medium, - conn: conn - ) - |> safe_to_string() - [_id, "t"] when not img.hidden_from_users -> - Phoenix.View.render(@image_view, "_image_target.html", - image: img, - size: :small, - conn: conn - ) - |> safe_to_string() - [_id, "s"] when not img.hidden_from_users -> - Phoenix.View.render(@image_view, "_image_target.html", - image: img, - size: :thumb_small, - conn: conn - ) - |> safe_to_string() - [_id, ""] -> - link(">>#{img.id}#{link_suffix(img)}", to: "/images/#{img.id}") - |> safe_to_string() - [_id, suffix] when suffix in ["t", "s", "p"] -> - link(">>#{img.id}#{suffix}#{link_suffix(img)}", to: "/images/#{img.id}") - |> safe_to_string() - [id, suffix] -> # This condition should never trigger, but let's leave it here just in case. - ">>#{id}#{suffix}" - end - true -> - ">>#{text}" - end + rendered = + cond do + img != nil -> + case group do + [_id, "p"] when not img.hidden_from_users -> + Phoenix.View.render(@image_view, "_image_target.html", + image: img, + size: :medium, + conn: conn + ) + |> safe_to_string() + + [_id, "t"] when not img.hidden_from_users -> + Phoenix.View.render(@image_view, "_image_target.html", + image: img, + size: :small, + conn: conn + ) + |> safe_to_string() + + [_id, "s"] when not img.hidden_from_users -> + Phoenix.View.render(@image_view, "_image_target.html", + image: img, + size: :thumb_small, + conn: conn + ) + |> safe_to_string() + + [_id, ""] -> + link(">>#{img.id}#{link_suffix(img)}", to: "/images/#{img.id}") + |> safe_to_string() + + [_id, suffix] when suffix in ["t", "s", "p"] -> + link(">>#{img.id}#{suffix}#{link_suffix(img)}", to: "/images/#{img.id}") + |> safe_to_string() + + # This condition should never trigger, but let's leave it here just in case. + [id, suffix] -> + ">>#{id}#{suffix}" + end + + true -> + ">>#{text}" + end [text, rendered] end) diff --git a/lib/philomena_web/textile_renderer.ex b/lib/philomena_web/textile_renderer.ex index 50870dfd..b3e465c6 100644 --- a/lib/philomena_web/textile_renderer.ex +++ b/lib/philomena_web/textile_renderer.ex @@ -12,7 +12,7 @@ defmodule PhilomenaWeb.TextileRenderer do def render(text, conn) do opts = %{image_transform: &Camo.Image.image_url/1} parsed = Parser.parse(opts, text) - + images = parsed |> Enum.flat_map(fn diff --git a/lib/philomena_web/views/error_view.ex b/lib/philomena_web/views/error_view.ex index 0e7cc087..1439cf87 100644 --- a/lib/philomena_web/views/error_view.ex +++ b/lib/philomena_web/views/error_view.ex @@ -1,17 +1,18 @@ defmodule PhilomenaWeb.ErrorView do use PhilomenaWeb, :view - import PhilomenaWeb.LayoutView, only: [ - stylesheet_path: 2, - dark_stylesheet_path: 1, - viewport_meta_tag: 1 - ] + import PhilomenaWeb.LayoutView, + only: [ + stylesheet_path: 2, + dark_stylesheet_path: 1, + viewport_meta_tag: 1 + ] @codes %{ 400 => {"Bad Request", "Couldn't process your request!"}, 403 => {"Forbidden", "Not allowed to access this page (are your cookies enabled?)"}, 404 => {"Not Found", "Couldn't find what you were looking for!"}, - 500 => {"Internal Error", "Couldn't process your request!"}, + 500 => {"Internal Error", "Couldn't process your request!"} } # By default, Phoenix returns the status message from diff --git a/native/philomena/src/markdown.rs b/native/philomena/src/markdown.rs index ff2cf0d2..b6345cba 100644 --- a/native/philomena/src/markdown.rs +++ b/native/philomena/src/markdown.rs @@ -15,7 +15,7 @@ fn common_options() -> ComrakOptions { options.render.hardbreaks = true; options.render.github_pre_lang = true; - options.extension.camoifier = Some(|s| camo::image_url(s).unwrap_or(String::from(""))); + options.extension.camoifier = Some(|s| camo::image_url(s).unwrap_or_else(|| String::from(""))); options } diff --git a/priv/repo/migrations/20210912171343_add_markdown_columns.exs b/priv/repo/migrations/20210912171343_add_markdown_columns.exs index 21267871..45961854 100644 --- a/priv/repo/migrations/20210912171343_add_markdown_columns.exs +++ b/priv/repo/migrations/20210912171343_add_markdown_columns.exs @@ -5,7 +5,7 @@ defmodule Philomena.Repo.Migrations.AddMarkdownColumns do alter table("comments") do add :body_md, :varchar, default: nil end - + alter table("messages") do add :body_md, :varchar, default: nil end @@ -75,7 +75,7 @@ defmodule Philomena.Repo.Migrations.AddMarkdownColumns do alter table("comments") do remove :body_md end - + alter table("messages") do remove :body_md end