Skip to content

Conversation

@hbhalodia
Copy link
Contributor

What?

Closes #73872

Why?

  • PR ensure that, whatever is added in rel should be kept as is on pasting when we have target="_blank", it should not strip the rel attributes.

How?

  • Checks if we have rel attribute, use that, else fallback to default rel value.

Testing Instructions

  1. Open any post/page.
  2. Paste the link you copied with rel and target blank as shown in issue Gutenberg strips the rel='nofollow' in links when copying content #73872.
  3. Save post and check on frontend, the rel should have same value which you copied.

Testing Instructions for Keyboard

  • None

Screenshots or screencast

Screen.Recording.2025-12-31.at.3.52.56.PM.mov

@github-actions github-actions bot added the [Package] Blocks /packages/blocks label Dec 31, 2025
@github-actions
Copy link

github-actions bot commented Dec 31, 2025

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Unlinked Accounts

The following contributors have not linked their GitHub and WordPress.org accounts: @diffray-bot.

Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Unlinked contributors: diffray-bot.

Co-authored-by: hbhalodia <[email protected]>
Co-authored-by: t-hamano <[email protected]>
Co-authored-by: ellatrix <[email protected]>
Co-authored-by: BlackStar1991 <[email protected]>
Co-authored-by: alanjacobmathew <[email protected]>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@hbhalodia hbhalodia requested a review from Copilot December 31, 2025 10:24
@github-actions
Copy link

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Required label: Any label starting with [Type].
  • Labels found: [Package] Blocks.

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes an issue where Gutenberg was stripping custom rel attributes (like rel="nofollow") from links when copying and pasting content with target="_blank".

Key Changes:

  • Modified the link processing logic to preserve existing rel attributes when target="_blank" is present
  • Only sets default rel="noreferrer noopener" when the rel attribute is missing or empty

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@diffray-bot
Copy link

Changes Summary

This PR fixes issue #73872 by modifying the link attribute handling in raw HTML content. When a link has target="_blank", the code now preserves existing rel attributes (like 'nofollow') while ensuring 'noreferrer' and 'noopener' are always included for security. Previously, any existing rel value would be completely replaced with only 'noreferrer noopener'.

Type: bugfix

Components Affected: Raw HTML handling - Phrasing content reducer, Link (anchor) element processing

Files Changed
File Summary Change Impact
...rc/api/raw-handling/phrasing-content-reducer.js Updated link handling logic to preserve existing rel attributes while guaranteeing noreferrer and noopener are present when target='_blank' ✏️ 🟡
...i/raw-handling/test/phrasing-content-reducer.js Added test case to verify existing rel attributes are preserved and merged with security-required attributes ✏️ 🟢

Risk Areas: Security attribute handling: The logic ensures noreferrer/noopener are always present, maintaining security posture, Attribute deduplication: Uses Set to remove duplicates but filters noreferrer/noopener separately - ensure this handles all edge cases, HTML sanitization: This is part of raw HTML content handling which is security-critical in a content management system

Suggestions
  • Verify the regex split pattern /\s+/ handles all HTML whitespace correctly (tabs, newlines, etc.)
  • Consider adding test cases for edge cases: multiple spaces, tabs, duplicate rel values like 'nofollow nofollow'
  • Document the precedence: noreferrer/noopener are added first, then user-provided rel values - this is the intended behavior

Full review in progress... | Powered by diffray

Comment on lines 46 to +51
// In jsdom-jscore, 'node.target' can be null.
// TODO: Explore fixing this by patching jsdom-jscore.
if ( node.target && node.target.toLowerCase() === '_blank' ) {
node.rel = 'noreferrer noopener';
const existingRels = ( node.rel || '' )
.split( /\s+/ )
.filter( Boolean );

Choose a reason for hiding this comment

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

🔴 CRITICAL - Unsafe textDecoration.includes() - undefined dereference
Agent: bugs

Category: bug

Description:
The code calls .includes() on textDecoration without checking if it's undefined. When textDecoration is not set in the style, this throws TypeError.

Suggestion:
Add a null/undefined check before calling .includes(): if (textDecorationLine === 'line-through' || (textDecoration && textDecoration.includes('line-through')))

Why this matters: Null references cause runtime crashes and unexpected behavior.

Confidence: 95%
Rule: bug_null_pointer
Review ID: ced57fa9-b348-43a4-a5aa-efb8247c8512
Rate it 👍 or 👎 to improve future reviews | Powered by diffray

Comment on lines +64 to +72
it( 'should preserve existing rel attribute when target is _blank', () => {
const input =
'<a href="https://wordpress.org" target="_blank" rel="nofollow noopener">WordPress</a>';
const output =
'<a href="https://wordpress.org" target="_blank" rel="noreferrer noopener nofollow">WordPress</a>';
expect(
deepFilterHTML( input, [ phrasingContentReducer ], {} )
).toEqual( output );
} );

Choose a reason for hiding this comment

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

🟡 MEDIUM - Missing test: duplicate rel values deduplication
Agent: testing

Category: quality

Description:
The code uses Array.from(new Set()) to deduplicate rel values but no test verifies this behavior.

Suggestion:
Add test case with duplicate rel values like 'nofollow nofollow' to verify deduplication works correctly.

Why this matters: New parameters without tests are a regression risk and indicate incomplete PR.

Confidence: 70%
Rule: test_new_parameter_coverage
Review ID: ced57fa9-b348-43a4-a5aa-efb8247c8512
Rate it 👍 or 👎 to improve future reviews | Powered by diffray

@diffray-bot
Copy link

Review Summary

Free public review - Want AI code reviews on your PRs? Check out diffray.ai

Validated 5 issues: 3 kept (1 critical bug, 2 test coverage), 2 filtered (low-value performance/style)

Issues Found: 3

💬 See 2 individual line comment(s) for details.

📊 2 unique issue type(s) across 3 location(s)

📋 Full issue list (click to expand)

🔴 CRITICAL - Unsafe textDecoration.includes() - undefined dereference

Agent: bugs

Category: bug

Why this matters: Null references cause runtime crashes and unexpected behavior.

File: packages/blocks/src/api/raw-handling/phrasing-content-reducer.js:46-51

Description: The code calls .includes() on textDecoration without checking if it's undefined. When textDecoration is not set in the style, this throws TypeError.

Suggestion: Add a null/undefined check before calling .includes(): if (textDecorationLine === 'line-through' || (textDecoration && textDecoration.includes('line-through')))

Confidence: 95%

Rule: bug_null_pointer


🟡 MEDIUM - Missing test: duplicate rel values deduplication (2 occurrences)

Agent: testing

Category: quality

Why this matters: New parameters without tests are a regression risk and indicate incomplete PR.

📍 View all locations
File Description Suggestion Confidence
packages/blocks/src/api/raw-handling/test/phrasing-content-reducer.js:64-72 The code uses Array.from(new Set()) to deduplicate rel values but no test verifies this behavior. Add test case with duplicate rel values like 'nofollow nofollow' to verify deduplication works corre... 70%
packages/blocks/src/api/raw-handling/test/phrasing-content-reducer.js:1-91 Test only covers single additional rel value ('nofollow'), doesn't test preserving multiple custom r... Add test with multiple rel values like 'nofollow external sponsored' to verify all are preserved cor... 65%

Rule: test_new_parameter_coverage


ℹ️ 1 issue(s) outside PR diff (click to expand)

These issues were found in lines not modified in this PR.

🟡 MEDIUM - Missing test: multiple non-standard rel values

Agent: testing

Category: quality

Why this matters: New parameters without tests are a regression risk and indicate incomplete PR.

File: packages/blocks/src/api/raw-handling/test/phrasing-content-reducer.js:1-91

Description: Test only covers single additional rel value ('nofollow'), doesn't test preserving multiple custom rel values.

Suggestion: Add test with multiple rel values like 'nofollow external sponsored' to verify all are preserved correctly.

Confidence: 65%

Rule: test_new_parameter_coverage



Review ID: ced57fa9-b348-43a4-a5aa-efb8247c8512
Rate it 👍 or 👎 to improve future reviews | Powered by diffray

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Blocks /packages/blocks

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gutenberg strips the rel='nofollow' in links when copying content

2 participants