diff --git a/src/prerender.d.ts b/src/prerender.d.ts index 49eb8ab..b9958bc 100644 --- a/src/prerender.d.ts +++ b/src/prerender.d.ts @@ -13,3 +13,5 @@ export default function prerender( vnode: VNode, options?: PrerenderOptions ): Promise; + +export function locationStub(path: string): void; diff --git a/src/prerender.js b/src/prerender.js index 49b841e..be435bf 100644 --- a/src/prerender.js +++ b/src/prerender.js @@ -40,3 +40,20 @@ export default async function prerender(vnode, options) { vnodeHook = null; } } + +/** + * Update `location` to current URL so routers can use things like `location.pathname` + * + * @param {string} path - current URL path + */ +export function locationStub(path) { + globalThis.location = {}; + const u = new URL(path, 'http://localhost'); + for (const i in u) { + try { + globalThis.location[i] = /to[A-Z]/.test(i) + ? u[i].bind(u) + : String(u[i]); + } catch {} + } +} diff --git a/test/location-stub.test.js b/test/location-stub.test.js new file mode 100644 index 0000000..e78b46d --- /dev/null +++ b/test/location-stub.test.js @@ -0,0 +1,36 @@ +import { describe, it, beforeEach, expect } from '@jest/globals'; +import { locationStub } from '../src/prerender.js'; + +describe('location-stub', () => { + beforeEach(() => { + if (globalThis.location) { + delete globalThis.location; + } + }); + + it('Contains all Location instance properties', () => { + locationStub('/foo/bar?baz=qux#quux'); + + [ + // 'ancestorOrigins', // Not supported by FireFox and sees little use, but we could add an empty val if it's needed + 'hash', + 'host', + 'hostname', + 'href', + 'origin', + 'pathname', + 'port', + 'protocol', + 'search', + ].forEach(key => { + expect(globalThis.location).toHaveProperty(key); + }); + }); + + // Do we need to support `assign`, `reload`, and/or `replace`? + it('Support bound methods', () => { + locationStub('/foo/bar?baz=qux#quux'); + + expect(globalThis.location.toString()).toBe('http://localhost/foo/bar?baz=qux#quux'); + }); +});