Skip to content

Commit

Permalink
fix: apply components to mdx
Browse files Browse the repository at this point in the history
close #637
  • Loading branch information
promer94 committed Aug 5, 2022
1 parent 88f999d commit 85689cc
Show file tree
Hide file tree
Showing 15 changed files with 87 additions and 152 deletions.
7 changes: 7 additions & 0 deletions .changeset/wet-keys-work.md
@@ -0,0 +1,7 @@
---
'nextra': patch
'nextra-theme-blog': patch
'nextra-theme-docs': patch
---

fix missing mdx components
9 changes: 3 additions & 6 deletions packages/nextra-theme-blog/src/article-layout.tsx
@@ -1,6 +1,5 @@
import React, { ReactNode } from 'react'
import Meta from './meta'
import MDXTheme from './mdx-theme'
import { useBlogContext } from './blog-context'
import { BasicLayout } from './basic-layout'
import { getParent } from './utils/parent'
Expand All @@ -11,11 +10,9 @@ export const ArticleLayout = ({ children }: { children: ReactNode }) => {
return (
<BasicLayout>
<Meta {...opts.meta} back={back} config={config} />
<MDXTheme>
{children}
{config.postFooter}
{config.comments}
</MDXTheme>
{children}
{config.postFooter}
{config.comments}
</BasicLayout>
)
}
11 changes: 9 additions & 2 deletions packages/nextra-theme-blog/src/blog-context.tsx
@@ -1,4 +1,9 @@
import React, { ReactElement, useContext, createContext, ReactNode } from 'react'
import React, {
ReactElement,
useContext,
createContext,
ReactNode
} from 'react'
import { LayoutProps } from './types'
import { isValidDate } from './utils/date'

Expand All @@ -12,7 +17,9 @@ export const BlogProvider = ({
const { date } = opts.meta

if (date && !isValidDate(date)) {
throw new Error(`Invalid date "${date}". Provide date in "YYYY/M/D", "YYYY/M/D H:m", "YYYY-MM-DD", "[YYYY-MM-DD]T[HH:mm]" or "[YYYY-MM-DD]T[HH:mm:ss.SSS]Z" format.`)
throw new Error(
`Invalid date "${date}". Provide date in "YYYY/M/D", "YYYY/M/D H:m", "YYYY-MM-DD", "[YYYY-MM-DD]T[HH:mm]" or "[YYYY-MM-DD]T[HH:mm:ss.SSS]Z" format.`
)
}
return (
<BlogContext.Provider value={{ config, opts }}>
Expand Down
46 changes: 17 additions & 29 deletions packages/nextra-theme-blog/src/index.tsx
@@ -1,4 +1,4 @@
import React, { ReactElement, ReactNode, FC } from 'react'
import React, { ReactElement, ReactNode, FC, PropsWithChildren } from 'react'
import { ThemeProvider } from 'next-themes'
import type { PageOpts } from 'nextra'
import type { LayoutProps, NextraBlogTheme } from './types'
Expand All @@ -7,7 +7,8 @@ import { ArticleLayout } from './article-layout'
import { PostsLayout } from './posts-layout'
import { PageLayout } from './page-layout'
import { DEFAULT_CONFIG } from './constants'
import { useRouter } from 'next/router'
import { components } from './mdx-theme'
import { Components } from '@mdx-js/react/lib'

const layoutMap = {
post: ArticleLayout,
Expand All @@ -34,26 +35,16 @@ const BlogLayout = ({
</BlogProvider>
)
}

const nextraPageContext: {
[key: string]: {
Content: FC
pageOpts: PageOpts
themeConfig: NextraBlogTheme
}
} = {}

function Layout(props: any) {
const { route } = useRouter()
const context = nextraPageContext[route]
if (!context) throw new Error(`No content found for ${route}.`)

const extendedConfig = { ...DEFAULT_CONFIG, ...context.themeConfig }

interface Props {
pageOpts: PageOpts
themeConfig: NextraBlogTheme
}
function Layout({ children, themeConfig, pageOpts }: PropsWithChildren<Props>) {
const extendedConfig = { ...DEFAULT_CONFIG, ...themeConfig }
return (
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
<BlogLayout config={extendedConfig} opts={context.pageOpts}>
<context.Content {...props} />
<BlogLayout config={extendedConfig} opts={pageOpts}>
{children}
</BlogLayout>
</ThemeProvider>
)
Expand All @@ -63,18 +54,15 @@ function Layout(props: any) {
// stable layout. We then put the actual content into a global store and use
// the route to identify it.
export default function withLayout(
route: string,
Content: FC,
MdxContent: FC<{ components: Components }>,
pageOpts: PageOpts,
themeConfig: NextraBlogTheme
) {
nextraPageContext[route] = {
Content,
pageOpts,
themeConfig
}

return Layout
return (
<Layout pageOpts={pageOpts} themeConfig={themeConfig}>
<MdxContent components={components} />
</Layout>
)
}

export { useBlogContext } from './blog-context'
Expand Down
15 changes: 3 additions & 12 deletions packages/nextra-theme-blog/src/mdx-theme.tsx
Expand Up @@ -7,11 +7,10 @@ import React, {
useEffect,
useState
} from 'react'
import { MDXProvider } from '@mdx-js/react'
import Link from 'next/link'
import ReactDOM from 'react-dom'
import { useBlogContext } from './blog-context'

import { Components } from '@mdx-js/react/lib'
export const HeadingContext = createContext<
React.RefObject<HTMLHeadingElement | null>
>(React.createRef())
Expand Down Expand Up @@ -42,9 +41,7 @@ const createHeaderLink =
return (
<Tag className={`subheading-${Tag}`} {...props}>
<span className="subheading-anchor -mt-8" id={id} />
<a href={`#${id}`}>
{children}
</a>
<a href={`#${id}`}>{children}</a>
</Tag>
)
}
Expand Down Expand Up @@ -80,7 +77,7 @@ const Pre = ({ children }: { children?: ReactNode }): ReactElement => {
</div>
)
}
const components = {
export const components: Components = {
h1: H1,
h2: createHeaderLink('h2'),
h3: createHeaderLink('h3'),
Expand All @@ -90,9 +87,3 @@ const components = {
a: A,
pre: Pre
}

const MDXTheme = ({ children }: { children: ReactNode }): ReactElement => {
return <MDXProvider components={components}>{children}</MDXProvider>
}

export default MDXTheme
3 changes: 1 addition & 2 deletions packages/nextra-theme-blog/src/page-layout.tsx
@@ -1,13 +1,12 @@
import React, { ReactNode } from 'react'
import { BasicLayout } from './basic-layout'
import MDXTheme from './mdx-theme'
import Nav from './nav'

export const PageLayout = ({ children }: { children: ReactNode }) => {
return (
<BasicLayout>
<Nav />
<MDXTheme>{children}</MDXTheme>
{children}
</BasicLayout>
)
}
8 changes: 2 additions & 6 deletions packages/nextra-theme-blog/src/posts-layout.tsx
Expand Up @@ -3,7 +3,6 @@ import { useRouter } from 'next/router'
import React, { ReactNode } from 'react'
import { useBlogContext } from './blog-context'
import { BasicLayout } from './basic-layout'
import MDXTheme from './mdx-theme'
import Nav from './nav'
import { collectPostsAndNavs } from './utils/collect'
import getTags from './utils/get-tags'
Expand Down Expand Up @@ -48,10 +47,7 @@ export const PostsLayout = ({ children }: { children: ReactNode }) => {
</p>
)}
{date && (
<time
className="text-sm text-gray-300"
dateTime={date.toISOString()}
>
<time className="text-sm text-gray-300" dateTime={date.toISOString()}>
{date.toDateString()}
</time>
)}
Expand All @@ -61,7 +57,7 @@ export const PostsLayout = ({ children }: { children: ReactNode }) => {
return (
<BasicLayout>
<Nav />
<MDXTheme>{children}</MDXTheme>
{children}
{postList}
</BasicLayout>
)
Expand Down
5 changes: 1 addition & 4 deletions packages/nextra-theme-blog/src/utils/collect.ts
Expand Up @@ -9,10 +9,7 @@ const isNav = (page: PageMapItem) => {
const isPost = (page: PageMapItem) => {
if (page.children) return false
if (page.name.startsWith('_')) return false
return (
!page.frontMatter?.type ||
page.frontMatter.type === 'post'
)
return !page.frontMatter?.type || page.frontMatter.type === 'post'
}

export const collectPostsAndNavs = ({ opts }: LayoutProps) => {
Expand Down
3 changes: 2 additions & 1 deletion packages/nextra-theme-blog/src/utils/date.ts
Expand Up @@ -12,4 +12,5 @@ export const sortDate = (a: PageMapItem, b: PageMapItem): number => {
const DATE_REGEX = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2})?(:\d{2}\.\d{3}Z)?$/
const DATE_REGEX_WITH_SLASH = /^\d{4}\/\d{1,2}\/\d{1,2}( \d{1,2}:\d{1,2})?$/

export const isValidDate = (date: string): boolean => DATE_REGEX.test(date) || DATE_REGEX_WITH_SLASH.test(date)
export const isValidDate = (date: string): boolean =>
DATE_REGEX.test(date) || DATE_REGEX_WITH_SLASH.test(date)
2 changes: 1 addition & 1 deletion packages/nextra-theme-blog/tsup.config.ts
Expand Up @@ -7,7 +7,7 @@ function outExtension() {
}

export default defineConfig({
entry: ['src/index.tsx', "src/cusdis.tsx"],
entry: ['src/index.tsx', 'src/cusdis.tsx'],
format: 'esm',
dts: true,
name: 'nextra-theme-blog',
Expand Down
14 changes: 6 additions & 8 deletions packages/nextra-theme-docs/src/breadcrumb.tsx
Expand Up @@ -23,14 +23,12 @@ export default function Breadcrumb({
<ArrowRightIcon width={14} className="mx-1 select-none" />
) : null}
<div
className={cn(
'transition-colors whitespace-nowrap',
{
'active text-gray-600 dark:text-gray-400': isActive,
'min-w-[24px] overflow-hidden text-ellipsis': !isActive,
'hover:text-gray-900 dark:hover:text-gray-200': isLink && !isActive
}
)}
className={cn('transition-colors whitespace-nowrap', {
'active text-gray-600 dark:text-gray-400': isActive,
'min-w-[24px] overflow-hidden text-ellipsis': !isActive,
'hover:text-gray-900 dark:hover:text-gray-200':
isLink && !isActive
})}
title={item.title}
>
{isLink && !isActive ? (
Expand Down
57 changes: 20 additions & 37 deletions packages/nextra-theme-docs/src/index.tsx
@@ -1,18 +1,16 @@
import type { PageMapItem, PageOpts } from 'nextra'
import type { FC, ReactElement, ReactNode } from 'react'

import { getComponents } from './misc/theme'
import React, { useEffect, useMemo, useRef, useState } from 'react'
import { useRouter } from 'next/router'
import 'focus-visible'
import scrollIntoView from 'scroll-into-view-if-needed'
import { SkipNavContent } from '@reach/skip-nav'
import { ThemeProvider } from 'next-themes'
import cn from 'classnames'

import Head from './head'
import Navbar from './navbar'
import Footer, { NavLinks } from './footer'
import { MDXTheme } from './misc/theme'
import Sidebar from './sidebar'
import ToC from './toc'
import { ThemeConfigContext, useConfig } from './config'
Expand Down Expand Up @@ -93,7 +91,7 @@ const Body = ({
<SkipNavContent />
{themeContext.layout === 'full' ? (
<article className="nextra-body full relative justify-center overflow-x-hidden pl-[max(env(safe-area-inset-left),1.5rem)] pr-[max(env(safe-area-inset-right),1.5rem)]">
<MDXTheme>{children}</MDXTheme>
{children}
{date && config.gitTimestamp ? (
<div className="pointer-default mt-12 mb-8 block text-right text-xs text-gray-500 dark:text-gray-400">
{typeof config.gitTimestamp === 'string'
Expand Down Expand Up @@ -132,7 +130,7 @@ const Body = ({
ref={mainElement}
>
{breadcrumb}
<MDXTheme>{children}</MDXTheme>
{children}
{date && config.gitTimestamp ? (
<div className="pointer-default mt-12 mb-8 block text-right text-xs text-gray-500 dark:text-gray-400">
{typeof config.gitTimestamp === 'string'
Expand Down Expand Up @@ -275,25 +273,18 @@ const InnerLayout = ({
)
}

const nextraPageContext: {
[key: string]: {
Content: FC
pageOpts: PageOpts
themeConfig: DocsThemeConfig
}
} = {}

function Layout(props: any) {
const { route } = useRouter()
const context = nextraPageContext[route]

if (!context) throw new Error(`No content found for ${route}.`)
interface Props {
children?: ReactNode
pageOpts: PageOpts
themeConfig: DocsThemeConfig
}

function Layout({ children, pageOpts, themeConfig }: Props) {
const extendedConfig = {
...defaultConfig,
...context.themeConfig,
unstable_flexsearch: context.pageOpts.unstable_flexsearch,
newNextLinkBehavior: context.pageOpts.newNextLinkBehavior
...themeConfig,
unstable_flexsearch: pageOpts.unstable_flexsearch,
newNextLinkBehavior: pageOpts.newNextLinkBehavior
}
const nextThemes = extendedConfig.nextThemes || {}

Expand All @@ -306,31 +297,23 @@ function Layout(props: any) {
storageKey={nextThemes.storageKey}
forcedTheme={nextThemes.forcedTheme}
>
<InnerLayout {...context.pageOpts}>
<context.Content {...props} />
</InnerLayout>
<InnerLayout {...pageOpts}>{children}</InnerLayout>
</ThemeProvider>
</ThemeConfigContext.Provider>
)
}

// Make sure the same component is always returned so Next.js will render the
// stable layout. We then put the actual content into a global store and use
// the route to identify it.
export default function withLayout(
route: string,
Content: FC,
MdxContent: FC<{ components: any }>,
pageOpts: PageOpts,
themeConfig: DocsThemeConfig
) {
nextraPageContext[route] = {
Content,
pageOpts,
themeConfig
}

return Layout
return (
<Layout pageOpts={pageOpts} themeConfig={themeConfig}>
<MdxContent components={getComponents()} />
</Layout>
)
}

export * from './types'
export { getComponents } from './misc/theme'
export { getComponents }

0 comments on commit 85689cc

Please sign in to comment.