diff --git a/app/components/alchemy/ingredients/link_view.rb b/app/components/alchemy/ingredients/link_view.rb index 8e7467f742..be828aa8e1 100644 --- a/app/components/alchemy/ingredients/link_view.rb +++ b/app/components/alchemy/ingredients/link_view.rb @@ -1,6 +1,8 @@ module Alchemy module Ingredients class LinkView < BaseView + include LinkTarget + attr_reader :link_text # @param ingredient [Alchemy::Ingredient] @@ -12,7 +14,11 @@ def initialize(ingredient, text: nil, html_options: {}) end def call - link_to(link_text, value, {target: ingredient.link_target.presence}.merge(html_options)).html_safe + target = ingredient.link_target.presence + link_to(link_text, value, { + target: link_target_value(target), + rel: link_rel_value(target) + }.merge(html_options)).html_safe end end end diff --git a/app/components/alchemy/ingredients/picture_view.rb b/app/components/alchemy/ingredients/picture_view.rb index d32ab0ab99..33e2cfc438 100644 --- a/app/components/alchemy/ingredients/picture_view.rb +++ b/app/components/alchemy/ingredients/picture_view.rb @@ -4,6 +4,8 @@ module Alchemy module Ingredients # Renders a picture ingredient view class PictureView < BaseView + include LinkTarget + attr_reader :ingredient, :show_caption, :disable_link, @@ -46,10 +48,11 @@ def call output = caption ? img_tag + caption : img_tag if is_linked? + target = ingredient.link_target.presence output = link_to(output, url_for(ingredient.link), { title: ingredient.link_title.presence, - target: (ingredient.link_target == "blank") ? "_blank" : nil, - data: {link_target: ingredient.link_target.presence} + rel: link_rel_value(target), + target: link_target_value(target) }) end diff --git a/app/components/alchemy/ingredients/text_view.rb b/app/components/alchemy/ingredients/text_view.rb index 62a7e665f5..5954a1b850 100644 --- a/app/components/alchemy/ingredients/text_view.rb +++ b/app/components/alchemy/ingredients/text_view.rb @@ -1,6 +1,8 @@ module Alchemy module Ingredients class TextView < BaseView + include LinkTarget + attr_reader :disable_link delegate :dom_id, :link, :link_title, :link_target, @@ -21,7 +23,8 @@ def call link_to(value, url_for(link), { id: dom_id.presence, title: link_title, - target: link_target + target: link_target_value(link_target), + rel: link_rel_value(link_target) }.merge(html_options)) end.html_safe end diff --git a/app/components/concerns/alchemy/ingredients/link_target.rb b/app/components/concerns/alchemy/ingredients/link_target.rb new file mode 100644 index 0000000000..3e3a168b9b --- /dev/null +++ b/app/components/concerns/alchemy/ingredients/link_target.rb @@ -0,0 +1,18 @@ +module Alchemy + module Ingredients + module LinkTarget + BLANK_VALUE = "_blank" + REL_VALUE = "noopener noreferrer" + + def link_rel_value(target) + if link_target_value(target) == BLANK_VALUE + REL_VALUE + end + end + + def link_target_value(target) + (target == "blank") ? BLANK_VALUE : target + end + end + end +end diff --git a/spec/components/alchemy/ingredients/picture_view_spec.rb b/spec/components/alchemy/ingredients/picture_view_spec.rb index 22d3c901a8..c3e848ee52 100644 --- a/spec/components/alchemy/ingredients/picture_view_spec.rb +++ b/spec/components/alchemy/ingredients/picture_view_spec.rb @@ -169,6 +169,32 @@ expect(page).to have_selector('a[href="/home"] img') end + context "with link target set to '_blank'" do + before do + ingredient.link_target = "_blank" + end + + it "adds rel noopener noreferrer" do + render_view + expect(page).to have_selector( + 'a[href="/home"][target="_blank"][rel="noopener noreferrer"] img' + ) + end + end + + context "with link target set to 'blank'" do + before do + ingredient.link_target = "blank" + end + + it "sets target '_blank' and adds rel noopener noreferrer" do + render_view + expect(page).to have_selector( + 'a[href="/home"][target="_blank"][rel="noopener noreferrer"] img' + ) + end + end + context "but disabled link option" do before do options[:disable_link] = true diff --git a/spec/views/alchemy/ingredients/link_view_spec.rb b/spec/views/alchemy/ingredients/link_view_spec.rb index 14301faee3..fd1d1830b4 100644 --- a/spec/views/alchemy/ingredients/link_view_spec.rb +++ b/spec/views/alchemy/ingredients/link_view_spec.rb @@ -45,4 +45,30 @@ expect(rendered).to eq('http://google.com') end end + + context "with link target set to '_blank'" do + let(:ingredient) do + Alchemy::Ingredients::Link.new(value: "http://google.com", link_target: "_blank") + end + + it "adds rel noopener noreferrer" do + render ingredient + expect(rendered).to eq( + 'http://google.com' + ) + end + end + + context "with link target set to 'blank'" do + let(:ingredient) do + Alchemy::Ingredients::Link.new(value: "http://google.com", link_target: "blank") + end + + it "sets target '_blank' and adds rel noopener noreferrer" do + render ingredient + expect(rendered).to eq( + 'http://google.com' + ) + end + end end diff --git a/spec/views/alchemy/ingredients/text_view_spec.rb b/spec/views/alchemy/ingredients/text_view_spec.rb index 1ac9a0ac2f..cb277bf98e 100644 --- a/spec/views/alchemy/ingredients/text_view_spec.rb +++ b/spec/views/alchemy/ingredients/text_view_spec.rb @@ -50,6 +50,24 @@ expect(rendered).to have_selector('a[title="Foo"][target="_blank"][href="http://google.com"]') end + context "with link target set to '_blank'" do + it "adds rel noopener noreferrer" do + render ingredient + expect(rendered).to have_selector( + 'a[title="Foo"][target="_blank"][href="http://google.com"][rel="noopener noreferrer"]' + ) + end + end + + context "with link target set to 'blank'" do + it "sets target '_blank' and adds rel noopener noreferrer" do + render ingredient + expect(rendered).to have_selector( + 'a[title="Foo"][target="_blank"][href="http://google.com"][rel="noopener noreferrer"]' + ) + end + end + context "with html_options given" do it "renders the linked with these options" do render ingredient, html_options: {title: "Bar", class: "blue"}