Skip to content
Snippets Groups Projects
Commit 2e8037f5 authored by Thomas Hutterer's avatar Thomas Hutterer :four: Committed by Scott de Jonge
Browse files

Add safe rel attribute on links with target "_blank"

Changelog: changed
parent f8ba2f20
No related branches found
No related tags found
1 merge request!145516Add safe rel attribute on links with target "_blank"
......@@ -122,8 +122,15 @@ def base_attributes
attributes['disabled'] = 'disabled' if @disabled || @loading
attributes['aria-disabled'] = true if @disabled || @loading
attributes['type'] = @type unless @href
attributes['rel'] = safe_rel_for_target_blank if link? && @target == '_blank'
attributes
end
def safe_rel_for_target_blank
(@button_options[:rel] || '').split(' ')
.concat(%w[noopener noreferrer])
.uniq.join(' ')
end
end
end
......@@ -18,7 +18,7 @@
%p
= s_('SlackIntegration|You must do this step only once.')
%p
= render Pajamas::ButtonComponent.new(href: slack_app_manifest_share_admin_application_settings_path, target: '_blank', button_options: { rel: 'noopener noreferrer' }) do
= render Pajamas::ButtonComponent.new(href: slack_app_manifest_share_admin_application_settings_path, target: '_blank') do
= s_("SlackIntegration|Create Slack app")
%hr
%h5
......
......@@ -7,5 +7,5 @@
- c.with_body do
= s_('ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab\'s Google Kubernetes Engine Integration.').html_safe % { sign_up_link: link }
- c.with_actions do
= render Pajamas::ButtonComponent.new(variant: :confirm, href: 'https://cloud.google.com/partners/partnercredit/?pcn_code=0014M00001h35gDQAQ#contact-form', target: '_blank', button_options: { rel: 'noopener noreferrer', data: { track_action: 'click_button', track_label: 'gcp_signup_offer_banner' } }) do
= render Pajamas::ButtonComponent.new(variant: :confirm, href: 'https://cloud.google.com/partners/partnercredit/?pcn_code=0014M00001h35gDQAQ#contact-form', target: '_blank', button_options: { data: { track_action: 'click_button', track_label: 'gcp_signup_offer_banner' } }) do
= s_("ClusterIntegration|Apply for credit")
......@@ -8,7 +8,7 @@
.text-muted
= template.description
.controls.d-flex.gl-align-items-center
= render Pajamas::ButtonComponent.new(button_options: { class: 'gl-mr-3', data: { track_label: "template_preview", track_property: template.name, track_action: "click_button", track_value: "" }, rel: 'noopener noreferrer' }, href: template.preview, target: '_blank') do
= render Pajamas::ButtonComponent.new(button_options: { class: 'gl-mr-3', data: { track_label: "template_preview", track_property: template.name, track_action: "click_button", track_value: "" } }, href: template.preview, target: '_blank') do
= _("Preview")
%label.btn.gl-button.btn-confirm.template-button.choose-template.gl-mb-0{ for: template.name,
'data-testid': "use_template_#{template.name}" }
......
......@@ -6,5 +6,5 @@
- profile_name = '<b>Full DAST scan - weekly</b>'.html_safe
= s_("OnDemandScans|Pre-scan verification for %{profile_name} completed with").html_safe % { profile_name: profile_name }
- c.with_actions do
= render Pajamas::ButtonComponent.new(href: "#", target: '_blank', button_options: { rel: 'noopener noreferrer' }) do
= render Pajamas::ButtonComponent.new(href: "#", target: '_blank') do
= s_("OnDemandScans|View results")
......@@ -28,7 +28,7 @@
.text-muted
= project.description
.controls.d-flex.align-items-baseline.gl-gap-3
= render Pajamas::ButtonComponent.new(href: project_path(project), target: '_blank', button_options: { rel: 'noopener noreferrer' }) do
= render Pajamas::ButtonComponent.new(href: project_path(project), target: '_blank') do
= _("Preview")
%label.btn.gl-button.btn-confirm.custom-template-button.choose-template.gl-mb-0{ for: project.name }
%input{ type: "radio", autocomplete: "off", name: "project[template_project_id]", id: project.name, value: project.id, data: { subgroup_full_path: project.namespace.full_path, target_group_full_path: @target_group&.full_path, subgroup_id: project.namespace_id, template_name: project.name, parent_group_id: @target_group&.id || group.parent_id } }
......
......@@ -10,7 +10,7 @@
.text-muted
= template.description
.controls.d-flex.align-items-baseline
= render Pajamas::ButtonComponent.new(href: project_path(template), target: '_blank', button_options: { class: 'gl-mr-3', rel: 'noopener noreferrer' }) do
= render Pajamas::ButtonComponent.new(href: project_path(template), target: '_blank', button_options: { class: 'gl-mr-3' }) do
= _('Preview')
%label.btn.gl-button.btn-confirm.custom-template-button.choose-template.gl-mb-0{ for: template.name }
%input{ type: "radio", autocomplete: "off", name: "project[template_project_id]", id: template.name, value: template.id, data: { template_name: template.name } }
......
......@@ -253,11 +253,35 @@
end
context 'button component renders a link' do
let(:options) { { href: 'https://gitlab.com', target: '_blank' } }
let(:options) { { href: 'https://gitlab.com', target: '_self' } }
it "renders a link instead of the button" do
expect(page).not_to have_css "button[type='button']"
expect(page).to have_css "a[href='https://gitlab.com'][target='_blank']"
expect(page).to have_css "a[href='https://gitlab.com'][target='_self']"
end
context 'with target="_blank"' do
let(:options) { { href: 'https://gitlab.com', target: '_blank' } }
it 'adds rel="noopener noreferrer"' do
expect(page).to have_css "a[href='https://gitlab.com'][target='_blank'][rel='noopener noreferrer']"
end
context 'with a value for "rel" already given' do
let(:options) { { href: 'https://gitlab.com', target: '_blank', button_options: { rel: 'help next' } } }
it 'keeps given value and adds "noopener noreferrer"' do
expect(page).to have_css "a[href='https://gitlab.com'][target='_blank'][rel='help next noopener noreferrer']"
end
end
context 'with "noopener noreferrer" for "rel" already given' do
let(:options) { { href: 'https://gitlab.com', target: '_blank', button_options: { rel: 'noopener noreferrer' } } }
it 'does not duplicate "noopener noreferrer"' do
expect(page).to have_css "a[href='https://gitlab.com'][target='_blank'][rel='noopener noreferrer']"
end
end
end
include_examples 'basic button behavior'
......
......@@ -44,10 +44,13 @@ def default( # rubocop:disable Metrics/ParameterLists
# The component can also be used to create links that look and feel like buttons.
# Just provide a `href` and optionally a `target` to create an `<a>` tag.
def link
# For links with target="_blank", the component automatically adds rel="noopener noreferrer".
#
# @param target select {{ Pajamas::ButtonComponent::TARGET_OPTIONS }}
def link(target: nil)
render(Pajamas::ButtonComponent.new(
href: "https://gitlab.com",
target: "_blank"
target: target
)) do
"This is a link"
end
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment