Render markdown to html for notifications

This commit is contained in:
Benjamin Neff 2022-07-13 05:05:58 +02:00
parent 3c02a1f067
commit dd3bc39c97
No known key found for this signature in database
GPG key ID: 971464C3F1A90194
12 changed files with 62 additions and 50 deletions

View file

@ -4,17 +4,19 @@ module NotifierHelper
include PostsHelper include PostsHelper
# @param post [Post] The post object. # @param post [Post] The post object.
# @param opts [Hash] Optional hash. Accepts :length parameters. # @param opts [Hash] Optional hash. Accepts :html parameter.
# @return [String] The formatted post. # @return [String] The formatted post.
def post_message(post, opts={}) def post_message(post, opts={})
post.message&.plain_text_without_markdown.presence || post_page_title(post) rendered = opts[:html] ? post.message&.markdownified_for_mail : post.message&.plain_text_without_markdown
rendered.presence || post_page_title(post)
end end
# @param comment [Comment] The comment to process. # @param comment [Comment] The comment to process.
# @param opts [Hash] Optional hash. Accepts :html parameter.
# @return [String] The formatted comment. # @return [String] The formatted comment.
def comment_message(comment, opts={}) def comment_message(comment, opts={})
if comment.post.public? if comment.post.public?
comment.message.plain_text_without_markdown opts[:html] ? comment.message.markdownified_for_mail : comment.message.plain_text_without_markdown
else else
I18n.translate "notifier.a_limited_post_comment" I18n.translate "notifier.a_limited_post_comment"
end end

View file

@ -1,5 +1,4 @@
%p = comment_message(@notification.comment, html: true)
= comment_message(@notification.comment, process_newlines: true)
%p %p
= link_to t("notifier.comment_on_post.reply", name: @notification.comment.post.author_first_name), = link_to t("notifier.comment_on_post.reply", name: @notification.comment.post.author_first_name),
post_url(@notification.comment.post, anchor: @notification.comment.guid) post_url(@notification.comment.post, anchor: @notification.comment.guid)

View file

@ -1,5 +1,4 @@
%p = comment_message(@notification.comment, html: true)
= comment_message(@notification.comment, process_newlines: true)
%p %p
= link_to t("notifier.comment_on_post.reply", name: @notification.comment.post.author_first_name), = link_to t("notifier.comment_on_post.reply", name: @notification.comment.post.author_first_name),
post_url(@notification.comment.post, anchor: @notification.comment.guid) post_url(@notification.comment.post, anchor: @notification.comment.guid)

View file

@ -1,8 +1,7 @@
- if @notification.like_target.public? - if @notification.like_target.public?
%p %p
#{t('.liked', name: @notification.sender_name)}: #{t('.liked', name: @notification.sender_name)}:
%p = post_message(@notification.like_target, html: true)
= post_message(@notification.like_target, process_newlines: true)
- else - else
%p %p
#{t('notifier.liked.limited_post', name: @notification.sender_name)}. #{t('notifier.liked.limited_post', name: @notification.sender_name)}.

View file

@ -1,6 +1,5 @@
- if @notification.post.public? - if @notification.post.public?
%p = post_message(@notification.post, html: true)
= post_message(@notification.post, process_newlines: true)
- else - else
%p %p
= t("notifier.mentioned.limited_post") = t("notifier.mentioned.limited_post")

View file

@ -1,6 +1,5 @@
- if @notification.comment.public? - if @notification.comment.public?
%p = @notification.comment.message.markdownified_for_mail
= @notification.comment.message.plain_text_without_markdown
- else - else
%p %p
= t("notifier.mentioned_in_comment.limited_post") = t("notifier.mentioned_in_comment.limited_post")

View file

@ -1,6 +1,5 @@
%p %p
#{t('.reshared', name: @notification.sender_name)}: #{t('.reshared', name: @notification.sender_name)}:
%p = post_message(@notification.reshare_root, html: true)
= post_message(@notification.reshare_root, process_newlines: true)
%p %p
= link_to t(".view_post"), post_url(@notification.reshare) = link_to t(".view_post"), post_url(@notification.reshare)

View file

@ -54,8 +54,9 @@ module Diaspora::Mentionable
# #
# @param [String] message text # @param [String] message text
# @param [Array] allowed_people ids of people that are allowed to stay # @param [Array] allowed_people ids of people that are allowed to stay
# @param [Boolean] absolute_links (false) render mentions with absolute links
# @return [String] message text with filtered mentions # @return [String] message text with filtered mentions
def self.filter_people(msg_text, allowed_people) def self.filter_people(msg_text, allowed_people, absolute_links: false)
mentioned_ppl = people_from_string(msg_text) mentioned_ppl = people_from_string(msg_text)
msg_text.to_s.gsub(REGEX) {|match_str| msg_text.to_s.gsub(REGEX) {|match_str|
@ -65,7 +66,7 @@ module Diaspora::Mentionable
if person && allowed_people.include?(person.id) if person && allowed_people.include?(person.id)
match_str match_str
else else
"@#{MentionsInternal.profile_link(person, name, diaspora_id)}" "@#{MentionsInternal.profile_link(person, name, diaspora_id, absolute: absolute_links)}"
end end
} }
end end
@ -121,11 +122,14 @@ module Diaspora::Mentionable
# #
# @param [Person] AR Person # @param [Person] AR Person
# @param [String] display name # @param [String] display name
# @param [String] diaspora_id
# @param [Boolean] absolute (false) render absolute link
# @return [String] markdown person link # @return [String] markdown person link
def self.profile_link(person, display_name, diaspora_id) def self.profile_link(person, display_name, diaspora_id, absolute: false)
return display_name || diaspora_id unless person.present? return display_name || diaspora_id unless person.present?
"[#{display_name || person.name}](#{Rails.application.routes.url_helpers.person_path(person)})" url_helper = Rails.application.routes.url_helpers
"[#{display_name || person.name}](#{absolute ? url_helper.person_url(person) : url_helper.person_path(person)})"
end end
end end
end end

View file

@ -56,8 +56,8 @@ module Diaspora
@message = renderer.render(message).strip @message = renderer.render(message).strip
end end
def markdownify def markdownify(renderer_class=Diaspora::Markdownify::HTML)
renderer = Diaspora::Markdownify::HTML.new options[:markdown_render_options] renderer = renderer_class.new options[:markdown_render_options]
markdown = Redcarpet::Markdown.new renderer, options[:markdown_options] markdown = Redcarpet::Markdown.new renderer, options[:markdown_options]
@message = markdown.render message @message = markdown.render message
@ -76,8 +76,8 @@ module Diaspora
@message = Diaspora::Mentionable.format message, options[:mentioned_people] @message = Diaspora::Mentionable.format message, options[:mentioned_people]
end end
if options[:disable_hovercards] || options[:link_all_mentions] if options[:disable_hovercards]
@message = Diaspora::Mentionable.filter_people message, [] @message = Diaspora::Mentionable.filter_people(message, [], absolute_links: true)
else else
make_mentions_plain_text make_mentions_plain_text
end end
@ -108,7 +108,6 @@ module Diaspora
end end
DEFAULTS = {mentioned_people: [], DEFAULTS = {mentioned_people: [],
link_all_mentions: false,
disable_hovercards: false, disable_hovercards: false,
truncate: false, truncate: false,
append: nil, append: nil,
@ -137,12 +136,8 @@ module Diaspora
# @param [Hash] opts Global options affecting output # @param [Hash] opts Global options affecting output
# @option opts [Array<Person>] :mentioned_people ([]) List of people # @option opts [Array<Person>] :mentioned_people ([]) List of people
# allowed to mention # allowed to mention
# @option opts [Boolean] :link_all_mentions (false) Whether to link
# all mentions. This makes plain links to profiles for people not in
# :mentioned_people
# @option opts [Boolean] :disable_hovercards (true) Render all mentions # @option opts [Boolean] :disable_hovercards (true) Render all mentions
# as profile links. This implies :link_all_mentions and ignores # as absolute profile links. This ignores :mentioned_people
# :mentioned_people
# @option opts [#to_i, Boolean] :truncate (false) Truncate message to # @option opts [#to_i, Boolean] :truncate (false) Truncate message to
# the specified length # the specified length
# @option opts [String] :append (nil) Append text to the end of # @option opts [String] :append (nil) Append text to the end of
@ -205,7 +200,7 @@ module Diaspora
render_tags render_tags
squish squish
append_and_truncate append_and_truncate
}.html_safe }.html_safe # rubocop:disable Rails/OutputSafety
end end
# @param [Hash] opts Override global output options, see {#initialize} # @param [Hash] opts Override global output options, see {#initialize}
@ -220,7 +215,20 @@ module Diaspora
render_tags render_tags
squish squish
append_and_truncate append_and_truncate
}.html_safe }.html_safe # rubocop:disable Rails/OutputSafety
end
def markdownified_for_mail
process(disable_hovercards: true) {
process_newlines
normalize
diaspora_links
camo_urls if AppConfig.privacy.camo.proxy_markdown_images?
render_mentions
markdownify(Diaspora::Markdownify::Email)
squish
append_and_truncate
}.html_safe # rubocop:disable Rails/OutputSafety
end end
# Get a short summary of the message # Get a short summary of the message

View file

@ -5,18 +5,23 @@
# the COPYRIGHT file. # the COPYRIGHT file.
describe NotifierHelper, :type => :helper do describe NotifierHelper, :type => :helper do
describe '#post_message' do describe "#post_message" do
before do before do
# post for markdown test # post for markdown test
@markdown_post = FactoryGirl.create(:status_message, @markdown_post = FactoryGirl.create(:status_message,
text: "[link](http://diasporafoundation.org) **bold text** *other text*", public: true) text: "[link](https://diasporafoundation.org) **bold text** *other text*",
@striped_markdown_post = "link (http://diasporafoundation.org) bold text other text" public: true)
@striped_markdown_post = "link (https://diasporafoundation.org) bold text other text"
end end
it 'strip markdown in the post' do it "strip markdown in the post" do
expect(post_message(@markdown_post)).to eq(@striped_markdown_post) expect(post_message(@markdown_post)).to eq(@striped_markdown_post)
end end
it "renders markdown as html" do
expect(post_message(@markdown_post, html: true)).to include("<a href=\"https://diasporafoundation.org\">link</a>")
end
it "falls back to the title if the post has no text" do it "falls back to the title if the post has no text" do
photo = FactoryGirl.build(:photo, public: true) photo = FactoryGirl.build(:photo, public: true)
photo_post = FactoryGirl.build(:status_message, author: photo.author, text: "", photos: [photo], public: true) photo_post = FactoryGirl.build(:status_message, author: photo.author, text: "", photos: [photo], public: true)
@ -32,13 +37,13 @@ describe NotifierHelper, :type => :helper do
end end
end end
describe '#comment_message' do describe "#comment_message" do
before do before do
# comment for markdown test # comment for markdown test
@markdown_comment = FactoryGirl.create(:comment) @markdown_comment = FactoryGirl.create(:comment)
@markdown_comment.post.public = true @markdown_comment.post.public = true
@markdown_comment.text = "[link](http://diasporafoundation.org) **bold text** *other text*" @markdown_comment.text = "[link](https://diasporafoundation.org) **bold text** *other text*"
@striped_markdown_comment = "link (http://diasporafoundation.org) bold text other text" @striped_markdown_comment = "link (https://diasporafoundation.org) bold text other text"
# comment for limited post # comment for limited post
@limited_comment = FactoryGirl.create(:comment) @limited_comment = FactoryGirl.create(:comment)
@ -46,11 +51,16 @@ describe NotifierHelper, :type => :helper do
@limited_comment.text = "This is top secret comment. Shhhhhhhh!!!" @limited_comment.text = "This is top secret comment. Shhhhhhhh!!!"
end end
it 'strip markdown in the comment' do it "strip markdown in the comment" do
expect(comment_message(@markdown_comment)).to eq(@striped_markdown_comment) expect(comment_message(@markdown_comment)).to eq(@striped_markdown_comment)
end end
it 'hides the private content' do it "renders markdown as html" do
expect(comment_message(@markdown_comment, html: true))
.to include("<a href=\"https://diasporafoundation.org\">link</a>")
end
it "hides the private content" do
expect(comment_message(@limited_comment)).not_to include("secret comment") expect(comment_message(@limited_comment)).not_to include("secret comment")
end end
end end

View file

@ -78,12 +78,6 @@ describe Diaspora::MessageRenderer do
end end
context 'linking all mentions' do context 'linking all mentions' do
it 'makes plain links for people not in the post aspects' do
message = message("@{Bob; #{bob.person.diaspora_handle}}", link_all_mentions: true).html
expect(message).to_not include 'hovercard'
expect(message).to include "/people/#{bob.person.guid}"
end
it "makes no hovercards if they're disabled" do it "makes no hovercards if they're disabled" do
message = message( message = message(
"@{Bob; #{bob.person.diaspora_handle}}", "@{Bob; #{bob.person.diaspora_handle}}",
@ -91,7 +85,7 @@ describe Diaspora::MessageRenderer do
disable_hovercards: true disable_hovercards: true
).html ).html
expect(message).to_not include 'hovercard' expect(message).to_not include 'hovercard'
expect(message).to include "/people/#{bob.person.guid}" expect(message).to include AppConfig.url_to("/people/#{bob.person.guid}")
end end
end end
end end

View file

@ -555,9 +555,9 @@ describe Notifier, type: :mailer do
describe "hashtags" do describe "hashtags" do
it "escapes hashtags" do it "escapes hashtags" do
mails = Notifier.admin("#Welcome to bureaucracy!", [bob]) status = FactoryGirl.create(:status_message, author: alice.person, text: "#Welcome to bureaucracy!", public: true)
expect(mails.length).to eq(1) like = status.likes.create!(author: bob.person)
mail = mails.first mail = Notifier.send_notification("liked", alice.id, like.author.id, like.id)
expect(mail.body.encoded).to match( expect(mail.body.encoded).to match(
"<p><a href=\"#{AppConfig.url_to(tag_path('welcome'))}\">#Welcome</a> to bureaucracy!</p>" "<p><a href=\"#{AppConfig.url_to(tag_path('welcome'))}\">#Welcome</a> to bureaucracy!</p>"
) )