diff --git a/packages/docusaurus-utils/src/__tests__/urlUtils.test.ts b/packages/docusaurus-utils/src/__tests__/urlUtils.test.ts index fc9cf1662032..4ad32a214771 100644 --- a/packages/docusaurus-utils/src/__tests__/urlUtils.test.ts +++ b/packages/docusaurus-utils/src/__tests__/urlUtils.test.ts @@ -277,6 +277,15 @@ describe('toURLPath', () => { hash: '', }); }); + + it('pathname + hash containing a question mark (no query)', () => { + const url = parseURLOrPath('/pathname#hash?notquery'); + expect(toURLPath(url)).toEqual({ + pathname: '/pathname', + search: undefined, + hash: 'hash?notquery', + }); + }); }); describe('parseLocalURLPath', () => { diff --git a/packages/docusaurus-utils/src/urlUtils.ts b/packages/docusaurus-utils/src/urlUtils.ts index 52c2ec7445b4..0b661ce3d6cc 100644 --- a/packages/docusaurus-utils/src/urlUtils.ts +++ b/packages/docusaurus-utils/src/urlUtils.ts @@ -177,13 +177,17 @@ export type URLPath = {pathname: string; search?: string; hash?: string}; export function toURLPath(url: URL): URLPath { const {pathname} = url; + // Only the part before the fragment can contain the query string. A "?" + // inside the hash (e.g. "/foo#bar?baz") must not be read as an empty query. + const beforeHash = url.hash ? url.href.slice(0, -url.hash.length) : url.href; + // Fixes annoying url.search behavior // "" => undefined // "?" => "" // "?param => "param" const search = url.search ? url.search.slice(1) - : url.href.includes('?') + : beforeHash.includes('?') ? '' : undefined;