diff --git a/.changesets/10677.md b/.changesets/10677.md new file mode 100644 index 000000000000..c97de900eb7a --- /dev/null +++ b/.changesets/10677.md @@ -0,0 +1,6 @@ +- Adds `searchParams` option to `useOgImage()` hook for adding arbitrary query string vars to generated URL (#10677) by @cannikin + +``` +const { url } = useOgImage({ searchParams: { foo: 'bar' }) +console.log(url) // => http://localhost:8910/photo.png?foo=bar +``` diff --git a/packages/ogimage-gen/src/hooks.test.ts b/packages/ogimage-gen/src/hooks.test.ts index 29f425a9f76c..ca43594b693d 100644 --- a/packages/ogimage-gen/src/hooks.test.ts +++ b/packages/ogimage-gen/src/hooks.test.ts @@ -101,6 +101,48 @@ describe('useOgImage', () => { expect(url).toBe('http://localhost/about.png?foo=bar') }) + test('can include additional query variables in the form of URLSearchParams', () => { + mockLocation.mockReturnValue({ + origin: 'http://localhost', + pathname: '/about', + searchParams: new URLSearchParams('foo=bar'), + }) + + const { url } = useOgImage({ + searchParams: new URLSearchParams({ baz: 'qux' }), + }) + + expect(url).toBe('http://localhost/about.png?foo=bar&baz=qux') + }) + + test('can include additional query variables in the form of an object', () => { + mockLocation.mockReturnValue({ + origin: 'http://localhost', + pathname: '/about', + searchParams: new URLSearchParams('foo=bar'), + }) + + const { url } = useOgImage({ + searchParams: { baz: 'qux' }, + }) + + expect(url).toBe('http://localhost/about.png?foo=bar&baz=qux') + }) + + test('searchParams should override existing query variables', () => { + mockLocation.mockReturnValue({ + origin: 'http://localhost', + pathname: '/about', + searchParams: new URLSearchParams('foo=bar'), + }) + + const { url } = useOgImage({ + searchParams: { foo: 'baz' }, + }) + + expect(url).toBe('http://localhost/about.png?foo=baz') + }) + test('allows setting a custom extension', () => { mockLocation.mockReturnValue({ origin: 'http://localhost', @@ -166,10 +208,11 @@ describe('useOgImage', () => { width: 1024, height: 768, quality: 75, + searchParams: new URLSearchParams({ baz: 'qux' }), }) expect(url).toBe( - 'http://localhost/user/1.png?foo=bar&width=1024&height=768&quality=75', + 'http://localhost/user/1.png?foo=bar&baz=qux&width=1024&height=768&quality=75', ) expect(width).toBe(1024) expect(height).toBe(768) diff --git a/packages/ogimage-gen/src/hooks.ts b/packages/ogimage-gen/src/hooks.ts index 1b414daace85..e13af2988965 100644 --- a/packages/ogimage-gen/src/hooks.ts +++ b/packages/ogimage-gen/src/hooks.ts @@ -5,6 +5,7 @@ export type OgImageUrlOptions = { width?: number height?: number quality?: number + searchParams?: URLSearchParams | Record } export const OGIMAGE_DEFAULTS = { @@ -15,11 +16,20 @@ export const OGIMAGE_DEFAULTS = { } export const useOgImage = (options?: OgImageUrlOptions) => { - const { origin, pathname, searchParams } = useLocation() + const { origin, pathname, searchParams: locationSearchParams } = useLocation() const ext = options?.extension || OGIMAGE_DEFAULTS.extension const width = options?.width const height = options?.height const quality = options?.quality + const searchParams = + options?.searchParams instanceof URLSearchParams + ? options?.searchParams + : new URLSearchParams(options?.searchParams || {}) + const outputSearchParams = new URLSearchParams({ + ...Object.fromEntries(locationSearchParams), + ...Object.fromEntries(searchParams), + }) + const output = [origin] // special case if we're at the root, image is available at /index.ext @@ -32,18 +42,18 @@ export const useOgImage = (options?: OgImageUrlOptions) => { output.push(`.${ext}`) if (width) { - searchParams.append('width', width.toString()) + outputSearchParams.append('width', width.toString()) } if (height) { - searchParams.append('height', height.toString()) + outputSearchParams.append('height', height.toString()) } if (quality) { - searchParams.append('quality', quality.toString()) + outputSearchParams.append('quality', quality.toString()) } // only append search params if there are any, so we don't up with a trailing `?` - if (searchParams.size) { - output.push(`?${searchParams}`) + if (outputSearchParams.size) { + output.push(`?${outputSearchParams}`) } return {