Skip to content

Commit

Permalink
Adds 'nofollow' setting to inline links (rich text only) (#53945)
Browse files Browse the repository at this point in the history
* Add ability for inline link format to parse and handle rel no follow

* Add no follow to Link Control

* Add support for optional help text on setting controls

* Only apply new setting to inline links for now

* Expose default link settings for use by component consumers

* Extend default settings in inline link implementation

* Use nofollow lowercase

* Make help text the title

* Adds test coverage

* Use help text to reduce size of label

* Correct text to qualify statement

Search engines are not compelled to obey this rule

* Remove help text
  • Loading branch information
getdave authored Aug 31, 2023
1 parent ea3c23d commit 6d77fd2
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 9 deletions.
1 change: 1 addition & 0 deletions packages/block-editor/src/components/link-control/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -475,5 +475,6 @@ function LinkControl( {
}

LinkControl.ViewerFill = ViewerFill;
LinkControl.DEFAULT_LINK_SETTINGS = DEFAULT_LINK_SETTINGS;

export default LinkControl;
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const LinkControlSettings = ( { value, onChange = noop, settings } ) => {
label={ setting.title }
onChange={ handleSettingChange( setting ) }
checked={ value ? !! value[ setting.id ] : false }
help={ setting?.help }
/>
) );

Expand Down
10 changes: 5 additions & 5 deletions packages/block-editor/src/components/link-control/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -401,19 +401,19 @@ $preview-image-height: 140px;
}

.block-editor-link-control__setting {
margin-bottom: $grid-unit-20;
margin-bottom: 0;
flex: 1;
padding: $grid-unit-10 0 $grid-unit-10 $grid-unit-30;

.components-base-control__field {
display: flex; // don't allow label to wrap under checkbox.
}

// Cancel left margin inherited from WP Admin Forms CSS.
input {
margin-left: 0;
}

&.block-editor-link-control__setting:last-child {
margin-bottom: 0;
}

.is-preview & {
padding: 20px $grid-unit-10 $grid-unit-10 0;
}
Expand Down
1 change: 1 addition & 0 deletions packages/format-library/src/link/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ export const link = {
type: 'data-type',
id: 'data-id',
target: 'target',
rel: 'rel',
},
__unstablePasteRule( value, { html, plainText } ) {
if ( isCollapsed( value ) ) {
Expand Down
15 changes: 14 additions & 1 deletion packages/format-library/src/link/inline.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ import { createLinkFormat, isValidHref, getFormatBoundary } from './utils';
import { link as settings } from './index';
import useLinkInstanceKey from './use-link-instance-key';

const LINK_SETTINGS = [
...LinkControl.DEFAULT_LINK_SETTINGS,
{
id: 'nofollow',
title: createInterpolateElement(
__( 'Mark as <code>nofollow</code>' ),
{ code: <code /> }
),
},
];

function InlineLinkUI( {
isActive,
activeAttributes,
Expand Down Expand Up @@ -60,6 +71,7 @@ function InlineLinkUI( {
type: activeAttributes.type,
id: activeAttributes.id,
opensInNewTab: activeAttributes.target === '_blank',
nofollow: activeAttributes.rel?.includes( 'nofollow' ),
title: richTextText,
};

Expand All @@ -77,7 +89,6 @@ function InlineLinkUI( {
const didToggleSetting =
linkValue.opensInNewTab !== nextValue.opensInNewTab &&
nextValue.url === undefined;

// Merge the next value with the current link value.
nextValue = {
...linkValue,
Expand All @@ -93,6 +104,7 @@ function InlineLinkUI( {
? String( nextValue.id )
: undefined,
opensInNewWindow: nextValue.opensInNewTab,
nofollow: nextValue.nofollow,
} );

const newText = nextValue.title || newUrl;
Expand Down Expand Up @@ -247,6 +259,7 @@ function InlineLinkUI( {
withCreateSuggestion={ userCanCreatePages }
createSuggestionButtonText={ createButtonText }
hasTextControl
settings={ LINK_SETTINGS }
/>
</Popover>
);
Expand Down
20 changes: 17 additions & 3 deletions packages/format-library/src/link/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,16 @@ export function isValidHref( href ) {
* @param {string} options.type The type of the link.
* @param {string} options.id The ID of the link.
* @param {boolean} options.opensInNewWindow Whether this link will open in a new window.
*
* @param {boolean} options.nofollow Whether this link is marked as no follow relationship.
* @return {Object} The final format object.
*/
export function createLinkFormat( { url, type, id, opensInNewWindow } ) {
export function createLinkFormat( {
url,
type,
id,
opensInNewWindow,
nofollow,
} ) {
const format = {
type: 'core/link',
attributes: {
Expand All @@ -101,7 +107,15 @@ export function createLinkFormat( { url, type, id, opensInNewWindow } ) {

if ( opensInNewWindow ) {
format.attributes.target = '_blank';
format.attributes.rel = 'noreferrer noopener';
format.attributes.rel = format.attributes.rel
? format.attributes.rel + ' noreferrer noopener'
: 'noreferrer noopener';
}

if ( nofollow ) {
format.attributes.rel = format.attributes.rel
? format.attributes.rel + ' nofollow'
: 'nofollow';
}

return format;
Expand Down
82 changes: 82 additions & 0 deletions test/e2e/specs/editor/blocks/links.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -233,4 +233,86 @@ test.describe( 'Links', () => {
// This verifies that the editor preference was persisted.
await expect( page.getByLabel( 'Open in new tab' ) ).not.toBeVisible();
} );

test( 'can toggle link settings and save', async ( {
page,
editor,
pageUtils,
} ) => {
await editor.insertBlock( {
name: 'core/paragraph',
attributes: {
content:
'<a href="https://wordpress.org/gutenberg">Gutenberg</a>',
},
} );

// Move caret into the link.
await pageUtils.pressKeys( 'ArrowRight' );

// Switch Link UI to "edit" mode.
await page.getByRole( 'button', { name: 'Edit' } ).click();

// Open Advanced Settings
await page
.getByRole( 'region', {
name: 'Editor content',
} )
.getByRole( 'button', {
name: 'Advanced',
} )
.click();

// expect settings for `Open in new tab` and `No follow`
await expect( page.getByLabel( 'Open in new tab' ) ).not.toBeChecked();
await expect( page.getByLabel( 'nofollow' ) ).not.toBeChecked();

// Toggle both of the settings
await page.getByLabel( 'Open in new tab' ).click();
await page.getByLabel( 'nofollow' ).click();

// Save the link
await page
.locator( '.block-editor-link-control' )
.getByRole( 'button', { name: 'Save' } )
.click();

// Expect correct attributes to be set on the underlying link.
await expect.poll( editor.getBlocks ).toMatchObject( [
{
name: 'core/paragraph',
attributes: {
content: `<a href="https://wordpress.org/gutenberg" target="_blank" rel="noreferrer noopener nofollow">Gutenberg</a>`,
},
},
] );

// Move caret back into the link.
await page.keyboard.press( 'ArrowRight' );
await page.keyboard.press( 'ArrowRight' );

// Edit the link
await page.getByRole( 'button', { name: 'Edit' } ).click();

// Toggle both the settings to be off.
// Note: no need to toggle settings again because the open setting should be persisted.
await page.getByLabel( 'Open in new tab' ).click();
await page.getByLabel( 'nofollow' ).click();

// Save the link
await page
.locator( '.block-editor-link-control' )
.getByRole( 'button', { name: 'Save' } )
.click();

// Expect correct attributes to be set on the underlying link.
await expect.poll( editor.getBlocks ).toMatchObject( [
{
name: 'core/paragraph',
attributes: {
content: `<a href="https://wordpress.org/gutenberg">Gutenberg</a>`,
},
},
] );
} );
} );

1 comment on commit 6d77fd2

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flaky tests detected in 6d77fd2.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/6037197246
📝 Reported issues:

Please sign in to comment.