From 3bdca34c2d037beaf0569828edb7eb55b2b9c407 Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Sun, 16 Jan 2022 22:13:07 +0100 Subject: [PATCH] QuestionMarkdown adjustments * Using `Redcarpet::Render::StripDown` as base now * Support for autolinks and named links in Markdown * Named links in questions just return the actual link as text * Fixed codestyle in files --- app/services/question_markdown.rb | 12 ++- app/services/shared_markers.rb | 27 +++++- spec/helpers/markdown_helper_spec.rb | 120 ++++++++++++++------------- 3 files changed, 93 insertions(+), 66 deletions(-) diff --git a/app/services/question_markdown.rb b/app/services/question_markdown.rb index 51d144a9..6ae585ea 100644 --- a/app/services/question_markdown.rb +++ b/app/services/question_markdown.rb @@ -1,10 +1,16 @@ -require 'uri' +# frozen_string_literal: true -class QuestionMarkdown < Redcarpet::Render::Base +require "uri" + +class QuestionMarkdown < Redcarpet::Render::StripDown include Rails.application.routes.url_helpers include SharedMarkers def paragraph(text) "

#{text}

" end -end \ No newline at end of file + + def link(link, _title, _content) + process_link(link) + end +end diff --git a/app/services/shared_markers.rb b/app/services/shared_markers.rb index c29e05c0..e127d43d 100644 --- a/app/services/shared_markers.rb +++ b/app/services/shared_markers.rb @@ -1,15 +1,34 @@ +# frozen_string_literal: true + module SharedMarkers include ActionView::Helpers::TagHelper - def autolink(link, _link_type) - href = if ALLOWED_HOSTS_IN_MARKDOWN.include?(URI(link).host) + def process_link(link, text = nil) + href = if ALLOWED_HOSTS_IN_MARKDOWN.include?(URI(link).host) || URI(link).relative? link else linkfilter_path(url: link) end - content_tag(:a, link, href: href, target: "_blank", rel: "nofollow") + options = { href: href } + + unless URI(link).relative? + options = options.merge({ + target: "_blank", + rel: "nofollow" + }) + end + + content_tag(:a, text.nil? ? link : text, options) rescue link end -end \ No newline at end of file + + def autolink(link, _link_type) + process_link(link) + end + + def link(link, _title, content) + process_link(link, content) + end +end diff --git a/spec/helpers/markdown_helper_spec.rb b/spec/helpers/markdown_helper_spec.rb index 23674ee3..fe947b59 100644 --- a/spec/helpers/markdown_helper_spec.rb +++ b/spec/helpers/markdown_helper_spec.rb @@ -1,124 +1,126 @@ +# frozen_string_literal: true + require "rails_helper" -describe MarkdownHelper, :type => :helper do +describe MarkdownHelper, type: :helper do before do stub_const("APP_CONFIG", { - 'hostname' => 'example.com', - 'https' => true, - 'items_per_page' => 5, - 'allowed_hosts' => [ - 'twitter.com' - ] - }) + "hostname" => "example.com", + "https" => true, + "items_per_page" => 5, + "allowed_hosts" => [ + "twitter.com" + ] + }) end - describe '#markdown' do - it 'should return the expected text' do - expect(markdown('**Strong text**')).to eq('

Strong text

') + describe "#markdown" do + it "should return the expected text" do + expect(markdown("**Strong text**")).to eq("

Strong text

") end - it 'should transform mentions into links' do - expect(markdown('@jake_weary')).to eq('

@jake_weary

') + it "should transform mentions into links" do + expect(markdown("@jake_weary")).to eq('

@jake_weary

') end end - describe '#strip_markdown' do - it 'should not return formatted text' do - expect(strip_markdown('**Strong text**')).to eq('Strong text') + describe "#strip_markdown" do + it "should not return formatted text" do + expect(strip_markdown("**Strong text**".dup)).to eq("Strong text") end end - describe '#twitter_markdown' do - context 'mentioned user has Twitter connected' do + describe "#twitter_markdown" do + context "mentioned user has Twitter connected" do let(:user) { FactoryBot.create(:user) } let(:service) { Services::Twitter.create(user: user) } - + before do - service.nickname = 'test' + service.nickname = "test" service.save! end - it 'should transform a internal mention to a Twitter mention' do - expect(twitter_markdown("@#{user.screen_name}")).to eq('@test') + it "should transform a internal mention to a Twitter mention" do + expect(twitter_markdown("@#{user.screen_name}")).to eq("@test") end end - context 'mentioned user doesnt have Twitter connected' do - it 'should not transform the mention' do - expect(twitter_markdown('@test')).to eq('test') + context "mentioned user doesnt have Twitter connected" do + it "should not transform the mention" do + expect(twitter_markdown("@test")).to eq("test") end end end - describe '#question_markdown' do - it 'should link allowed links without the linkfilter' do - expect(question_markdown('https://twitter.com/retrospring')).to eq('

https://twitter.com/retrospring

') + describe "#question_markdown" do + it "should link allowed links without the linkfilter" do + expect(question_markdown("https://twitter.com/retrospring")).to eq('

https://twitter.com/retrospring

') end - it 'should link untrusted links with the linkfilter' do - expect(question_markdown('https://rrerr.net')).to eq('

https://rrerr.net

') + it "should link untrusted links with the linkfilter" do + expect(question_markdown("https://rrerr.net")).to eq('

https://rrerr.net

') end - it 'should not process any markup aside of links' do - expect(question_markdown('**your account has been disabled**, [click here to enable it again](https://evil.example.com)')). to eq('

**your account has been disabled**, [click here to enable it again](https://evil.example.com)

') + it "should not process any markup aside of links" do + expect(question_markdown("**your account has been disabled**, [click here to enable it again](https://evil.example.com)")).to eq('

your account has been disabled, https://evil.example.com

') end - it 'should not raise an exception if an invalid link is processed' do - expect{ question_markdown('https://example.com/example.質問') }.not_to raise_error + it "should not raise an exception if an invalid link is processed" do + expect { question_markdown("https://example.com/example.質問") }.not_to raise_error end - it 'should not process invalid links' do - expect(question_markdown('https://example.com/example.質問')).to eq('

https://example.com/example.質問

') + it "should not process invalid links" do + expect(question_markdown("https://example.com/example.質問")).to eq("

https://example.com/example.質問

") end end - describe '#raw_markdown' do - it 'should return the expected text' do - expect(raw_markdown('# Heading')).to eq("

Heading

\n") + describe "#raw_markdown" do + it "should return the expected text" do + expect(raw_markdown("# Heading")).to eq("

Heading

\n") end end - describe '#get_markdown' do - it 'should return the contents of the specified file' do - expect(get_markdown('spec/fixtures/markdown/test.md')).to eq("# Heading") + describe "#get_markdown" do + it "should return the contents of the specified file" do + expect(get_markdown("spec/fixtures/markdown/test.md")).to eq("# Heading") end - it 'should return an error message on error' do - expect(get_markdown('non/existant/path.md')).to eq("# Error reading #{Rails.root}/non/existant/path.md") + it "should return an error message on error" do + expect(get_markdown("non/existant/path.md")).to eq("# Error reading #{Rails.root.join('non/existant/path.md')}") end end - describe '#markdown_io' do - it 'should return the expected text' do - expect(markdown_io('spec/fixtures/markdown/io.md')).to eq('

Strong text

') + describe "#markdown_io" do + it "should return the expected text" do + expect(markdown_io("spec/fixtures/markdown/io.md")).to eq("

Strong text

") end end - describe '#strip_markdown_io' do - it 'should return the expected text' do - expect(strip_markdown_io('spec/fixtures/markdown/io.md')).to eq('Strong text') + describe "#strip_markdown_io" do + it "should return the expected text" do + expect(strip_markdown_io("spec/fixtures/markdown/io.md")).to eq("Strong text") end end - describe '#twitter_markdown_io' do + describe "#twitter_markdown_io" do let(:user) { FactoryBot.create(:user) } let(:service) { Services::Twitter.create(user: user) } before do - user.screen_name = 'test' + user.screen_name = "test" user.save! - service.nickname = 'ObamaGaming' + service.nickname = "ObamaGaming" service.save! end - it 'should return the expected text' do - expect(twitter_markdown_io('spec/fixtures/markdown/twitter.md')).to eq('@ObamaGaming') + it "should return the expected text" do + expect(twitter_markdown_io("spec/fixtures/markdown/twitter.md")).to eq("@ObamaGaming") end end - describe '#raw_markdown_io' do - it 'should return the expected text' do - expect(raw_markdown_io('spec/fixtures/markdown/test.md')).to eq("

Heading

\n") + describe "#raw_markdown_io" do + it "should return the expected text" do + expect(raw_markdown_io("spec/fixtures/markdown/test.md")).to eq("

Heading

\n") end end -end \ No newline at end of file +end