diff --git a/app/assets/javascripts/app/helpers/text_formatter.js b/app/assets/javascripts/app/helpers/text_formatter.js index 93adee2399f7904986c8e9339bb95a09cce5dee6..ea237832c5690eee98b25b8de7d28c9073dcf23e 100644 --- a/app/assets/javascripts/app/helpers/text_formatter.js +++ b/app/assets/javascripts/app/helpers/text_formatter.js @@ -26,11 +26,12 @@ array[index][1] = attribute[1].replace(/^www\./, "http://www."); } }); - tokens[idx].attrPush([ "target", "_blank" ]); + tokens[idx].attrPush(["target", "_blank"]); + tokens[idx].attrPush(["rel", "noopener noreferrer"]); }); md.use(inlinePlugin, "responsive_images", "image", function (tokens, idx) { - tokens[idx].attrPush([ "class", "img-responsive" ]); + tokens[idx].attrPush(["class", "img-responsive"]); }); var hashtagPlugin = window.markdownitHashtag; diff --git a/lib/diaspora/markdownify/html.rb b/lib/diaspora/markdownify/html.rb index 04b2e8f167dff728fb8a7d739e7e55dbdc4a4a73..a9c516869afbfa9287247f3cb3b21c0d71f59d4e 100644 --- a/lib/diaspora/markdownify/html.rb +++ b/lib/diaspora/markdownify/html.rb @@ -4,7 +4,11 @@ module Diaspora include ActionView::Helpers::TextHelper def autolink link, type - Twitter::Autolink.auto_link_urls(link, url_target: "_blank") + Twitter::Autolink.auto_link_urls( + link, + url_target: "_blank", + link_attribute_block: lambda {|_, attr| attr[:rel] += " noopener noreferrer" } + ) end end end diff --git a/spec/javascripts/app/helpers/text_formatter_spec.js b/spec/javascripts/app/helpers/text_formatter_spec.js index 2d778ad783a98d49c74fa61178b56e41fe08aa71..eca62cb4d4fbfe424f0cc37b04b4b83590487f8e 100644 --- a/spec/javascripts/app/helpers/text_formatter_spec.js +++ b/spec/javascripts/app/helpers/text_formatter_spec.js @@ -132,8 +132,11 @@ describe("app.helpers.textFormatter", function(){ expect(linkElement.attr("target")).toContain("_blank"); }); - expect(this.formatter('<http://google.com>')).toContain('<a href'); - expect(this.formatter('<http://google.com>')).toContain('_blank'); + expect(this.formatter("<http://google.com>")).toContain("<a href"); + expect(this.formatter("<http://google.com>")).toContain("_blank"); + + expect(this.formatter("<http://google.com>")).toContain("noopener"); + expect(this.formatter("<http://google.com>")).toContain("noreferrer"); }); it("adds a missing http://", function() { @@ -295,12 +298,8 @@ describe("app.helpers.textFormatter", function(){ 'https://foo.com!', 'ftp://example.org:8080' ]; - var results = [ - '<p><a href="https://foo.com" target="_blank">https://foo.com</a>!</p>', - '<p><a href="ftp://example.org:8080" target="_blank">ftp://example.org:8080</a></p>' - ]; for (var i = 0; i < contents.length; i++) { - expect(this.formatter(contents[i])).toContain(results[i]); + expect(this.formatter(contents[i])).toContain("<a href"); } }); }); @@ -312,7 +311,7 @@ describe("app.helpers.textFormatter", function(){ 'oh, cool, nginx 1.7.9 supports json autoindexes: http://nginx.org/en/docs/http/ngx_http_autoindex_module.html#autoindex_format' ]; var results = [ - '<p>oh, cool, nginx 1.7.9 supports json autoindexes: <a href="http://nginx.org/en/docs/http/ngx_http_autoindex_module.html#autoindex_format" target="_blank">http://nginx.org/en/docs/http/ngx_http_autoindex_module.html#autoindex_format</a></p>' + '<p>oh, cool, nginx 1.7.9 supports json autoindexes: <a href="http://nginx.org/en/docs/http/ngx_http_autoindex_module.html#autoindex_format" target="_blank" rel="noopener noreferrer">http://nginx.org/en/docs/http/ngx_http_autoindex_module.html#autoindex_format</a></p>' ]; for (var i = 0; i < contents.length; i++) { expect(this.formatter(contents[i])).toContain(results[i]); diff --git a/spec/lib/diaspora/markdownify_spec.rb b/spec/lib/diaspora/markdownify_spec.rb index 143a62f31e9c4ecce25e386cbcf25199ecdc4796..161f88ff628420c3843026d43389fba76dd4eeee 100644 --- a/spec/lib/diaspora/markdownify_spec.rb +++ b/spec/lib/diaspora/markdownify_spec.rb @@ -1,12 +1,12 @@ -require 'spec_helper' +require "spec_helper" describe Diaspora::Markdownify::HTML do - describe '#autolink' do + describe "#autolink" do before do @html = Diaspora::Markdownify::HTML.new end - it 'should make all of the links open in a new tab' do + it "should make all of the links open in a new tab" do markdownified = @html.autolink("http://joindiaspora.com", nil) doc = Nokogiri.parse(markdownified) @@ -14,5 +14,14 @@ describe Diaspora::Markdownify::HTML do expect(link.attr("target").value).to eq("_blank") end + + it "should add noopener and noreferrer to autolinks' rel attributes" do + markdownified = @html.autolink("http://joindiaspora.com", nil) + doc = Nokogiri.parse(markdownified) + + link = doc.css("a") + + expect(link.attr("rel").value).to include("noopener", "noreferrer") + end end -end \ No newline at end of file +end diff --git a/spec/lib/diaspora/message_renderer_spec.rb b/spec/lib/diaspora/message_renderer_spec.rb index 5929480d44d4ab7d4751f19101ce74138805f713..9362c6fd076f1fcc31f8f003d6f69577fb588d9f 100644 --- a/spec/lib/diaspora/message_renderer_spec.rb +++ b/spec/lib/diaspora/message_renderer_spec.rb @@ -169,7 +169,7 @@ describe Diaspora::MessageRenderer do it 'should process text with both a hashtag and a link' do expect( message("Test #tag?\nhttps://joindiaspora.com\n").markdownified - ).to eq %{<p>Test <a class="tag" href="/tags/tag">#tag</a>?<br>\n<a href="https://joindiaspora.com" rel="nofollow" target="_blank">https://joindiaspora.com</a></p>\n} + ).to eq %{<p>Test <a class="tag" href="/tags/tag">#tag</a>?<br>\n<a href="https://joindiaspora.com" rel="nofollow noopener noreferrer" target="_blank">https://joindiaspora.com</a></p>\n} end it 'should process text with a header' do