From bd000d340f099af5958a0b876e53974873318a28 Mon Sep 17 00:00:00 2001 From: lidarbtc Date: Mon, 10 Nov 2025 16:45:25 +0900 Subject: [PATCH] Fix copy button lookup for trailing-slash docs route --- .../src/theme/CopyPageContent/index.tsx | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/packages/docusaurus-theme-llms-txt/src/theme/CopyPageContent/index.tsx b/packages/docusaurus-theme-llms-txt/src/theme/CopyPageContent/index.tsx index 220ce9f..48cb604 100644 --- a/packages/docusaurus-theme-llms-txt/src/theme/CopyPageContent/index.tsx +++ b/packages/docusaurus-theme-llms-txt/src/theme/CopyPageContent/index.tsx @@ -27,6 +27,10 @@ import type { CopyPageContentProps, PluginGlobalData } from '../../types'; import styles from './styles.module.css'; +type RouteData = NonNullable< + ReturnType['copyContentData'] +>[string]; + /** * Main Copy Page Button component */ @@ -38,6 +42,23 @@ export default function CopyPageContent({ // JSON keys include baseUrl, so we need to use pathnameWithBase for lookup const pathnameWithBase = useBaseUrl(pathname); + // copy-content JSON may store either `/docs` or `/docs/`, so probe both forms + const lookupKeys = React.useMemo(() => { + if (!pathnameWithBase) { + return []; + } + + if (pathnameWithBase.endsWith('/') && pathnameWithBase.length > 1) { + return [pathnameWithBase, pathnameWithBase.slice(0, -1)]; + } + + if (!pathnameWithBase.endsWith('/')) { + return [pathnameWithBase, `${pathnameWithBase}/`]; + } + + return [pathnameWithBase]; + }, [pathnameWithBase]); + // Get plugin configuration from global data const pluginData = usePluginData('docusaurus-plugin-llms-txt', undefined) as | PluginGlobalData @@ -53,9 +74,18 @@ export default function CopyPageContent({ // Resolve final configuration const finalConfig = useCopyButtonConfig(pluginConfig); - // Get route data for current path - // Use pathnameWithBase because JSON keys include baseUrl - const routeData = copyContentData?.[pathnameWithBase]; + // Resolve route data for the current path by checking both trailing-slash and non-slash keys in `lookupKeys`. + let routeData: RouteData | undefined; + if (copyContentData) { + for (const key of lookupKeys) { + const data = copyContentData[key]; + if (data) { + routeData = data; + break; + } + } + } + const shouldDisplay = typeof routeData === 'object' ? routeData.shouldDisplay : false; const hasMarkdown =