Skip to content

Embeds: Skip autoembed processing inside <pre> and <code> tags#12646

Open
HasnainAshfaq wants to merge 5 commits into
WordPress:trunkfrom
HasnainAshfaq:feature/39472-autoembed-skip-pre-code
Open

Embeds: Skip autoembed processing inside <pre> and <code> tags#12646
HasnainAshfaq wants to merge 5 commits into
WordPress:trunkfrom
HasnainAshfaq:feature/39472-autoembed-skip-pre-code

Conversation

@HasnainAshfaq

Copy link
Copy Markdown

Summary

Fixes #39472. URLs inside <pre> and <code> blocks are meant to be displayed as literal text, but WordPress was converting them to embeds.

This fix protects <pre> and <code> block content with placeholders before URL detection runs, then restores the original content afterward — the same placeholder approach used by wpautop() for <pre> tags.

Trac ticket: https://core.trac.wordpress.org/ticket/39472

Changes

  • src/wp-includes/class-wp-embed.php: In WP_Embed::autoembed(), extract <pre> and <code> blocks into placeholders before URL scanning, restore them after.
  • tests/phpunit/tests/oembed/WpEmbed.php: Three new tests covering: URL in <pre> not embedded, URL in <code> not embedded, URL outside protected tags is still embedded.

Test plan

  • Run npm run test:php -- --filter test_autoembed — all 14 tests pass
  • Manually create a post with a YouTube URL inside a <code> block — confirm it renders as literal text, not an embed
  • Verify a YouTube URL outside <code>/<pre> still embeds normally

Adds a redirect from `/.well-known/change-password` to the user profile
page (`wp-admin/profile.php`) inside `wp_redirect_admin_locations()`.

Browsers and password managers use this well-known URL to help users
change their passwords. A `wp_change_password_url` filter is provided
for sites with custom user flows (e.g. membership plugins) to redirect
to a different URL.

Fixes #51173
- Add root-relative `/.well-known/change-password` to the match array
  so subdirectory installs (e.g. example.com/blog/) are also covered
- Fix test helper to use exception interception instead of empty-string
  filter return, preventing premature exit() from killing PHPUnit
- Correct trailing-slash test: untrailingslashit() normalises the URI
  so it does match and redirect (test now asserts the redirect fires)
- Use remove_filter() instead of remove_all_filters() in filter test

Fixes #51173
Aligns $filter assignment with surrounding variables per WPCS rules.

Fixes #51173
- Restore REQUEST_URI to truly unset state if it was not set before
  the test ran, rather than forcing it to an empty string
- Save and restore the original $wp_query->is_404 value in the helper
  instead of hard-coding false, preventing state leakage between tests
- Add assertNotNull() before assertStringContainsString() calls so a
  missing redirect produces a clear failure rather than a type error

Fixes #51173
URLs inside <pre> and <code> blocks are meant to be displayed as literal
text, not converted to embeds. This uses a placeholder approach (consistent
with wpautop's handling of <pre> tags) to protect those blocks before URL
detection and restore them after.

Fixes #39472
Copilot AI review requested due to automatic review settings July 22, 2026 13:57
@github-actions

Copy link
Copy Markdown

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.

Core Committers: Use this line as a base for the props when committing in SVN:

Props hasnainashfaq.

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

@github-actions

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

Copilot AI left a comment

Copy link
Copy Markdown

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 primarily updates WP_Embed::autoembed() to prevent URLs inside <pre> and <code> tags from being converted into embeds (per Trac #39472), by temporarily replacing those tag blocks with placeholders during URL detection and then restoring them. However, the PR also includes an unrelated canonical redirect feature and tests for /.well-known/change-password (ticket 51173), which does not match the PR title/description and should be split out.

Changes:

  • Update WP_Embed::autoembed() to placeholder-protect <pre>/<code> blocks during auto-embed URL scanning, then restore them.
  • Add PHPUnit coverage for “do not autoembed inside <pre>/<code>” and “still embed outside”.
  • Add /.well-known/change-password redirect handling and corresponding tests (appears out of scope for this PR).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
src/wp-includes/class-wp-embed.php Adds placeholder protection for <pre>/<code> content during autoembed URL detection.
tests/phpunit/tests/oembed/WpEmbed.php Adds tests for URLs inside <pre>/<code> not embedding, and URLs outside still embedding.
src/wp-includes/canonical.php Adds change-password well-known redirect + new filter (unrelated to embeds; likely accidental inclusion).
tests/phpunit/tests/canonical/changePassword.php Adds tests for the new change-password redirect behavior (unrelated to embeds).

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

Comment on lines +454 to +462
foreach ( array( 'pre', 'code' ) as $tag ) {
if ( str_contains( $content, "<$tag" ) ) {
$content = preg_replace_callback(
'#<' . $tag . '[\s>].*?</' . $tag . '>#is',
$protect_callback,
$content
);
}
}
Comment on lines +1071 to +1077
$password_change_urls = array(
'/.well-known/change-password',
home_url( '.well-known/change-password', 'relative' ),
site_url( '.well-known/change-password', 'relative' ),
);

if ( in_array( untrailingslashit( $_SERVER['REQUEST_URI'] ), $password_change_urls, true ) ) {
Comment on lines +3 to +11
/**
* Tests for the /.well-known/change-password redirect.
*
* @group canonical
* @group rewrite
* @group query
* @ticket 51173
*/
class Tests_Canonical_ChangePassword extends WP_UnitTestCase {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants