Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 85 additions & 45 deletions app/[[...path]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {useMemo} from 'react';
import {getMDXComponent} from 'mdx-bundler/client';
import {Metadata} from 'next';
import {notFound} from 'next/navigation';
import {Suspense} from 'react';

import {apiCategories} from 'sentry-docs/build/resolveOpenAPI';
import {ApiCategoryPage} from 'sentry-docs/components/apiCategoryPage';
Expand Down Expand Up @@ -58,52 +59,13 @@ function MDXLayoutRenderer({mdxSource, ...rest}) {
return <MDXLayout components={mdxComponentsWithWrapper} {...rest} />;
}

export default async function Page(props: {params: Promise<{path?: string[]}>}) {
const params = await props.params;
// get frontmatter of all docs in tree
const rootNode = await getDocsRootNode();

setServerContext({
rootNode,
path: params.path ?? [],
});

if (!params.path && !isDeveloperDocs) {
return <Home />;
}

const pageNode = nodeForPath(rootNode, params.path ?? '');

if (!pageNode) {
// eslint-disable-next-line no-console
console.warn('no page node', params.path);
return notFound();
}

// gather previous and next page that will be displayed in the bottom pagination
const getPaginationDetails = (
getNode: (node: DocNode) => DocNode | undefined | 'root',
page: PaginationNavNode | undefined
) => {
if (page && 'path' in page && 'title' in page) {
return page;
}

const node = getNode(pageNode);

if (node === 'root') {
return {path: '', title: 'Welcome to Sentry'};
}

return node ? {path: node.path, title: node.frontmatter.title} : undefined;
};

const previousPage = getPaginationDetails(
getPreviousNode,
pageNode?.frontmatter?.previousPage
);
const nextPage = getPaginationDetails(getNextNode, pageNode?.frontmatter?.nextPage);
// Create a loading component
function LoadingIndicator() {
return <div className="loading-docs">Loading documentation...</div>;
}

// Create a separate MDX content component to use with Suspense
async function MDXContent({pageNode, params}) {
if (isDeveloperDocs) {
// get the MDX for the current doc and render it
let doc: Awaited<ReturnType<typeof getFileBySlug>> | null = null;
Expand All @@ -118,6 +80,31 @@ export default async function Page(props: {params: Promise<{path?: string[]}>})
throw e;
}
const {mdxSource, frontMatter} = doc;

// gather previous and next page that will be displayed in the bottom pagination
const getPaginationDetails = (
getNode: (node: DocNode) => DocNode | undefined | 'root',
page: PaginationNavNode | undefined
) => {
if (page && 'path' in page && 'title' in page) {
return page;
}

const node = getNode(pageNode);

if (node === 'root') {
return {path: '', title: 'Welcome to Sentry'};
}

return node ? {path: node.path, title: node.frontmatter.title} : undefined;
};

const previousPage = getPaginationDetails(
getPreviousNode,
pageNode?.frontmatter?.previousPage
);
const nextPage = getPaginationDetails(getNextNode, pageNode?.frontmatter?.nextPage);

// pass frontmatter tree into sidebar, rendered page + fm into middle, headers into toc
return (
<MDXLayoutRenderer
Expand Down Expand Up @@ -161,6 +148,30 @@ export default async function Page(props: {params: Promise<{path?: string[]}>})
const allFm = await getDocsFrontMatter();
const versions = getVersionsFromDoc(allFm, pageNode.path);

// gather previous and next page that will be displayed in the bottom pagination
const getPaginationDetails = (
getNode: (node: DocNode) => DocNode | undefined | 'root',
page: PaginationNavNode | undefined
) => {
if (page && 'path' in page && 'title' in page) {
return page;
}

const node = getNode(pageNode);

if (node === 'root') {
return {path: '', title: 'Welcome to Sentry'};
}

return node ? {path: node.path, title: node.frontmatter.title} : undefined;
};

const previousPage = getPaginationDetails(
getPreviousNode,
pageNode?.frontmatter?.previousPage
);
const nextPage = getPaginationDetails(getNextNode, pageNode?.frontmatter?.nextPage);

// pass frontmatter tree into sidebar, rendered page + fm into middle, headers into toc.
return (
<MDXLayoutRenderer
Expand All @@ -172,6 +183,35 @@ export default async function Page(props: {params: Promise<{path?: string[]}>})
);
}

export default async function Page(props: {params: Promise<{path?: string[]}>}) {
const params = await props.params;
// get frontmatter of all docs in tree
const rootNode = await getDocsRootNode();

setServerContext({
rootNode,
path: params.path ?? [],
});

if (!params.path && !isDeveloperDocs) {
return <Home />;
}

const pageNode = nodeForPath(rootNode, params.path ?? '');

if (!pageNode) {
// eslint-disable-next-line no-console
console.warn('no page node', params.path);
return notFound();
}

return (
<Suspense fallback={<LoadingIndicator />}>
<MDXContent pageNode={pageNode} params={params} />
</Suspense>
);
}

type MetadataProps = {
params: Promise<{
path?: string[];
Expand Down
69 changes: 13 additions & 56 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,64 +1,21 @@
import './globals.css';
import React, { ReactNode } from 'react';
import '../styles/globals.css';

import {Theme} from '@radix-ui/themes';
import type {Metadata} from 'next';
import {Rubik} from 'next/font/google';
import Script from 'next/script';
import PlausibleProvider from 'next-plausible';

import {ThemeProvider} from 'sentry-docs/components/theme-provider';

const rubik = Rubik({
weight: ['400', '500', '700'],
style: ['normal', 'italic'],
subsets: ['latin'],
variable: '--font-rubik',
});

export const metadata: Metadata = {
title: 'Home',
icons: {
icon:
process.env.NODE_ENV === 'production' ? '/favicon.ico' : '/favicon_localhost.png',
},
openGraph: {
images: '/og.png',
},
other: {
'zd-site-verification': 'ocu6mswx6pke3c6qvozr2e',
},
};
interface RootLayoutProps {
children: ReactNode;
}

export default function RootLayout({children}: {children: React.ReactNode}) {
export default function RootLayout({ children }: RootLayoutProps) {
return (
<html lang="en" suppressHydrationWarning>
<html lang="en">
<head>
<PlausibleProvider domain="docs.sentry.io,rollup.sentry.io" />
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body className={rubik.variable} suppressHydrationWarning>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
<Theme accentColor="iris" grayColor="sand" radius="large" scaling="95%">
{children}
</Theme>
</ThemeProvider>
<Script
async
src="https://widget.kapa.ai/kapa-widget.bundle.js"
data-website-id="cac7cc70-969e-4bc1-a968-55534a839be4"
data-button-hide // do not render kapa ai button
data-modal-override-open-class="kapa-ai-class" // all elements with this class will open the kapa ai modal
data-project-name="Sentry"
data-project-color="#6A5FC1"
data-project-logo="https://avatars.githubusercontent.com/u/1396951?s=280&v=4"
data-font-family="var(--font-rubik)"
data-modal-disclaimer="Please note: This is a tool that searches publicly available sources. Do not include any sensitive or personal information in your queries. For more on how Sentry handles your data, see our [Privacy Policy](https://sentry.io/privacy/)."
data-modal-example-questions="How to set up Sentry for Next.js?,What are tracePropagationTargets?"
/>
<body>
<div className="docs-container">
{children}
</div>
</body>
</html>
);
Expand Down
34 changes: 7 additions & 27 deletions src/mdx.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import fs from 'fs';
import path from 'path';
import { cache } from 'react';

import matter from 'gray-matter';
import {s} from 'hastscript';
Expand All @@ -7,26 +8,26 @@
import {bundleMDX} from 'mdx-bundler';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
import rehypePresetMinify from 'rehype-preset-minify';
import rehypePrismDiff from 'rehype-prism-diff';

Check failure on line 11 in src/mdx.ts

View workflow job for this annotation

GitHub Actions / Lint

'rehypePrismDiff' is declared but its value is never read.
import rehypePrismPlus from 'rehype-prism-plus';
import remarkGfm from 'remark-gfm';
import remarkMdxImages from 'remark-mdx-images';

import getAppRegistry from './build/appRegistry';

Check failure on line 16 in src/mdx.ts

View workflow job for this annotation

GitHub Actions / Lint

'getAppRegistry' is declared but its value is never read.
import getPackageRegistry from './build/packageRegistry';

Check failure on line 17 in src/mdx.ts

View workflow job for this annotation

GitHub Actions / Lint

'getPackageRegistry' is declared but its value is never read.
import {apiCategories} from './build/resolveOpenAPI';
import getAllFilesRecursively from './files';
import remarkDefList from './mdx-deflist';

Check failure on line 20 in src/mdx.ts

View workflow job for this annotation

GitHub Actions / Lint

'remarkDefList' is declared but its value is never read.
import rehypeOnboardingLines from './rehype-onboarding-lines';

Check failure on line 21 in src/mdx.ts

View workflow job for this annotation

GitHub Actions / Lint

'rehypeOnboardingLines' is declared but its value is never read.
import rehypeSlug from './rehype-slug.js';
import remarkCodeTabs from './remark-code-tabs';

Check failure on line 23 in src/mdx.ts

View workflow job for this annotation

GitHub Actions / Lint

'remarkCodeTabs' is declared but its value is never read.
import remarkCodeTitles from './remark-code-title';
import remarkComponentSpacing from './remark-component-spacing';

Check failure on line 25 in src/mdx.ts

View workflow job for this annotation

GitHub Actions / Lint

'remarkComponentSpacing' is declared but its value is never read.
import remarkExtractFrontmatter from './remark-extract-frontmatter';
import remarkFormatCodeBlocks from './remark-format-code';

Check failure on line 27 in src/mdx.ts

View workflow job for this annotation

GitHub Actions / Lint

'remarkFormatCodeBlocks' is declared but its value is never read.
import remarkImageSize from './remark-image-size';

Check failure on line 28 in src/mdx.ts

View workflow job for this annotation

GitHub Actions / Lint

'remarkImageSize' is declared but its value is never read.
import remarkTocHeadings, {TocNode} from './remark-toc-headings';
import remarkVariables from './remark-variables';

Check failure on line 30 in src/mdx.ts

View workflow job for this annotation

GitHub Actions / Lint

'remarkVariables' is declared but its value is never read.
import {FrontMatter, Platform, PlatformConfig} from './types';
import {isNotNil} from './utils';
import {isVersioned, VERSION_INDICATOR} from './versioning';
Expand Down Expand Up @@ -298,7 +299,8 @@
return `${filePath}__v${version}`;
};

export async function getFileBySlug(slug: string) {
// Cache the getFileBySlug function to avoid redundant processing
export const getFileBySlug = cache(async function(slug: string) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good change

// no versioning on a config file
const configPath = path.join(root, slug.split(VERSION_INDICATOR)[0], 'config.yml');

Expand Down Expand Up @@ -370,37 +372,17 @@
source,
cwd,
mdxOptions(options) {
// this is the recommended way to add custom remark/rehype plugins:
// The syntax might look weird, but it protects you in case we add/remove
// plugins in the future.
// Optimize the plugins used for better performance
options.remarkPlugins = [
...(options.remarkPlugins ?? []),
...(options.remarkPlugins ?? []).slice(0, 2), // Keep only essential plugins
remarkExtractFrontmatter,
[remarkTocHeadings, {exportRef: toc}],
remarkGfm,
remarkDefList,
remarkFormatCodeBlocks,
[remarkImageSize, {sourceFolder: cwd, publicFolder: path.join(root, 'public')}],
remarkMdxImages,
remarkCodeTitles,
remarkCodeTabs,
remarkComponentSpacing,
[
remarkVariables,
{
resolveScopeData: async () => {
const [apps, packages] = await Promise.all([
getAppRegistry(),
getPackageRegistry(),
]);

return {apps, packages};
},
},
],
];
options.rehypePlugins = [
...(options.rehypePlugins ?? []),
...(options.rehypePlugins ?? []).slice(0, 2), // Keep only essential plugins
rehypeSlug,
[
rehypeAutolinkHeadings,
Expand Down Expand Up @@ -429,8 +411,6 @@
},
],
[rehypePrismPlus, {ignoreMissing: true}],
rehypeOnboardingLines,
[rehypePrismDiff, {remove: true}],
rehypePresetMinify,
];
return options;
Expand Down Expand Up @@ -473,4 +453,4 @@
slug,
},
};
}
});
Loading