Leave fragment-only references alone when rewriting URLs - #320
Open
mauteri wants to merge 1 commit into
Open
Conversation
A reference like `#section` points within the document that contains it, so there is no origin to migrate. Resolving it against the base URL made it look like a child of the source site, and rewriting it turned an in-page anchor into `/#section` and a bare `#` into `/`. Blocks whose saved markup carries such an href then fail validation after an import. Mirrors WordPress/wordpress-importer#263. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
wp_rewrite_urls()resolves every URL against the base URL before consulting the mapping. A fragment-only reference like#sectionhas no host and no path, so after resolution it is indistinguishable from an ordinary same-site link,is_child_url_of()matches it, and it gets rewritten:<a href="#section"><a href="/#section"><a href="#"><a href="/"><!-- wp:button {"url":"#login"} --><!-- wp:button {"url":"\/#login"} -->An in-page anchor becomes a link to the site root, and a bare
#loses its fragment entirely. In the importer this also breaks block validation: any block whose saved markup carries such an href (accordions, tab and anchor navigation,#placeholders handled by JavaScript) no longer matches itssave()output after an import.The fix
Skip references whose raw value starts with
#before the cache and the mapping are consulted. The guard readsget_raw_url()on purpose, since parsing is what destroys the distinction. It is scoped to references that are only a fragment. A URL carrying a fragment alongside a host or path still rewrites and keeps its fragment (https://legacy-blog.com/page#sectionbecomeshttps://modern-webstore.org/page#section), and that case is in the tests as a control.Tests
Four cases added to
RewriteUrlsTest::provider_test_wp_rewrite_urls(). Without the guard the three fragment-only cases fail with exactly the rewrites above; the absolute-URL-with-fragment control passes with and without it.Context
This is the upstream half of WordPress/wordpress-importer#263, where the same change was made against the vendored copy under
src/php-toolkit/. Per @desrosj's review there, the toolkit should land it first and the importer then pick it up. It is a smallcontinueat the top of the loop inwp_rewrite_urls(), so it should rebase over #307 either way.Query-only references (
?filter=all) have the same shape and currently become/?filter=all. Left alone here to keep this to the reported behavior.🤖 Generated with Claude Code