repo_description: The React documentation website
repo_topics: documentation javascript react website
code: /**
   * Copyright (c) Meta Platforms, Inc. and affiliates.
   *
   * This source code is licensed under the MIT license found in the
   * LICENSE file in the root directory of this source tree.
   */
  
  /*
   * Copyright (c) Facebook, Inc. and its affiliates.
   */
  
  import {Fragment, useMemo} from 'react';
  import {useRouter} from 'next/router';
  import {Page} from 'components/Layout/Page';
  import sidebarHome from '../sidebarHome.json';
  import sidebarLearn from '../sidebarLearn.json';
  import sidebarReference from '../sidebarReference.json';
  import sidebarCommunity from '../sidebarCommunity.json';
  import sidebarBlog from '../sidebarBlog.json';
  import {MDXComponents} from 'components/MDX/MDXComponents';
  import compileMDX from 'utils/compileMDX';
  import {generateRssFeed} from '../utils/rss';
  
  export default function Layout({content, toc, meta, languages}) {
    const parsedContent = useMemo(
      () => JSON.parse(content, reviveNodeOnClient),
      [content]
    );
    const parsedToc = useMemo(() => JSON.parse(toc, reviveNodeOnClient), [toc]);
    const section = useActiveSection();
    let routeTree;
    switch (section) {
      case 'home':
      case 'unknown':
        routeTree = sidebarHome;
        break;
      case 'learn':
        routeTree = sidebarLearn;
        break;
      case 'reference':
        routeTree = sidebarReference;
        break;
      case 'community':
        routeTree = sidebarCommunity;
        break;
      case 'blog':
        routeTree = sidebarBlog;
        break;
    }
    return (
      <Page
        toc={parsedToc}
        routeTree={routeTree}
        meta={meta}
        section={section}
        languages={languages}>
        {parsedContent}
      </Page>
    );
  }
  
  function useActiveSection() {
    const {asPath} = useRouter();
    const cleanedPath = asPath.split(/[\?\#]/)[0];
    if (cleanedPath === '/') {
      return 'home';
    } else if (cleanedPath.startsWith('/reference')) {
      return 'reference';
    } else if (asPath.startsWith('/learn')) {
      return 'learn';
    } else if (asPath.startsWith('/community')) {
      return 'community';
    } else if (asPath.startsWith('/blog')) {
      return 'blog';
    } else {
      return 'unknown';
    }
  }
  
  // Deserialize a client React tree from JSON.
  function reviveNodeOnClient(parentPropertyName, val) {
    if (Array.isArray(val) && val[0] == '$r') {
      // Assume it's a React element.
      let Type = val[1];
      let key = val[2];
      if (key == null) {
        key = parentPropertyName; // Index within a parent.
      }
      let props = val[3];
      if (Type === 'wrapper') {
        Type = Fragment;
        props = {children: props.children};
      }
      if (Type in MDXComponents) {
        Type = MDXComponents[Type];
      }
      if (!Type) {
        console.error('Unknown type: ' + Type);
        Type = Fragment;
      }
      return <Type key={key} {...props} />;
    } else {
      return val;
    }
  }
  
  // Put MDX output into JSON for client.
  export async function getStaticProps(context) {
    generateRssFeed();
    const fs = require('fs');
    const rootDir = process.cwd() + '/src/content/';
  
    // Read MDX from the file.
    let path = (context.params.markdownPath || []).join('/') || 'index';
    let mdx;
    try {
      mdx = fs.readFileSync(rootDir + path + '.md', 'utf8');
    } catch {
      mdx = fs.readFileSync(rootDir + path + '/index.md', 'utf8');
    }
  
    const {toc, content, meta, languages} = await compileMDX(mdx, path, {});
    return {
      props: {
        toc,
        content,
        meta,
        languages,
      },
    };
  }
  
  // Collect all MDX files for static generation.
  export async function getStaticPaths() {
    const {promisify} = require('util');
    const {resolve} = require('path');
    const fs = require('fs');
    const readdir = promisify(fs.readdir);
    const stat = promisify(fs.stat);
    const rootDir = process.cwd() + '/src/content';
  
    // Pages that should only be available in development.
    const devOnlyPages = new Set(['learn/rsc-sandbox-test']);
  
    // Find all MD files recursively.
    async function getFiles(dir) {
      const subdirs = await readdir(dir);
      const files = await Promise.all(
        subdirs.map(async (subdir) => {
          const res = resolve(dir, subdir);
          return (await stat(res)).isDirectory()
            ? getFiles(res)
            : res.slice(rootDir.length + 1);
        })
      );
      return (
        files
          .flat()
          // ignores `errors/*.md`, they will be handled by `pages/errors/[errorCode].tsx`
          .filter((file) => file.endsWith('.md') && !file.startsWith('errors/'))
      );
    }
  
    // 'foo/bar/baz.md' -> ['foo', 'bar', 'baz']
    // 'foo/bar/qux/index.md' -> ['foo', 'bar', 'qux']
    function getSegments(file) {
      let segments = file.slice(0, -3).replace(/\\/g, '/').split('/');
      if (segments[segments.length - 1] === 'index') {
        segments.pop();
      }
      return segments;
    }
  
    const files = await getFiles(rootDir);
  
    const paths = files
      .map((file) => ({
        params: {
          markdownPath: getSegments(file),
          // ^^^ CAREFUL HERE.
          // If you rename markdownPath, update patches/next-remote-watch.patch too.
          // Otherwise you'll break Fast Refresh for all MD files.
        },
      }))
      .filter((entry) => {
        if (process.env.NODE_ENV !== 'production') return true;
        const pagePath = entry.params.markdownPath.join('/');
        return !devOnlyPages.has(pagePath);
      });
  
    return {
      paths: paths,
      fallback: false,
    };
  }
  