From: Eduardo San Martin Morote Date: Wed, 20 May 2020 10:18:53 +0000 (+0200) Subject: fix(hash): use location.pathname X-Git-Tag: v4.0.0-alpha.13~58 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=007814745dd98bb8cfa53f44d5c308193b2fbb60;p=thirdparty%2Fvuejs%2Frouter.git fix(hash): use location.pathname Fix #261 --- diff --git a/__tests__/history/hash.spec.ts b/__tests__/history/hash.spec.ts index 50cfcdc9..33305afa 100644 --- a/__tests__/history/hash.spec.ts +++ b/__tests__/history/hash.spec.ts @@ -37,10 +37,18 @@ describe('History Hash', () => { }) it('should use a correct base', () => { + dom.reconfigure({ url: 'https://esm.dev' }) + console.log(location.host, location.pathname) createWebHashHistory() + // starts with a `/` expect(createWebHistory).toHaveBeenCalledWith('/#') }) + it('does not append a # if the user provides one', () => { + createWebHashHistory('/#/app') + expect(createWebHistory).toHaveBeenCalledWith('/#/app') + }) + it('should be able to provide a base', () => { createWebHashHistory('/folder/') expect(createWebHistory).toHaveBeenCalledWith('/folder/#') @@ -58,6 +66,26 @@ describe('History Hash', () => { createWebHashHistory('/bar/') expect(createWebHistory).toHaveBeenCalledWith('/bar/#') }) + + describe('url with pathname', () => { + it('keeps the pathname as base', () => { + dom.reconfigure({ url: 'https://esm.dev/subfolder' }) + createWebHashHistory() + expect(createWebHistory).toHaveBeenCalledWith('/subfolder#') + }) + + it('keeps the pathname without a trailing slash as base', () => { + dom.reconfigure({ url: 'https://esm.dev/subfolder#/foo' }) + createWebHashHistory() + expect(createWebHistory).toHaveBeenCalledWith('/subfolder#') + }) + + it('keeps the pathname with trailing slash as base', () => { + dom.reconfigure({ url: 'https://esm.dev/subfolder/#/foo' }) + createWebHashHistory() + expect(createWebHistory).toHaveBeenCalledWith('/subfolder/#') + }) + }) }) describe('file://', () => { @@ -68,9 +96,7 @@ describe('History Hash', () => { it('should use a correct base', () => { createWebHashHistory() // both, a trailing / and none work - expect(createWebHistory).toHaveBeenCalledWith( - expect.stringMatching(/^#\/?$/) - ) + expect(createWebHistory).toHaveBeenCalledWith('/usr/some-file.html#') }) }) }) diff --git a/__tests__/history/html5.spec.ts b/__tests__/history/html5.spec.ts index 03f2b0e1..026bed02 100644 --- a/__tests__/history/html5.spec.ts +++ b/__tests__/history/html5.spec.ts @@ -74,4 +74,35 @@ describe('History HTMl5', () => { expect(createWebHistory('#/bar').base).toBe('#/bar') expect(createWebHistory('#/bar/').base).toBe('#/bar') }) + + it('prepends the host to support // urls', () => { + let history = createWebHistory() + let spy = jest.spyOn(window.history, 'pushState') + history.push('/foo') + expect(spy).toHaveBeenCalledWith( + expect.anything(), + expect.any(String), + 'https://example.com/foo' + ) + history.push('//foo') + expect(spy).toHaveBeenLastCalledWith( + expect.anything(), + expect.any(String), + 'https://example.com//foo' + ) + spy.mockRestore() + }) + + it('works with file:/// urls and a base', () => { + dom.reconfigure({ url: 'file:///usr/etc/index.html' }) + let history = createWebHistory('/usr/etc/index.html#/') + let spy = jest.spyOn(window.history, 'pushState') + history.push('/foo') + expect(spy).toHaveBeenCalledWith( + expect.anything(), + expect.any(String), + 'file:///usr/etc/index.html#/foo' + ) + spy.mockRestore() + }) }) diff --git a/__tests__/utils.ts b/__tests__/utils.ts index 655adcb3..225eca37 100644 --- a/__tests__/utils.ts +++ b/__tests__/utils.ts @@ -94,7 +94,7 @@ export function createDom(options?: ConstructorOptions) { const dom = new JSDOM( ``, { - url: 'https://example.org/', + url: 'https://example.com/', referrer: 'https://example.com/', contentType: 'text/html', ...options, diff --git a/src/history/hash.ts b/src/history/hash.ts index 5b801540..15bba544 100644 --- a/src/history/hash.ts +++ b/src/history/hash.ts @@ -4,9 +4,31 @@ import { createWebHistory } from './html5' /** * Creates a hash history. * - * @param base - optional base to provide. Defaults to `/` + * @param base - optional base to provide. Defaults to `location.pathname` or + * `/` if at root. If there is a `base` tag in the `head`, its value will be + * **ignored**. + * + * @example + * ```js + * // at https://example.com/folder + * createWebHashHistory() // gives a url of `https://example.com/folder#` + * createWebHashHistory('/folder/') // gives a url of `https://example.com/folder/#` + * // if the `#` is provided in the base, it won't be added by `createWebHashHistory` + * createWebHashHistory('/folder/#/app/') // gives a url of `https://example.com/folder/#/app/` + * // you should avoid doing this because it changes the original url and breaks copying urls + * createWebHashHistory('/other-folder/') // gives a url of `https://example.com/other-folder/#` + * + * // at file:///usr/etc/folder/index.html + * // for locations with no `host`, the base is ignored + * createWebHashHistory('/iAmIgnored') // gives a url of `file:///usr/etc/folder/index.html#` + * ``` */ -export function createWebHashHistory(base: string = '/'): RouterHistory { +export function createWebHashHistory(base?: string): RouterHistory { // Make sure this implementation is fine in terms of encoding, specially for IE11 - return createWebHistory(location.host ? base + '#' : '#') + // for `file://`, directly use the pathname and ignore the base + // location.pathname contains an initial `/` even at the root: `https://example.com` + base = location.host ? base || location.pathname : location.pathname + // allow the user to provide a `#` in the middle: `/base/#/app` + if (base.indexOf('#') < 0) base += '#' + return createWebHistory(base) }