1+ /* eslint-disable @eslint-react/dom-no-dangerously-set-innerhtml -- The script is static; banner data is escaped in data attributes. */
2+
13import { availableLocales , defaultLocale } from '@node-core/website-i18n' ;
24import { Analytics } from '@vercel/analytics/react' ;
35import { SpeedInsights } from '@vercel/speed-insights/next' ;
@@ -7,14 +9,20 @@ import { NextIntlClientProvider } from 'next-intl';
79import BaseLayout from '#site/layouts/Base' ;
810import { VERCEL_ENV } from '#site/next.constants.mjs' ;
911import { IBM_PLEX_MONO , OPEN_SANS } from '#site/next.fonts' ;
12+ import { siteConfig } from '#site/next.json.mjs' ;
1013import { ThemeProvider } from '#site/providers/themeProvider' ;
14+ import { BANNER_DISMISSAL_STORAGE_KEY } from '#site/util/banner' ;
1115
1216import type { FC , PropsWithChildren } from 'react' ;
1317
1418import '#site/styles/index.css' ;
1519
1620const fontClasses = classNames ( IBM_PLEX_MONO . variable , OPEN_SANS . variable ) ;
1721
22+ const banner = siteConfig . websiteBanners . index ;
23+
24+ const bannerPreHydrationScript = `try{var s=document.currentScript;if(s&&localStorage.getItem(s.dataset.storageKey)===s.dataset.banner){document.documentElement.dataset.bannerDismissed='true'}}catch{}` ;
25+
1826type RootLayoutProps = PropsWithChildren < {
1927 params : Promise < { locale : string } > ;
2028} > ;
@@ -32,6 +40,15 @@ const RootLayout: FC<RootLayoutProps> = async ({ children, params }) => {
3240 lang = { hrefLang }
3341 suppressHydrationWarning
3442 >
43+ < head >
44+ { banner && (
45+ < script
46+ data-banner = { banner . text }
47+ data-storage-key = { BANNER_DISMISSAL_STORAGE_KEY }
48+ dangerouslySetInnerHTML = { { __html : bannerPreHydrationScript } }
49+ />
50+ ) }
51+ </ head >
3552 < body suppressHydrationWarning >
3653 < NextIntlClientProvider >
3754 < ThemeProvider >
0 commit comments