diff --git a/apps/govuk-docs/package.json b/apps/govuk-docs/package.json index 2bd174a68..2303bb218 100644 --- a/apps/govuk-docs/package.json +++ b/apps/govuk-docs/package.json @@ -56,7 +56,7 @@ "plop": "3.1.2", "react": "16.14.0", "react-dom": "16.14.0", - "react-helmet-async": "1.3.0", + "react-helmet-async": "2.0.5", "react-router": "5.3.4", "react-router-dom": "5.3.4", "serverless": "3.39.0", diff --git a/apps/govuk-template/package.json b/apps/govuk-template/package.json index 12ce50bcf..3001afe59 100644 --- a/apps/govuk-template/package.json +++ b/apps/govuk-template/package.json @@ -60,7 +60,7 @@ "plop": "3.1.2", "react": "16.14.0", "react-dom": "16.14.0", - "react-helmet-async": "1.3.0", + "react-helmet-async": "2.0.5", "react-router": "5.3.4", "react-router-dom": "5.3.4", "serverless": "3.39.0", diff --git a/components/page/src/GovUKPage.tsx b/components/page/src/GovUKPage.tsx index 4814e99e4..107698cd5 100644 --- a/components/page/src/GovUKPage.tsx +++ b/components/page/src/GovUKPage.tsx @@ -1,5 +1,5 @@ import { FC, createElement as h } from 'react'; -import { Helmet } from 'react-helmet-async'; +import reactHelmetDefault, * as reactHelmetNamed from 'react-helmet-async'; import { Page, PageProps } from './Page'; import favicon from 'govuk-frontend/govuk/assets/images/favicon.ico'; @@ -12,6 +12,9 @@ import ogImage from 'govuk-frontend/govuk/assets/images/govuk-opengraph-image.pn import '../assets/GovUKPage.scss'; +const reactHelmet = reactHelmetDefault || reactHelmetNamed; +const { Helmet } = reactHelmet; + export type GovUKPageProps = Omit; export const GovUKPage: FC = ({ children, classModifiers, ...props }) => ( diff --git a/components/page/src/NotGovUKPage.tsx b/components/page/src/NotGovUKPage.tsx index 50a65e4a4..53190bd84 100644 --- a/components/page/src/NotGovUKPage.tsx +++ b/components/page/src/NotGovUKPage.tsx @@ -1,5 +1,5 @@ import { FC, createElement as h } from 'react'; -import { Helmet } from 'react-helmet-async'; +import reactHelmetDefault, * as reactHelmetNamed from 'react-helmet-async'; import { Page, PageProps } from './Page'; import favicon from '../assets/coat-favicon.ico'; @@ -11,6 +11,9 @@ import ogImage from '../assets/coat-opengraph-image.png'; import '../assets/NotGovUKPage.scss'; +const reactHelmet = reactHelmetDefault || reactHelmetNamed; +const { Helmet } = reactHelmet; + export type NotGovUKPageProps = Omit; export const NotGovUKPage: FC = ({ children, classModifiers, ...props }) => ( diff --git a/components/page/src/Page.tsx b/components/page/src/Page.tsx index e2f36a857..0d1647e33 100644 --- a/components/page/src/Page.tsx +++ b/components/page/src/Page.tsx @@ -1,5 +1,5 @@ import { FC, Fragment, HTMLProps, ReactNode, createElement as h } from 'react'; -import { Helmet } from 'react-helmet-async'; +import reactHelmetDefault, * as reactHelmetNamed from 'react-helmet-async'; import { BackLink } from '@not-govuk/back-link'; import { Breadcrumb, Breadcrumbs } from '@not-govuk/breadcrumbs'; import { StandardProps, classBuilder } from '@not-govuk/component-helpers'; @@ -12,6 +12,9 @@ import { WidthContainer } from '@not-govuk/width-container'; import '../assets/Page.scss'; +const reactHelmet = reactHelmetDefault || reactHelmetNamed; +const { Helmet } = reactHelmet; + export type PageProps = ( StandardProps & HTMLProps & diff --git a/lib/app-composer/src/index.ts b/lib/app-composer/src/index.ts index 7943f8e77..9a5c1e1c8 100644 --- a/lib/app-composer/src/index.ts +++ b/lib/app-composer/src/index.ts @@ -2,7 +2,7 @@ import { GraphQLSchema } from 'graphql'; import { ApolloClient, ApolloProvider, InMemoryCache, createHttpLink } from '@apollo/client'; import { SchemaLink } from '@apollo/client/link/schema'; import { ComponentType, Fragment, ReactNode, Suspense, createElement as h, lazy } from 'react'; -import { Helmet, HelmetProvider, FilledContext } from 'react-helmet-async'; +import { Helmet, HelmetProvider, HelmetServerState } from 'react-helmet-async'; import { StaticRouter, StaticRouterProps, Switch } from 'react-router'; import { BrowserRouter, BrowserRouterProps } from 'react-router-dom'; import { Route, RouteComponentProps, withRouter } from '@not-govuk/route-utils'; @@ -54,6 +54,10 @@ type ServerError = { message: string }; +export type HelmetDataContext = { + helmet: HelmetServerState +} + export type ApplicationPropsSSR = ApplicationPropsCommon & { pages: PageInfoSSR[] }; @@ -63,7 +67,7 @@ export type ApplicationProps = ApplicationPropsCSR | ApplicationPropsSSR; type ApplicationCSR = ComponentType; type ApplicationSSR = ComponentType & { extractDataCache: () => object - helmetContext: FilledContext + helmetContext: HelmetDataContext }; export type Application = ComponentType; @@ -304,7 +308,7 @@ export const compose: Compose = options => { return Object.assign(App, { extractDataCache, - helmetContext: helmetContext as FilledContext + helmetContext: helmetContext as HelmetDataContext }); }; diff --git a/lib/component-test-helpers/src/index.ts b/lib/component-test-helpers/src/index.ts index cb354786e..c8bfdf748 100644 --- a/lib/component-test-helpers/src/index.ts +++ b/lib/component-test-helpers/src/index.ts @@ -1,11 +1,14 @@ import { FC, ReactElement, ReactNode, createElement as h } from 'react'; -import { HelmetProvider } from 'react-helmet-async'; +import reactHelmetDefault, * as reactHelmetNamed from 'react-helmet-async'; import { MemoryRouter } from 'react-router'; import { render as _render, RenderOptions } from '@testing-library/react'; import userEventDefault from '@testing-library/user-event'; import '@testing-library/jest-dom'; +const reactHelmet = reactHelmetDefault || reactHelmetNamed; +const { HelmetProvider } = reactHelmet; + const Providers: FC<{ children?: ReactNode, routerProps?: object }> = ({ children, routerProps diff --git a/lib/server-renderer/package.json b/lib/server-renderer/package.json index 23c2ea4d1..870177fc6 100644 --- a/lib/server-renderer/package.json +++ b/lib/server-renderer/package.json @@ -32,7 +32,7 @@ "@types/react": "16.14.60", "@types/react-dom": "16.9.24", "graphql": "15.9.0", - "react-helmet-async": "1.3.0", + "react-helmet-async": "2.0.5", "typescript": "4.9.5" } } diff --git a/package.json b/package.json index c2c8304f8..e02f5e3b1 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "process": "^0.11.10", "react": "16.14.0", "react-dom": "16.14.0", - "react-helmet-async": "1.3.0", + "react-helmet-async": "2.0.5", "react-router": "5.3.4", "react-router-dom": "5.3.4", "ts-jest": "29.2.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1b4cdcd2b..fa690fd00 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -39,7 +39,7 @@ importers: process: ^0.11.10 react: 16.14.0 react-dom: 16.14.0 - react-helmet-async: 1.3.0 + react-helmet-async: 2.0.5 react-router: 5.3.4 react-router-dom: 5.3.4 ts-jest: 29.2.3 @@ -84,7 +84,7 @@ importers: process: 0.11.10 react: 16.14.0 react-dom: 16.14.0_react@16.14.0 - react-helmet-async: 1.3.0_wcqkhtmu7mswc6yz4uyexck3ty + react-helmet-async: 2.0.5_react@16.14.0 react-router: 5.3.4_react@16.14.0 react-router-dom: 5.3.4_react@16.14.0 ts-jest: 29.2.3_emrc4okhxugh6ej24zdudb2ocy @@ -119,7 +119,7 @@ importers: plop: 3.1.2 react: 16.14.0 react-dom: 16.14.0 - react-helmet-async: 1.3.0 + react-helmet-async: 2.0.5 react-router: 5.3.4 react-router-dom: 5.3.4 serverless: 3.39.0 @@ -154,7 +154,7 @@ importers: plop: 3.1.2 react: 16.14.0 react-dom: 16.14.0_react@16.14.0 - react-helmet-async: 1.3.0_wcqkhtmu7mswc6yz4uyexck3ty + react-helmet-async: 2.0.5_react@16.14.0 react-router: 5.3.4_react@16.14.0 react-router-dom: 5.3.4_react@16.14.0 serverless: 3.39.0 @@ -195,7 +195,7 @@ importers: plop: 3.1.2 react: 16.14.0 react-dom: 16.14.0 - react-helmet-async: 1.3.0 + react-helmet-async: 2.0.5 react-router: 5.3.4 react-router-dom: 5.3.4 serverless: 3.39.0 @@ -234,7 +234,7 @@ importers: plop: 3.1.2 react: 16.14.0 react-dom: 16.14.0_react@16.14.0 - react-helmet-async: 1.3.0_wcqkhtmu7mswc6yz4uyexck3ty + react-helmet-async: 2.0.5_react@16.14.0 react-router: 5.3.4_react@16.14.0 react-router-dom: 5.3.4_react@16.14.0 serverless: 3.39.0 @@ -1935,7 +1935,7 @@ importers: '@types/react': 16.14.60 '@types/react-dom': 16.9.24 graphql: 15.9.0 - react-helmet-async: 1.3.0 + react-helmet-async: 2.0.5 restify-errors: ^8.0.2 typescript: 4.9.5 dependencies: @@ -1947,7 +1947,7 @@ importers: '@types/react': 16.14.60 '@types/react-dom': 16.9.24 graphql: 15.9.0 - react-helmet-async: 1.3.0 + react-helmet-async: 2.0.5 typescript: 4.9.5 lib/storybook-preset: @@ -2144,8 +2144,8 @@ packages: es5-ext: 0.10.62 dev: true - /@adobe/css-tools/4.2.0: - resolution: {integrity: sha512-E09FiIft46CmH5Qnjb0wsW54/YQd69LsxeKUOWawmws1XWvyFGURnAChH0mlr7YPFR1ofwvUQfcL0J3lMxXqPA==} + /@adobe/css-tools/4.4.0: + resolution: {integrity: sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==} dev: false /@ampproject/remapping/2.2.0: @@ -9406,8 +9406,8 @@ packages: defer-to-connect: 2.0.1 dev: true - /@testing-library/dom/8.20.0: - resolution: {integrity: sha512-d9ULIT+a4EXLX3UU8FBjauG9NnsZHkHztXoIcTsOKoOw030fyjheN9svkTULjJxtYag9DZz5Jz5qkWZDPxTFwA==} + /@testing-library/dom/8.20.1: + resolution: {integrity: sha512-/DiOQ5xBxgdYRC8LNk7U+RWat0S3qRLeIw3ZIkMQ9kkVlRmwD/Eg8k8CqIpD6GW7u20JIUOfMKbxtiLutpjQ4g==} engines: {node: '>=12'} dependencies: '@babel/code-frame': 7.24.7 @@ -9416,7 +9416,7 @@ packages: aria-query: 5.1.3 chalk: 4.1.2 dom-accessibility-api: 0.5.16 - lz-string: 1.4.4 + lz-string: 1.5.0 pretty-format: 27.5.1 dev: false @@ -9424,9 +9424,9 @@ packages: resolution: {integrity: sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg==} engines: {node: '>=8', npm: '>=6', yarn: '>=1'} dependencies: - '@adobe/css-tools': 4.2.0 + '@adobe/css-tools': 4.4.0 '@babel/runtime': 7.21.0 - '@types/testing-library__jest-dom': 5.14.5 + '@types/testing-library__jest-dom': 5.14.9 aria-query: 5.1.3 chalk: 3.0.0 css.escape: 1.5.1 @@ -9443,7 +9443,7 @@ packages: react-dom: <18.0.0 dependencies: '@babel/runtime': 7.21.0 - '@testing-library/dom': 8.20.0 + '@testing-library/dom': 8.20.1 '@types/react-dom': 16.9.24 dev: false @@ -9859,8 +9859,8 @@ packages: /@types/tapable/1.0.8: resolution: {integrity: sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==} - /@types/testing-library__jest-dom/5.14.5: - resolution: {integrity: sha512-SBwbxYoyPIvxHbeHxTZX2Pe/74F/tX2/D3mMvzabdeJ25bBojfW0TyB8BHrbq/9zaaKICJZjLP+8r6AeZMFCuQ==} + /@types/testing-library__jest-dom/5.14.9: + resolution: {integrity: sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==} dependencies: '@types/jest': 29.5.12 dev: false @@ -16083,7 +16083,7 @@ packages: chalk: 4.1.2 diff-sequences: 29.4.3 jest-get-type: 29.4.3 - pretty-format: 29.5.0 + pretty-format: 29.7.0 /jest-diff/29.7.0: resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} @@ -16214,7 +16214,7 @@ packages: chalk: 4.1.2 jest-diff: 29.5.0 jest-get-type: 29.4.3 - pretty-format: 29.5.0 + pretty-format: 29.7.0 /jest-matcher-utils/29.7.0: resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} @@ -16236,7 +16236,7 @@ packages: chalk: 4.1.2 graceful-fs: 4.2.11 micromatch: 4.0.5 - pretty-format: 29.5.0 + pretty-format: 29.7.0 slash: 3.0.0 stack-utils: 2.0.6 @@ -17029,8 +17029,8 @@ packages: es5-ext: 0.10.62 dev: true - /lz-string/1.4.4: - resolution: {integrity: sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==} + /lz-string/1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true dev: false @@ -18706,7 +18706,6 @@ packages: '@jest/schemas': 29.6.3 ansi-styles: 5.2.0 react-is: 18.2.0 - dev: true /pretty-hrtime/1.0.3: resolution: {integrity: sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==} @@ -19037,35 +19036,28 @@ packages: resolution: {integrity: sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==} dev: false - /react-fast-compare/3.2.0: - resolution: {integrity: sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==} + /react-fast-compare/3.2.2: + resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} dev: true - /react-helmet-async/1.3.0: - resolution: {integrity: sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==} + /react-helmet-async/2.0.5: + resolution: {integrity: sha512-rYUYHeus+i27MvFE+Jaa4WsyBKGkL6qVgbJvSBoX8mbsWoABJXdEO0bZyi0F6i+4f0NuIb8AvqPMj3iXFHkMwg==} peerDependencies: react: ^16.6.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.6.0 || ^17.0.0 || ^18.0.0 dependencies: - '@babel/runtime': 7.21.0 invariant: 2.2.4 - prop-types: 15.8.1 - react-fast-compare: 3.2.0 + react-fast-compare: 3.2.2 shallowequal: 1.1.0 dev: true - /react-helmet-async/1.3.0_wcqkhtmu7mswc6yz4uyexck3ty: - resolution: {integrity: sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==} + /react-helmet-async/2.0.5_react@16.14.0: + resolution: {integrity: sha512-rYUYHeus+i27MvFE+Jaa4WsyBKGkL6qVgbJvSBoX8mbsWoABJXdEO0bZyi0F6i+4f0NuIb8AvqPMj3iXFHkMwg==} peerDependencies: react: ^16.6.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.6.0 || ^17.0.0 || ^18.0.0 dependencies: - '@babel/runtime': 7.21.0 invariant: 2.2.4 - prop-types: 15.8.1 react: 16.14.0 - react-dom: 16.14.0_react@16.14.0 - react-fast-compare: 3.2.0 + react-fast-compare: 3.2.2 shallowequal: 1.1.0 dev: true