From 1cb730396fb61edb90df6c4d94b75c57e111f1e7 Mon Sep 17 00:00:00 2001 From: Hayden Costa <97135207+costh-netm@users.noreply.github.com> Date: Fri, 30 Jun 2023 11:48:50 +0100 Subject: [PATCH] feat: add base as option (#81) * Add base element as an option * Add automatically generated api documentation * Update e2e tests and override unit test --- ...atsby-plugin-next-seo.baseseoprops.base.md | 13 ++++++++++ .../gatsby-plugin-next-seo.baseseoprops.md | 1 + docs/api/gatsby-plugin-next-seo.gatsbyseo.md | 2 +- docs/etc/gatsby-plugin-next-seo.api.md | 9 ++++++- e2e/__tests__/seo.e2e.ts | 8 +++++++ example/gatsby-config.js | 4 ++++ example/src/pages/overridden.tsx | 4 ++++ .../__snapshots__/base-seo.test.tsx.snap | 5 ++++ src/meta/__tests__/base-seo.test.tsx | 24 +++++++++++++++++++ src/meta/base-seo.tsx | 4 ++++ src/meta/gatsby-seo.tsx | 3 +++ src/types.ts | 9 +++++++ 12 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 docs/api/gatsby-plugin-next-seo.baseseoprops.base.md diff --git a/docs/api/gatsby-plugin-next-seo.baseseoprops.base.md b/docs/api/gatsby-plugin-next-seo.baseseoprops.base.md new file mode 100644 index 0000000..3d250dd --- /dev/null +++ b/docs/api/gatsby-plugin-next-seo.baseseoprops.base.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [gatsby-plugin-next-seo](./gatsby-plugin-next-seo.md) > [BaseSeoProps](./gatsby-plugin-next-seo.baseseoprops.md) > [base](./gatsby-plugin-next-seo.baseseoprops.base.md) + +## BaseSeoProps.base property + +Specifies the base URL to use for all relative URLs in a document. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base + +Signature: + +```typescript +base?: BaseProps; +``` diff --git a/docs/api/gatsby-plugin-next-seo.baseseoprops.md b/docs/api/gatsby-plugin-next-seo.baseseoprops.md index f8e9c23..5d37c43 100644 --- a/docs/api/gatsby-plugin-next-seo.baseseoprops.md +++ b/docs/api/gatsby-plugin-next-seo.baseseoprops.md @@ -15,6 +15,7 @@ export interface BaseSeoProps | Property | Type | Description | | --- | --- | --- | +| [base](./gatsby-plugin-next-seo.baseseoprops.base.md) | BaseProps | Specifies the base URL to use for all relative URLs in a document. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base | | [canonical](./gatsby-plugin-next-seo.baseseoprops.canonical.md) | string | Set the page canonical url. | | [description](./gatsby-plugin-next-seo.baseseoprops.description.md) | string | Set the page meta description. | | [facebook](./gatsby-plugin-next-seo.baseseoprops.facebook.md) | { appId: string; } | Used for Facebook Insights, you must add a facebook app ID to your page to for it. | diff --git a/docs/api/gatsby-plugin-next-seo.gatsbyseo.md b/docs/api/gatsby-plugin-next-seo.gatsbyseo.md index 791bb01..2f7a8f7 100644 --- a/docs/api/gatsby-plugin-next-seo.gatsbyseo.md +++ b/docs/api/gatsby-plugin-next-seo.gatsbyseo.md @@ -9,7 +9,7 @@ This component render the tags in the `` for SEO on a per page basis. As a Signature: ```typescript -GatsbySeo: ({ metaTags, linkTags, canonical, description, facebook, htmlAttributes, language, languageAlternates, mobileAlternate, nofollow, noindex, openGraph, title, titleTemplate, twitter, }: GatsbySeoProps) => JSX.Element +GatsbySeo: ({ metaTags, linkTags, canonical, description, facebook, htmlAttributes, language, languageAlternates, mobileAlternate, nofollow, noindex, openGraph, title, titleTemplate, twitter, base, }: GatsbySeoProps) => JSX.Element ``` ## Remarks diff --git a/docs/etc/gatsby-plugin-next-seo.api.md b/docs/etc/gatsby-plugin-next-seo.api.md index 16f3abf..0876855 100644 --- a/docs/etc/gatsby-plugin-next-seo.api.md +++ b/docs/etc/gatsby-plugin-next-seo.api.md @@ -60,11 +60,18 @@ export interface ArticleJsonLdProps extends DeferSeoProps, Overrides
{ url: string; } +// Warning: (ae-internal-missing-underscore) The name "BaseProps" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal (undocumented) +export type BaseProps = JSX.IntrinsicElements['base']; + // @public export const BaseSeo: ({ defer, metaTags, linkTags, ...props }: AllSeoProps) => JSX.Element; // @public (undocumented) export interface BaseSeoProps { + // Warning: (ae-incompatible-release-tags) The symbol "base" is marked as @public, but its signature references "BaseProps" which is marked as @internal + base?: BaseProps; canonical?: string; description?: string; facebook?: { @@ -216,7 +223,7 @@ export interface FAQJsonLdProps extends DeferSeoProps, Overrides { } // @public -export const GatsbySeo: ({ metaTags, linkTags, canonical, description, facebook, htmlAttributes, language, languageAlternates, mobileAlternate, nofollow, noindex, openGraph, title, titleTemplate, twitter, }: GatsbySeoProps) => JSX.Element; +export const GatsbySeo: ({ metaTags, linkTags, canonical, description, facebook, htmlAttributes, language, languageAlternates, mobileAlternate, nofollow, noindex, openGraph, title, titleTemplate, twitter, base, }: GatsbySeoProps) => JSX.Element; // @public (undocumented) export interface GatsbySeoPluginOptions extends DefaultSeoProps, BaseSeoProps { diff --git a/e2e/__tests__/seo.e2e.ts b/e2e/__tests__/seo.e2e.ts index 358d761..bd6c0e5 100644 --- a/e2e/__tests__/seo.e2e.ts +++ b/e2e/__tests__/seo.e2e.ts @@ -9,6 +9,8 @@ test.each(testIterator)('Default SEO / - %s', async (_, disableJavascript) => { const $document = await launch({ disableJavascript, path: '/' }); const tagAssertions = [ { selector: 'h1', prop: 'innerText', result: 'Default SEO on this Page' }, + { selector: 'base', prop: 'href', result: 'http://www.test.com/' }, + { selector: 'base', prop: 'target', result: '_blank' }, { selector: 'head title', prop: 'innerText', @@ -116,6 +118,12 @@ test.each(testIterator)( const tagAssertions: TagAssertionBuilder[] = [ { selector: 'h1', prop: 'innerText', result: 'Overridden Seo' }, + { + selector: 'base', + prop: 'href', + result: 'http://www.overridetest.com/', + }, + { selector: 'base', prop: 'target', result: '_self' }, { selector: 'html', prop: 'lang', diff --git a/example/gatsby-config.js b/example/gatsby-config.js index 22c47b7..8fc83c7 100644 --- a/example/gatsby-config.js +++ b/example/gatsby-config.js @@ -14,6 +14,10 @@ module.exports = { { resolve: 'gatsby-plugin-next-seo', options: { + base: { + href: 'http://www.test.com', + target: '_blank', + }, title: 'Title A', titleTemplate: '%s | Gatsby SEO', description: 'Description A', diff --git a/example/src/pages/overridden.tsx b/example/src/pages/overridden.tsx index b5b861d..78664dc 100644 --- a/example/src/pages/overridden.tsx +++ b/example/src/pages/overridden.tsx @@ -9,6 +9,10 @@ const Overridden = () => ( noindex={true} nofollow={true} title='Title B' + base={{ + href: 'http://www.overridetest.com', + target: '_self', + }} description='Description B' canonical='https://www.canonical.ie/b' language='en' diff --git a/src/meta/__tests__/__snapshots__/base-seo.test.tsx.snap b/src/meta/__tests__/__snapshots__/base-seo.test.tsx.snap index 5fad357..61829c5 100644 --- a/src/meta/__tests__/__snapshots__/base-seo.test.tsx.snap +++ b/src/meta/__tests__/__snapshots__/base-seo.test.tsx.snap @@ -591,6 +591,11 @@ exports[`renders correctly 1`] = ` This is a test title. + { SEO.language, ); + expect(document.querySelector('base')?.getAttribute('href')).toBe( + SEO?.base?.href, + ); + expect(document.querySelector('base')?.getAttribute('target')).toBe( + SEO?.base?.target, + ); + const title = getByText( document.documentElement, (content, element) => @@ -315,9 +326,15 @@ test('BaseSeo respects the nesting/overriding behaviour of React Helmet', () => const title = 'Example Title'; const exampleUrlBase = 'https://example.com'; const exampleUrlOverride = 'https://examp2le.com'; + const exampleBaseHrefOverride = 'https://overridetest.com'; + const exampleBaseTargetOverride = '_self'; render( <> ); expect(ogUrlTag).toBeTruthy(); expect(ogUrlTag?.getAttribute('content')).toEqual(exampleUrlOverride); + + expect(document.querySelector('base')?.getAttribute('href')).toBe( + exampleBaseHrefOverride, + ); + expect(document.querySelector('base')?.getAttribute('target')).toBe( + exampleBaseTargetOverride, + ); }); const ArticleSEO = { diff --git a/src/meta/base-seo.tsx b/src/meta/base-seo.tsx index 6c628a7..100dab9 100644 --- a/src/meta/base-seo.tsx +++ b/src/meta/base-seo.tsx @@ -479,6 +479,10 @@ export const BaseSeo = ({ helmetProps['titleTemplate'] = props.titleTemplate; } + if (props.base) { + helmetProps['base'] = props.base; + } + return ( <> diff --git a/src/meta/gatsby-seo.tsx b/src/meta/gatsby-seo.tsx index 5c8fb44..74a1ca0 100644 --- a/src/meta/gatsby-seo.tsx +++ b/src/meta/gatsby-seo.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ import React from 'react'; import { GatsbySeoProps } from '../types'; @@ -39,6 +40,7 @@ export const GatsbySeo = ({ title, titleTemplate, twitter, + base, }: GatsbySeoProps) => { return ( ); }; diff --git a/src/types.ts b/src/types.ts index 03ca5d1..3fd1a1d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -244,6 +244,11 @@ interface HTMLAttributes { * @public */ export interface BaseSeoProps { + /** + * Specifies the base URL to use for all relative URLs in a document. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base + */ + base?: BaseProps; + /** * The language being used for the current page. * @@ -592,3 +597,7 @@ export type StyleProps = JSX.IntrinsicElements['style']; * @internal */ export type TitleProps = JSX.IntrinsicElements['title']; +/** + * @internal + */ +export type BaseProps = JSX.IntrinsicElements['base'];