From dff37df3dcccb906d202d4691d8be6bd76f1e70d Mon Sep 17 00:00:00 2001 From: Tem Revil Date: Tue, 3 Nov 2026 01:53:12 +0200 Subject: [PATCH] fix(theme-classic): show a new announcement bar id on first load --- .../src/__tests__/inlineScripts.test.ts | 57 ++++++++++++++++++- .../docusaurus-theme-classic/src/index.ts | 9 ++- .../src/inlineScripts.ts | 7 +++ 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/packages/docusaurus-theme-classic/src/__tests__/inlineScripts.test.ts b/packages/docusaurus-theme-classic/src/__tests__/inlineScripts.test.ts index 2690e0b09c89..40f31bda9246 100644 --- a/packages/docusaurus-theme-classic/src/__tests__/inlineScripts.test.ts +++ b/packages/docusaurus-theme-classic/src/__tests__/inlineScripts.test.ts @@ -6,7 +6,10 @@ */ import {describe, expect, it} from 'vitest'; -import {getThemeInlineScript} from '../inlineScripts'; +import { + getAnnouncementBarInlineScript, + getThemeInlineScript, +} from '../inlineScripts'; describe('inlineScripts', () => { it('inline javascript for default options', () => { @@ -40,4 +43,56 @@ describe('inlineScripts', () => { }), ).toMatchSnapshot(); }); + + describe('getAnnouncementBarInlineScript', () => { + function runScript( + storage: Record, + announcementBarId: string, + ) { + const attributes: Record = {}; + const script = getAnnouncementBarInlineScript({ + siteStorage: {type: 'localStorage', namespace: ''}, + announcementBarId, + }); + new Function('localStorage', 'document', script)( + {getItem: (key: string) => storage[key] ?? null}, + { + documentElement: { + setAttribute: (name: string, value: string) => { + attributes[name] = value; + }, + }, + }, + ); + return String(attributes['data-announcement-bar-initially-dismissed']); + } + + it('is dismissed when the current announcement was dismissed', () => { + expect( + runScript( + { + 'docusaurus.announcement.dismiss': 'true', + 'docusaurus.announcement.id': 'announcement-1', + }, + 'announcement-1', + ), + ).toBe('true'); + }); + + it('is not dismissed when the announcement id changed', () => { + expect( + runScript( + { + 'docusaurus.announcement.dismiss': 'true', + 'docusaurus.announcement.id': 'announcement-1', + }, + 'announcement-2', + ), + ).toBe('false'); + }); + + it('is not dismissed for a first visit', () => { + expect(runScript({}, 'announcement-1')).toBe('false'); + }); + }); }); diff --git a/packages/docusaurus-theme-classic/src/index.ts b/packages/docusaurus-theme-classic/src/index.ts index 8c5a236835a3..c937a4733c59 100644 --- a/packages/docusaurus-theme-classic/src/index.ts +++ b/packages/docusaurus-theme-classic/src/index.ts @@ -134,7 +134,14 @@ export default function themeClassic( innerHTML: ` ${getThemeInlineScript({colorMode, siteStorage})} ${DataAttributeQueryStringInlineJavaScript} -${announcementBar ? getAnnouncementBarInlineScript({siteStorage}) : ''} +${ + announcementBar + ? getAnnouncementBarInlineScript({ + siteStorage, + announcementBarId: announcementBar.id, + }) + : '' +} `, }, ], diff --git a/packages/docusaurus-theme-classic/src/inlineScripts.ts b/packages/docusaurus-theme-classic/src/inlineScripts.ts index fe49094a52c4..2e2da848c4e3 100644 --- a/packages/docusaurus-theme-classic/src/inlineScripts.ts +++ b/packages/docusaurus-theme-classic/src/inlineScripts.ts @@ -76,14 +76,17 @@ export const DataAttributeQueryStringInlineJavaScript = ` // the announcement bar asap (before React hydration) export function getAnnouncementBarInlineScript({ siteStorage, + announcementBarId, }: { siteStorage: SiteStorage; + announcementBarId: string; }): string { // Duplicated constant. Unfortunately we can't import it from theme-common, as // we need to support older nodejs versions without ESM support // TODO: import from theme-common once we support Node.js with ESM support // + move all those announcementBar stuff there too const AnnouncementBarDismissStorageKey = `docusaurus.announcement.dismiss${siteStorage.namespace}`; + const AnnouncementBarIdStorageKey = `docusaurus.announcement.id${siteStorage.namespace}`; const AnnouncementBarDismissDataAttribute = 'data-announcement-bar-initially-dismissed'; @@ -91,6 +94,10 @@ export function getAnnouncementBarInlineScript({ return `(function() { function isDismissed() { try { + // A dismissal only applies to the announcement it was made for + if (localStorage.getItem('${AnnouncementBarIdStorageKey}') !== ${JSON.stringify(announcementBarId)}) { + return false; + } return localStorage.getItem('${AnnouncementBarDismissStorageKey}') === 'true'; } catch (err) {} return false;