/ docs-website / src / theme / Root.js
Root.js
  1  // SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>
  2  //
  3  // SPDX-License-Identifier: Apache-2.0
  4  
  5  import React, {useEffect, useState} from 'react';
  6  import Root from '@theme-original/Root';
  7  import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
  8  
  9  export default function RootWrapper(props) {
 10    const {siteConfig} = useDocusaurusContext();
 11  
 12    // Determine product from URL path or environment
 13    const getProduct = () => {
 14      if (typeof window !== 'undefined') {
 15        const path = window.location.pathname;
 16        if (path.startsWith('/professional')) return 'professional';
 17        if (path.startsWith('/enterprise')) return 'enterprise';
 18      }
 19      return siteConfig?.customFields?.docsProduct ||
 20        (typeof process !== 'undefined' && process.env.DOCS_PRODUCT) ||
 21        'haystack';
 22    };
 23  
 24    const [product, setProduct] = useState(getProduct);
 25  
 26    // Update product when location changes
 27    useEffect(() => {
 28      const handleLocationChange = () => {
 29        const newProduct = getProduct();
 30        console.log('[Root.js] Location changed, setting product to:', newProduct);
 31        setProduct(newProduct);
 32      };
 33  
 34      // Listen for route changes
 35      if (typeof window !== 'undefined') {
 36        window.addEventListener('popstate', handleLocationChange);
 37        // Also check on initial load and navigation
 38        handleLocationChange();
 39      }
 40  
 41      return () => {
 42        if (typeof window !== 'undefined') {
 43          window.removeEventListener('popstate', handleLocationChange);
 44        }
 45      };
 46    }, []);
 47  
 48    // Mark single-word sidebar items for truncation styling
 49    useEffect(() => {
 50      if (typeof document === 'undefined') {
 51        return;
 52      }
 53  
 54      const markSingleWordLinks = () => {
 55        const menuLinks = document.querySelectorAll('.menu__link');
 56        menuLinks.forEach(link => {
 57          // Get the text content, trimmed
 58          const text = link.textContent?.trim() || '';
 59          // Check if it's a single word (no spaces)
 60          const isSingleWord = text.length > 0 && !text.includes(' ');
 61  
 62          if (isSingleWord) {
 63            link.classList.add('menu__link--single-word');
 64          } else {
 65            link.classList.remove('menu__link--single-word');
 66          }
 67        });
 68      };
 69  
 70      // Run initially
 71      markSingleWordLinks();
 72  
 73      // Re-run when DOM changes (sidebar updates, navigation, etc.)
 74      const observer = new MutationObserver(markSingleWordLinks);
 75      observer.observe(document.body, {childList: true, subtree: true});
 76  
 77      return () => {
 78        observer.disconnect();
 79      };
 80    }, []);
 81  
 82    useEffect(() => {
 83      console.log('[Root.js] Current product:', product);
 84      console.log('[Root.js] Current path:', typeof window !== 'undefined' ? window.location.pathname : 'N/A');
 85      if (typeof document === 'undefined') {
 86        return;
 87      }
 88  
 89      document.documentElement.setAttribute('data-docs-product', product);
 90  
 91      const filterToc = () => {
 92        console.log('[Root.js] filterToc called, product:', product);
 93        const items = document.querySelectorAll('.table-of-contents__item');
 94        console.log('[Root.js] Found TOC items:', items.length);
 95  
 96        items.forEach(item => {
 97          const link = item.querySelector('.table-of-contents__link');
 98          if (!link) {
 99            return;
100          }
101          const href = link.getAttribute('href') || '';
102          const isEnterprise = href.startsWith('#enterprise-');
103          const isProfessional = href.startsWith('#professional-');
104  
105          console.log('[Root.js] TOC item:', {href, isEnterprise, isProfessional, product});
106  
107          if (
108            (product === 'professional' && isEnterprise) ||
109            (product === 'enterprise' && isProfessional)
110          ) {
111            console.log('[Root.js] Removing TOC item:', href);
112            item.parentElement?.removeChild(item);
113          }
114        });
115      };
116  
117      filterToc();
118  
119      const observer = new MutationObserver(filterToc);
120      observer.observe(document.body, {childList: true, subtree: true});
121  
122      return () => {
123        document.documentElement.removeAttribute('data-docs-product');
124        observer.disconnect();
125      };
126    }, [product]);
127  
128    return <Root {...props} />;
129  }