From 2eb313194afcb1e09aced411ce355b18e283ce53 Mon Sep 17 00:00:00 2001 From: Zeno Kapitein Date: Mon, 22 Jun 2026 17:12:35 +0200 Subject: [PATCH] Remove old PageAction checks (#4333) --- .../[siteData]/~gitbook/mcp/handler.ts | 11 ++- .../components/DocumentView/Prompt/Prompt.tsx | 2 + .../src/components/PageBody/PageHeader.tsx | 68 +++++++++++++++---- 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/packages/gitbook/src/app/sites/dynamic/[mode]/[siteURL]/[siteData]/~gitbook/mcp/handler.ts b/packages/gitbook/src/app/sites/dynamic/[mode]/[siteURL]/[siteData]/~gitbook/mcp/handler.ts index 788a9e2e1..3d46aeb99 100644 --- a/packages/gitbook/src/app/sites/dynamic/[mode]/[siteURL]/[siteData]/~gitbook/mcp/handler.ts +++ b/packages/gitbook/src/app/sites/dynamic/[mode]/[siteURL]/[siteData]/~gitbook/mcp/handler.ts @@ -1,4 +1,4 @@ -import { SiteInsightsDisplayContext } from '@gitbook/api'; +import { CustomizationPageActionType, SiteInsightsDisplayContext } from '@gitbook/api'; import { type RouteLayoutParams, getDynamicSiteContext } from '@/app/utils'; import { getExposableError, throwIfDataError } from '@/lib/data'; @@ -20,7 +20,14 @@ export async function handleMcpRequest( const { context } = await getDynamicSiteContext(params); const { dataFetcher, linker, site } = context; - if (!context.customization.pageActions.mcp) { + // Use the configured `items` list when the API provides it, and fall back to the deprecated + // `mcp` flag otherwise (legacy mode), since this endpoint is called directly and cannot rely on + // any page-rendering fallback. + const { pageActions } = context.customization; + const isMcpEnabled = pageActions.items + ? pageActions.items.includes(CustomizationPageActionType.Mcp) + : pageActions.mcp; + if (!isMcpEnabled) { return new Response('Not Found', { status: 404 }); } diff --git a/packages/gitbook/src/components/DocumentView/Prompt/Prompt.tsx b/packages/gitbook/src/components/DocumentView/Prompt/Prompt.tsx index dc214406a..db8574405 100644 --- a/packages/gitbook/src/components/DocumentView/Prompt/Prompt.tsx +++ b/packages/gitbook/src/components/DocumentView/Prompt/Prompt.tsx @@ -53,6 +53,8 @@ function getOpenInAIProviders(props: BlockProps): boolean { function isExternalAIPageActionEnabled( pageActions: SiteCustomizationSettings['pageActions'] ): boolean { + // Use the configured `items` list when the API provides it, and fall back to the deprecated + // `externalAI` flag otherwise (legacy mode). return pageActions.items ? pageActions.items.includes(CustomizationPageActionType.ExternalAi) : pageActions.externalAI; diff --git a/packages/gitbook/src/components/PageBody/PageHeader.tsx b/packages/gitbook/src/components/PageBody/PageHeader.tsx index d118de9ae..9e0bdda34 100644 --- a/packages/gitbook/src/components/PageBody/PageHeader.tsx +++ b/packages/gitbook/src/components/PageBody/PageHeader.tsx @@ -2,7 +2,12 @@ import type { GitBookSiteContext } from '@/lib/context'; import type { AncestorRevisionPage } from '@/lib/pages'; import { tcls } from '@/lib/tailwind'; import { getPageRSSURL } from '@/routes/rss'; -import { CustomizationAIMode, type RevisionPageDocument, SiteVisibility } from '@gitbook/api'; +import { + CustomizationAIMode, + CustomizationPageActionType, + type RevisionPageDocument, + SiteVisibility, +} from '@gitbook/api'; import { Icon } from '@gitbook/icons'; import urlJoin from 'url-join'; import { getPDFURLSearchParams } from '../PDF'; @@ -29,18 +34,18 @@ export async function PageHeader(props: { const pageActionsEnabled = page.layout.actions !== false; - // Show page actions if *any* of the actions are enabled - const hasPageActions = - pageActionsEnabled && - [ - context.customization.ai.mode === CustomizationAIMode.Assistant, - context.customization.pageActions.externalAI, - context.customization.pageActions.markdown, - context.customization.pageActions.mcp, - context.customization.pdf.enabled, - context.customization.git.showEditLink, - withRSSFeed, - ].some(Boolean); + // Show page actions if *any* of the configured actions are enabled, or if the RSS feed is + // available. RSS is contextual (only on update/blog index pages) and is not part of the + // configured `items` list, so it is checked separately. + const hasConfiguredPageActions = [ + CustomizationPageActionType.Assistant, + CustomizationPageActionType.ExternalAi, + CustomizationPageActionType.Markdown, + CustomizationPageActionType.Mcp, + CustomizationPageActionType.Pdf, + CustomizationPageActionType.Git, + ].some((type) => isPageActionEnabled(context.customization, type)); + const hasPageActions = pageActionsEnabled && (hasConfiguredPageActions || withRSSFeed); if (!page.layout.title && !page.layout.description && !hasPageActions) { return null; @@ -164,13 +169,15 @@ function getPageActionsURLs({ markdown: `${context.linker.toAbsoluteURL(context.linker.toPathInSpace(page.path))}.md`, rss: withRSSFeed ? getPageRSSURL(context, page) : undefined, editOnGit: - context.customization.git.showEditLink && context.space.gitSync?.url && page.git + isPageActionEnabled(context.customization, CustomizationPageActionType.Git) && + context.space.gitSync?.url && + page.git ? { provider: context.space?.gitSync?.installationProvider, url: urlJoin(context.space.gitSync.url, page.git.path), } : undefined, - pdf: context.customization.pdf.enabled + pdf: isPageActionEnabled(context.customization, CustomizationPageActionType.Pdf) ? context.linker.toPathInSpace( `~gitbook/pdf?${getPDFURLSearchParams({ page: page.id, @@ -183,6 +190,37 @@ function getPageActionsURLs({ }; } +/** + * Whether a given built-in page action is enabled. Uses the configured `items` list when the API + * provides it, and falls back to the deprecated boolean flags otherwise (legacy mode), matching the + * fallback used by the page actions dropdown. + */ +function isPageActionEnabled( + customization: GitBookSiteContext['customization'], + type: CustomizationPageActionType +): boolean { + const { pageActions } = customization; + if (pageActions.items) { + return pageActions.items.includes(type); + } + switch (type) { + case CustomizationPageActionType.ExternalAi: + return pageActions.externalAI; + case CustomizationPageActionType.Markdown: + return pageActions.markdown; + case CustomizationPageActionType.Mcp: + return pageActions.mcp; + case CustomizationPageActionType.Pdf: + return customization.pdf.enabled; + case CustomizationPageActionType.Git: + return customization.git.showEditLink; + case CustomizationPageActionType.Assistant: + return customization.ai.mode === CustomizationAIMode.Assistant; + default: + return false; + } +} + /** * Return the MCP URL to be used in the page actions dropdown. */