mirror of
https://github.com/mastodon/mastodon.git
synced 2024-12-28 05:55:04 +01:00
Change referrer policy to be controlled by header in web UI (#33214)
This commit is contained in:
parent
2e35b15b4d
commit
425311e1d9
@ -109,7 +109,7 @@ module.exports = defineConfig({
|
||||
'react/jsx-equals-spacing': 'error',
|
||||
'react/jsx-no-bind': 'error',
|
||||
'react/jsx-no-useless-fragment': 'error',
|
||||
'react/jsx-no-target-blank': 'off',
|
||||
'react/jsx-no-target-blank': ['error', { allowReferrer: true }],
|
||||
'react/jsx-tag-spacing': 'error',
|
||||
'react/jsx-uses-react': 'off', // not needed with new JSX transform
|
||||
'react/jsx-wrap-multilines': 'error',
|
||||
|
@ -8,6 +8,7 @@ module Admin
|
||||
layout 'admin'
|
||||
|
||||
before_action :set_cache_headers
|
||||
before_action :set_referrer_policy_header
|
||||
|
||||
after_action :verify_authorized
|
||||
|
||||
@ -17,6 +18,10 @@ module Admin
|
||||
response.cache_control.replace(private: true, no_store: true)
|
||||
end
|
||||
|
||||
def set_referrer_policy_header
|
||||
response.headers['Referrer-Policy'] = 'same-origin'
|
||||
end
|
||||
|
||||
def set_user
|
||||
@user = Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
|
@ -36,7 +36,7 @@ export default class AttachmentList extends ImmutablePureComponent {
|
||||
|
||||
return (
|
||||
<li key={attachment.get('id')}>
|
||||
<a href={displayUrl} target='_blank' rel='noopener noreferrer'>
|
||||
<a href={displayUrl} target='_blank' rel='noopener'>
|
||||
{compact && <Icon id='link' icon={LinkIcon} />}
|
||||
{compact && ' ' }
|
||||
{displayUrl ? filename(displayUrl) : <FormattedMessage id='attachments_list.unprocessed' defaultMessage='(unprocessed)' />}
|
||||
|
@ -124,7 +124,7 @@ class DropdownMenu extends PureComponent {
|
||||
|
||||
return (
|
||||
<li className={classNames('dropdown-menu__item', { 'dropdown-menu__item--dangerous': dangerous })} key={`${text}-${i}`}>
|
||||
<a href={href} target={target} data-method={method} rel='noopener noreferrer' role='button' tabIndex={0} ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyPress={this.handleItemKeyPress} data-index={i}>
|
||||
<a href={href} target={target} data-method={method} rel='noopener' role='button' tabIndex={0} ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyPress={this.handleItemKeyPress} data-index={i}>
|
||||
{text}
|
||||
</a>
|
||||
</li>
|
||||
|
@ -98,7 +98,7 @@ export default class ErrorBoundary extends PureComponent {
|
||||
)}
|
||||
</p>
|
||||
|
||||
<p className='error-boundary__footer'>Mastodon v{version} · <a href={source_url} rel='noopener noreferrer' target='_blank'><FormattedMessage id='errors.unexpected_crash.report_issue' defaultMessage='Report issue' /></a> · <button onClick={this.handleCopyStackTrace} className={copied ? 'copied' : ''}><FormattedMessage id='errors.unexpected_crash.copy_stacktrace' defaultMessage='Copy stacktrace to clipboard' /></button></p>
|
||||
<p className='error-boundary__footer'>Mastodon v{version} · <a href={source_url} rel='noopener' target='_blank'><FormattedMessage id='errors.unexpected_crash.report_issue' defaultMessage='Report issue' /></a> · <button onClick={this.handleCopyStackTrace} className={copied ? 'copied' : ''}><FormattedMessage id='errors.unexpected_crash.copy_stacktrace' defaultMessage='Copy stacktrace to clipboard' /></button></p>
|
||||
</div>
|
||||
|
||||
<Helmet>
|
||||
|
@ -88,7 +88,7 @@ export const FollowButton: React.FC<{
|
||||
<a
|
||||
href='/settings/profile'
|
||||
target='_blank'
|
||||
rel='noreferrer noopener'
|
||||
rel='noopener'
|
||||
className='button button-secondary'
|
||||
>
|
||||
{label}
|
||||
|
@ -106,7 +106,7 @@ class Item extends PureComponent {
|
||||
if (attachment.get('type') === 'unknown') {
|
||||
return (
|
||||
<div className={classNames('media-gallery__item', { standalone, 'media-gallery__item--tall': height === 100, 'media-gallery__item--wide': width === 100 })} key={attachment.get('id')}>
|
||||
<a className='media-gallery__item-thumbnail' href={attachment.get('remote_url') || attachment.get('url')} style={{ cursor: 'pointer' }} title={description} lang={lang} target='_blank' rel='noopener noreferrer'>
|
||||
<a className='media-gallery__item-thumbnail' href={attachment.get('remote_url') || attachment.get('url')} style={{ cursor: 'pointer' }} title={description} lang={lang} target='_blank' rel='noopener'>
|
||||
<Blurhash
|
||||
hash={attachment.get('blurhash')}
|
||||
className='media-gallery__preview'
|
||||
@ -138,7 +138,7 @@ class Item extends PureComponent {
|
||||
href={attachment.get('remote_url') || originalUrl}
|
||||
onClick={this.handleClick}
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
rel='noopener'
|
||||
>
|
||||
<img
|
||||
src={previewUrl}
|
||||
|
@ -42,7 +42,7 @@ class ServerBanner extends PureComponent {
|
||||
return (
|
||||
<div className='server-banner'>
|
||||
<div className='server-banner__introduction'>
|
||||
<FormattedMessage id='server_banner.is_one_of_many' defaultMessage='{domain} is one of the many independent Mastodon servers you can use to participate in the fediverse.' values={{ domain: <strong>{domain}</strong>, mastodon: <a href='https://joinmastodon.org' target='_blank'>Mastodon</a> }} />
|
||||
<FormattedMessage id='server_banner.is_one_of_many' defaultMessage='{domain} is one of the many independent Mastodon servers you can use to participate in the fediverse.' values={{ domain: <strong>{domain}</strong>, mastodon: <a href='https://joinmastodon.org' target='_blank' rel='noopener'>Mastodon</a> }} />
|
||||
</div>
|
||||
|
||||
<Link to='/about'>
|
||||
|
@ -293,7 +293,7 @@ class Status extends ImmutablePureComponent {
|
||||
if (e?.button === 0 && !(e?.ctrlKey || e?.metaKey)) {
|
||||
history.push(path);
|
||||
} else if (e?.button === 1 || (e?.button === 0 && (e?.ctrlKey || e?.metaKey))) {
|
||||
window.open(path, '_blank', 'noreferrer noopener');
|
||||
window.open(path, '_blank', 'noopener');
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -123,7 +123,7 @@ class About extends PureComponent {
|
||||
<div className='about__header'>
|
||||
<ServerHeroImage blurhash={server.getIn(['thumbnail', 'blurhash'])} src={server.getIn(['thumbnail', 'url'])} srcSet={server.getIn(['thumbnail', 'versions'])?.map((value, key) => `${value} ${key.replace('@', '')}`).join(', ')} className='about__header__hero' />
|
||||
<h1>{isLoading ? <Skeleton width='10ch' /> : server.get('domain')}</h1>
|
||||
<p><FormattedMessage id='about.powered_by' defaultMessage='Decentralized social media powered by {mastodon}' values={{ mastodon: <a href='https://joinmastodon.org' className='about__mail' target='_blank'>Mastodon</a> }} /></p>
|
||||
<p><FormattedMessage id='about.powered_by' defaultMessage='Decentralized social media powered by {mastodon}' values={{ mastodon: <a href='https://joinmastodon.org' className='about__mail' target='_blank' rel='noopener'>Mastodon</a> }} /></p>
|
||||
</div>
|
||||
|
||||
<div className='about__meta'>
|
||||
|
@ -421,7 +421,7 @@ class Header extends ImmutablePureComponent {
|
||||
|
||||
<div className='account__header__bar'>
|
||||
<div className='account__header__tabs'>
|
||||
<a className='avatar' href={account.get('avatar')} rel='noopener noreferrer' target='_blank' onClick={this.handleAvatarClick}>
|
||||
<a className='avatar' href={account.get('avatar')} rel='noopener' target='_blank' onClick={this.handleAvatarClick}>
|
||||
<Avatar account={suspended || hidden ? undefined : account} size={90} />
|
||||
</a>
|
||||
|
||||
|
@ -90,8 +90,8 @@ describe('emoji', () => {
|
||||
});
|
||||
|
||||
it('keeps ordering as expected (issue fixed by PR 20677)', () => {
|
||||
expect(emojify('<p>💕 <a class="hashtag" href="https://example.com/tags/foo" rel="nofollow noopener noreferrer" target="_blank">#<span>foo</span></a> test: foo.</p>'))
|
||||
.toEqual('<p><picture><img draggable="false" class="emojione" alt="💕" title=":two_hearts:" src="/emoji/1f495.svg"></picture> <a class="hashtag" href="https://example.com/tags/foo" rel="nofollow noopener noreferrer" target="_blank">#<span>foo</span></a> test: foo.</p>');
|
||||
expect(emojify('<p>💕 <a class="hashtag" href="https://example.com/tags/foo" rel="nofollow noopener" target="_blank">#<span>foo</span></a> test: foo.</p>'))
|
||||
.toEqual('<p><picture><img draggable="false" class="emojione" alt="💕" title=":two_hearts:" src="/emoji/1f495.svg"></picture> <a class="hashtag" href="https://example.com/tags/foo" rel="nofollow noopener" target="_blank">#<span>foo</span></a> test: foo.</p>');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -85,7 +85,7 @@ class ContentWithRouter extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
link.setAttribute('target', '_blank');
|
||||
link.setAttribute('rel', 'noopener noreferrer');
|
||||
link.setAttribute('rel', 'noopener');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ export const RelationshipsSeveranceEvent = ({ type, target, followingCount, foll
|
||||
|
||||
<div className='notification-group__main'>
|
||||
<p>{intl.formatMessage(messages[type], { from: <strong>{domain}</strong>, target: <strong>{target}</strong>, followingCount, followersCount })}</p>
|
||||
<a href='/severed_relationships' target='_blank' rel='noopener noreferrer' className='link-button'><FormattedMessage id='notification.relationships_severance_event.learn_more' defaultMessage='Learn more' /></a>
|
||||
<a href='/severed_relationships' target='_blank' rel='noopener' className='link-button'><FormattedMessage id='notification.relationships_severance_event.learn_more' defaultMessage='Learn more' /></a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -55,7 +55,7 @@ class Report extends ImmutablePureComponent {
|
||||
</div>
|
||||
|
||||
<div className='notification__report__actions'>
|
||||
<a href={`/admin/reports/${report.get('id')}`} className='button' target='_blank' rel='noopener noreferrer'>{intl.formatMessage(messages.openReport)}</a>
|
||||
<a href={`/admin/reports/${report.get('id')}`} className='button' target='_blank' rel='noopener'>{intl.formatMessage(messages.openReport)}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -70,7 +70,7 @@ export const EmbeddedStatus: React.FC<{ statusId: string }> = ({
|
||||
if (button === 0 && !(ctrlKey || metaKey)) {
|
||||
history.push(path);
|
||||
} else if (button === 1 || (button === 0 && (ctrlKey || metaKey))) {
|
||||
window.open(path, '_blank', 'noreferrer noopener');
|
||||
window.open(path, '_blank', 'noopener');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ const Embed: React.FC<{ id: string }> = ({ id }) => {
|
||||
className='embed__overlay'
|
||||
href={permalink}
|
||||
target='_blank'
|
||||
rel='noreferrer noopener'
|
||||
rel='noopener'
|
||||
aria-label=''
|
||||
/>
|
||||
</div>
|
||||
|
@ -208,7 +208,7 @@ export default class Card extends PureComponent {
|
||||
<div className='status-card__actions' onClick={this.handleEmbedClick} role='none'>
|
||||
<div>
|
||||
<button type='button' onClick={this.handleEmbedClick}><Icon id='play' icon={PlayArrowIcon} /></button>
|
||||
<a href={card.get('url')} onClick={this.handleExternalLinkClick} target='_blank' rel='noopener noreferrer'><Icon id='external-link' icon={OpenInNewIcon} /></a>
|
||||
<a href={card.get('url')} onClick={this.handleExternalLinkClick} target='_blank' rel='noopener'><Icon id='external-link' icon={OpenInNewIcon} /></a>
|
||||
</div>
|
||||
</div>
|
||||
) : spoilerButton}
|
||||
@ -219,7 +219,7 @@ export default class Card extends PureComponent {
|
||||
return (
|
||||
<div className={classNames('status-card', { expanded: largeImage })} ref={this.setRef} onClick={revealed ? null : this.handleReveal} role={revealed ? 'button' : null}>
|
||||
{embed}
|
||||
<a href={card.get('url')} target='_blank' rel='noopener noreferrer'>{description}</a>
|
||||
<a href={card.get('url')} target='_blank' rel='noopener'>{description}</a>
|
||||
</div>
|
||||
);
|
||||
} else if (card.get('image')) {
|
||||
@ -239,7 +239,7 @@ export default class Card extends PureComponent {
|
||||
|
||||
return (
|
||||
<>
|
||||
<a href={card.get('url')} className={classNames('status-card', { expanded: largeImage, bottomless: showAuthor })} target='_blank' rel='noopener noreferrer' ref={this.setRef}>
|
||||
<a href={card.get('url')} className={classNames('status-card', { expanded: largeImage, bottomless: showAuthor })} target='_blank' rel='noopener' ref={this.setRef}>
|
||||
{embed}
|
||||
{description}
|
||||
</a>
|
||||
|
@ -24,7 +24,7 @@ export default class ActionsModal extends ImmutablePureComponent {
|
||||
|
||||
return (
|
||||
<li key={`${text}-${i}`}>
|
||||
<a href={href} target='_blank' rel='noopener noreferrer' onClick={this.props.onClick} data-index={i} className={classNames({ active })}>
|
||||
<a href={href} target='_blank' rel='noopener' onClick={this.props.onClick} data-index={i} className={classNames({ active })}>
|
||||
{icon && <IconButton title={text} icon={icon} iconComponent={iconComponent} role='presentation' tabIndex={-1} inverted />}
|
||||
<div>
|
||||
<div className={classNames({ 'actions-modal__item-label': !!meta })}>{text}</div>
|
||||
|
@ -26,7 +26,7 @@ export const LinkFooter: React.FC<{
|
||||
{statusPageUrl && (
|
||||
<>
|
||||
<DividingCircle />
|
||||
<a href={statusPageUrl} target='_blank' rel='noopener noreferrer'>
|
||||
<a href={statusPageUrl} target='_blank' rel='noopener'>
|
||||
<FormattedMessage id='footer.status' defaultMessage='Status' />
|
||||
</a>
|
||||
</>
|
||||
@ -72,15 +72,11 @@ export const LinkFooter: React.FC<{
|
||||
|
||||
<p>
|
||||
<strong>Mastodon</strong>:{' '}
|
||||
<a href='https://joinmastodon.org' target='_blank' rel='noreferrer'>
|
||||
<a href='https://joinmastodon.org' target='_blank' rel='noopener'>
|
||||
<FormattedMessage id='footer.about' defaultMessage='About' />
|
||||
</a>
|
||||
<DividingCircle />
|
||||
<a
|
||||
href='https://joinmastodon.org/apps'
|
||||
target='_blank'
|
||||
rel='noreferrer'
|
||||
>
|
||||
<a href='https://joinmastodon.org/apps' target='_blank' rel='noopener'>
|
||||
<FormattedMessage id='footer.get_app' defaultMessage='Get the app' />
|
||||
</a>
|
||||
<DividingCircle />
|
||||
@ -91,7 +87,7 @@ export const LinkFooter: React.FC<{
|
||||
/>
|
||||
</Link>
|
||||
<DividingCircle />
|
||||
<a href={source_url} rel='noopener noreferrer' target='_blank'>
|
||||
<a href={source_url} rel='noopener' target='_blank'>
|
||||
<FormattedMessage
|
||||
id='footer.source_code'
|
||||
defaultMessage='View source code'
|
||||
|
@ -7,7 +7,7 @@ class TextFormatter
|
||||
|
||||
URL_PREFIX_REGEX = %r{\A(https?://(www\.)?|xmpp:)}
|
||||
|
||||
DEFAULT_REL = %w(nofollow noopener noreferrer).freeze
|
||||
DEFAULT_REL = %w(nofollow noopener).freeze
|
||||
|
||||
DEFAULT_OPTIONS = {
|
||||
multiline: true,
|
||||
|
@ -44,7 +44,7 @@
|
||||
= t("statuses.visibilities.#{status.visibility}")
|
||||
·
|
||||
|
||||
= link_to ActivityPub::TagManager.instance.url_for(status.proper), class: 'detailed-status__link', rel: 'noopener noreferrer' do
|
||||
= link_to ActivityPub::TagManager.instance.url_for(status.proper), class: 'detailed-status__link', rel: 'noopener' do
|
||||
= t('admin.statuses.view_publicly')
|
||||
|
||||
- if status.proper.sensitive?
|
||||
|
@ -63,7 +63,7 @@
|
||||
= material_symbol 'link'
|
||||
= media_attachment.file_file_name
|
||||
.strike-card__statuses-list__item__meta
|
||||
= link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', rel: 'noopener noreferrer' do
|
||||
= link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', rel: 'noopener' do
|
||||
%time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
|
||||
- unless status.application.nil?
|
||||
·
|
||||
|
@ -9,7 +9,7 @@
|
||||
data: { confirm: t('admin.reports.are_you_sure') },
|
||||
name: :report,
|
||||
type: :submit
|
||||
= link_to t('admin.statuses.open'), ActivityPub::TagManager.instance.url_for(@status), class: 'button', target: '_blank', rel: 'noopener noreferrer'
|
||||
= link_to t('admin.statuses.open'), ActivityPub::TagManager.instance.url_for(@status), class: 'button', target: '_blank', rel: 'noopener'
|
||||
|
||||
%h3= t('admin.statuses.metadata')
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
.time-period
|
||||
= date_range(@time_period)
|
||||
|
||||
= link_to t('admin.tags.open'), tag_url(@tag), class: 'button', target: '_blank', rel: 'noopener noreferrer'
|
||||
= link_to t('admin.tags.open'), tag_url(@tag), class: 'button', target: '_blank', rel: 'noopener'
|
||||
|
||||
- if current_user.can?(:view_dashboard)
|
||||
.dashboard
|
||||
@ -17,7 +17,7 @@
|
||||
label: t('admin.trends.tags.dashboard.tag_accounts_measure'),
|
||||
measure: 'tag_accounts',
|
||||
params: { id: @tag.id },
|
||||
rel: 'noopener noreferrer',
|
||||
rel: 'noopener',
|
||||
start_at: @time_period.first,
|
||||
target: '_blank'
|
||||
.dashboard__item
|
||||
|
@ -6,7 +6,7 @@
|
||||
.one-liner
|
||||
= admin_account_link_to status.account
|
||||
|
||||
= link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', class: 'emojify', rel: 'noopener noreferrer' do
|
||||
= link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', class: 'emojify', rel: 'noopener' do
|
||||
= one_line_preview(status)
|
||||
|
||||
- status.ordered_media_attachments.each do |media_attachment|
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
%br/
|
||||
|
||||
= link_to tag_path(tag), target: '_blank', rel: 'noopener noreferrer' do
|
||||
= link_to tag_path(tag), target: '_blank', rel: 'noopener' do
|
||||
= t('admin.trends.tags.used_by_over_week', count: tag.history.reduce(0) { |sum, day| sum + day.accounts })
|
||||
|
||||
- if tag.trendable?
|
||||
|
@ -2,7 +2,7 @@
|
||||
- compact ||= false
|
||||
|
||||
.card.h-card
|
||||
= link_to account_url, target: '_blank', rel: 'noopener noreferrer' do
|
||||
= link_to account_url, target: '_blank', rel: 'noopener' do
|
||||
- unless compact
|
||||
.card__img
|
||||
= image_tag account.header.url, alt: ''
|
||||
|
@ -27,7 +27,7 @@
|
||||
= material_symbol 'link'
|
||||
= media_attachment.file_file_name
|
||||
.strike-card__statuses-list__item__meta
|
||||
= link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', rel: 'noopener noreferrer' do
|
||||
= link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', rel: 'noopener' do
|
||||
%time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
|
||||
- unless status.application.nil?
|
||||
·
|
||||
|
@ -19,11 +19,11 @@
|
||||
= media_attachment.file_file_name
|
||||
|
||||
.detailed-status__meta
|
||||
= link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'name-tag', target: '_blank', rel: 'noopener noreferrer' do
|
||||
= link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'name-tag', target: '_blank', rel: 'noopener' do
|
||||
= image_tag(status.account.avatar.url, width: 15, height: 15, alt: '', class: 'avatar')
|
||||
.username= status.account.acct
|
||||
·
|
||||
= link_to ActivityPub::TagManager.instance.url_for(status), class: 'detailed-status__datetime', rel: 'noopener noreferrer' do
|
||||
= link_to ActivityPub::TagManager.instance.url_for(status), class: 'detailed-status__datetime', rel: 'noopener' do
|
||||
%time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
|
||||
- if status.edited?
|
||||
·
|
||||
|
@ -9,7 +9,7 @@
|
||||
- @applications.each do |application|
|
||||
.applications-list__item{ id: dom_id(application) }
|
||||
- if application.website.present?
|
||||
= link_to application.name, application.website, target: '_blank', rel: 'noopener noreferrer', class: 'announcements-list__item__title'
|
||||
= link_to application.name, application.website, target: '_blank', rel: 'noopener', class: 'announcements-list__item__title'
|
||||
- else
|
||||
%strong.announcements-list__item__title
|
||||
= application.name
|
||||
|
@ -11,4 +11,4 @@
|
||||
.redirect__message
|
||||
%h1= t('redirects.title', instance: site_hostname)
|
||||
%p= t('redirects.prompt')
|
||||
%p= link_to @redirect_path, @redirect_path, rel: 'noreferrer noopener'
|
||||
%p= link_to @redirect_path, @redirect_path, rel: 'noopener'
|
||||
|
@ -153,7 +153,7 @@ Rails.application.configure do
|
||||
'X-Frame-Options' => 'DENY',
|
||||
'X-Content-Type-Options' => 'nosniff',
|
||||
'X-XSS-Protection' => '0',
|
||||
'Referrer-Policy' => 'same-origin',
|
||||
'Referrer-Policy' => ENV['ALLOW_REFERRER_ORIGIN'] == 'true' ? 'origin' : 'same-origin',
|
||||
}
|
||||
|
||||
# TODO: Remove once devise-two-factor data migration complete
|
||||
|
@ -114,7 +114,7 @@ class Sanitize
|
||||
|
||||
add_attributes: {
|
||||
'a' => {
|
||||
'rel' => 'nofollow noopener noreferrer',
|
||||
'rel' => 'nofollow noopener',
|
||||
'target' => '_blank',
|
||||
},
|
||||
},
|
||||
|
@ -39,15 +39,15 @@ RSpec.describe Sanitize::Config do
|
||||
end
|
||||
|
||||
it 'keeps a with href' do
|
||||
expect(Sanitize.fragment('<a href="http://example.com">Test</a>', subject)).to eq '<a href="http://example.com" rel="nofollow noopener noreferrer" target="_blank">Test</a>'
|
||||
expect(Sanitize.fragment('<a href="http://example.com">Test</a>', subject)).to eq '<a href="http://example.com" rel="nofollow noopener" target="_blank">Test</a>'
|
||||
end
|
||||
|
||||
it 'keeps a with translate="no"' do
|
||||
expect(Sanitize.fragment('<a href="http://example.com" translate="no">Test</a>', subject)).to eq '<a href="http://example.com" translate="no" rel="nofollow noopener noreferrer" target="_blank">Test</a>'
|
||||
expect(Sanitize.fragment('<a href="http://example.com" translate="no">Test</a>', subject)).to eq '<a href="http://example.com" translate="no" rel="nofollow noopener" target="_blank">Test</a>'
|
||||
end
|
||||
|
||||
it 'removes "translate" attribute with invalid value' do
|
||||
expect(Sanitize.fragment('<a href="http://example.com" translate="foo">Test</a>', subject)).to eq '<a href="http://example.com" rel="nofollow noopener noreferrer" target="_blank">Test</a>'
|
||||
expect(Sanitize.fragment('<a href="http://example.com" translate="foo">Test</a>', subject)).to eq '<a href="http://example.com" rel="nofollow noopener" target="_blank">Test</a>'
|
||||
end
|
||||
|
||||
it 'removes a with unparsable href' do
|
||||
@ -55,7 +55,7 @@ RSpec.describe Sanitize::Config do
|
||||
end
|
||||
|
||||
it 'keeps a with supported scheme and no host' do
|
||||
expect(Sanitize.fragment('<a href="dweb:/a/foo">Test</a>', subject)).to eq '<a href="dweb:/a/foo" rel="nofollow noopener noreferrer" target="_blank">Test</a>'
|
||||
expect(Sanitize.fragment('<a href="dweb:/a/foo">Test</a>', subject)).to eq '<a href="dweb:/a/foo" rel="nofollow noopener" target="_blank">Test</a>'
|
||||
end
|
||||
|
||||
it 'sanitizes math to LaTeX' do
|
||||
|
Loading…
Reference in New Issue
Block a user