diff --git a/documentation/src/theme/DocItem/Layout/index.tsx b/documentation/src/theme/DocItem/Layout/index.tsx new file mode 100644 index 0000000000..91749457d9 --- /dev/null +++ b/documentation/src/theme/DocItem/Layout/index.tsx @@ -0,0 +1,212 @@ +import React, {type ReactNode, useState} from 'react'; +import Layout from '@theme-original/DocItem/Layout'; +import type LayoutType from '@theme/DocItem/Layout'; +import type {WrapperProps} from '@docusaurus/types'; +import {useDoc} from '@docusaurus/plugin-content-docs/client'; +import clsx from 'clsx'; +import {useWindowSize, ThemeClassNames} from '@docusaurus/theme-common'; +import DocItemPaginator from '@theme/DocItem/Paginator'; +import DocVersionBanner from '@theme/DocVersionBanner'; +import DocVersionBadge from '@theme/DocVersionBadge'; +import DocItemFooter from '@theme/DocItem/Footer'; +import DocItemTOCMobile from '@theme/DocItem/TOC/Mobile'; +import DocItemTOCDesktop from '@theme/DocItem/TOC/Desktop'; +import DocBreadcrumbs from '@theme/DocBreadcrumbs'; +import ContentVisibility from '@theme/ContentVisibility'; +import Heading from '@theme/Heading'; +import MDXContent from '@theme/MDXContent'; + +type Props = WrapperProps; + +// Component for the Copy Page button +function CopyPageButton(): ReactNode { + const [copied, setCopied] = useState(false); + + const handleCopy = async () => { + try { + // For now, just copy a placeholder text + // In Phase 2, we'll copy the actual markdown content + const textToCopy = `# Copy Page Feature\n\nThis is a placeholder for the copy page functionality.\nIn Phase 2, this will copy the actual markdown source.`; + + await navigator.clipboard.writeText(textToCopy); + setCopied(true); + + // Reset the "Copied" state after 2 seconds + setTimeout(() => { + setCopied(false); + }, 2000); + } catch (err) { + console.error('Failed to copy text: ', err); + } + }; + + return ( + + ); +} + +// Hook to determine if we should show the copy button +function useShouldShowCopyButton(): boolean { + const {metadata} = useDoc(); + + // Debug: Log metadata to understand the structure + React.useEffect(() => { + console.log('DocItem Metadata for Copy Button:', { + source: metadata?.source, + permalink: metadata?.permalink, + isGeneratedIndex: metadata?.isGeneratedIndex, + type: metadata?.type, + frontMatter: metadata?.frontMatter, + }); + }, [metadata]); + + // Show copy button only on actual content pages (not category/index pages) + // A content page should have a source file (.md file) + const hasSource = metadata?.source && metadata.source.includes('.md'); + + // Don't show on generated index pages + const isNotGeneratedIndex = !metadata?.isGeneratedIndex; + + // Don't show on category pages (they typically have /category/ in the permalink) + const isNotCategoryPage = !metadata?.permalink?.includes('/category/'); + + const shouldShow = hasSource && isNotGeneratedIndex && isNotCategoryPage; + + console.log('Copy button decision:', { + hasSource, + isNotGeneratedIndex, + isNotCategoryPage, + shouldShow, + permalink: metadata?.permalink + }); + + return shouldShow; +} + +/** + * Decide if the toc should be rendered, on mobile or desktop viewports + */ +function useDocTOC() { + const {frontMatter, toc} = useDoc(); + const windowSize = useWindowSize(); + + const hidden = frontMatter.hide_table_of_contents; + const canRender = !hidden && toc.length > 0; + + const mobile = canRender ? : undefined; + + const desktop = + canRender && (windowSize === 'desktop' || windowSize === 'ssr') ? ( + + ) : undefined; + + return { + hidden, + mobile, + desktop, + }; +} + +// Custom Content component that includes the copy button +function CustomDocItemContent({children}: {children: ReactNode}): ReactNode { + const shouldShowCopyButton = useShouldShowCopyButton(); + const {metadata, frontMatter, contentTitle} = useDoc(); + + // Check if we should render a synthetic title (same logic as original DocItem/Content) + const shouldRenderTitle = !frontMatter.hide_title && typeof contentTitle === 'undefined'; + const syntheticTitle = shouldRenderTitle ? metadata.title : null; + + return ( +
+ {syntheticTitle && ( +
+ {syntheticTitle} + {shouldShowCopyButton && } +
+ )} + {!syntheticTitle && shouldShowCopyButton && ( +
+ +
+ )} + {children} +
+ ); +} + +// Custom Layout component that replicates the original but with our custom content +function CustomDocItemLayout({children}: {children: ReactNode}): ReactNode { + const docTOC = useDocTOC(); + const {metadata} = useDoc(); + + return ( +
+
+ + +
+
+ + + {docTOC.mobile} + {children} + +
+ +
+
+ {docTOC.desktop &&
{docTOC.desktop}
} +
+ ); +} + +export default function LayoutWrapper(props: Props): ReactNode { + return ; +}