Skip to content

Commit

Permalink
feat(nextra/docs/blog): allow import .md/.mdx as well (#547)
Browse files Browse the repository at this point in the history
  • Loading branch information
dimaMachina committed Jul 23, 2022
1 parent 8101efe commit 699d131
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 62 deletions.
7 changes: 7 additions & 0 deletions .changeset/spicy-swans-check.md
@@ -0,0 +1,7 @@
---
'nextra': patch
'nextra-theme-blog': patch
'nextra-theme-docs': patch
---

feat(nextra/docs/blog): allow import `.md`/`.mdx` as well
5 changes: 5 additions & 0 deletions examples/swr-site/components/external.mdx
@@ -0,0 +1,5 @@
import Callout from 'nextra-theme-docs/callout'

<Callout type="info" emoji="💣">
This `<Callout />` comes from `external.mdx`
</Callout>
26 changes: 26 additions & 0 deletions examples/swr-site/pages/docs/advanced/markdown-import.en-US.mdx
@@ -0,0 +1,26 @@
import External from '../../../components/external.mdx'
import IndexPage from '../../index.en-US.mdx'

# Markdown import

## Import of markdown file

```mdx
import External from '../../../components/external.mdx'

<External />
```

<External />

## Import of another page

You can also import complete pages:

```mdx filename="not-index.md"
import IndexPage from '../../index.en-US.mdx'

<IndexPage />
```

<IndexPage />
1 change: 1 addition & 0 deletions examples/swr-site/pages/docs/advanced/meta.en-US.json
Expand Up @@ -11,6 +11,7 @@
"cache": "Cache",
"performance": "Performance",
"react-native": "React Native",
"markdown-import": "Markdown import",
"more": "More: A Super Super Super Super Long Directory",
"file-name.with.DOTS": "Filenames with dots"
}
29 changes: 7 additions & 22 deletions packages/nextra-theme-blog/src/index.tsx
Expand Up @@ -14,7 +14,6 @@ import getTags from './utils/get-tags'
import sortDate from './utils/sort-date'
import type { PageMapItem, PageOpt } from 'nextra'
import type { NextraBlogTheme } from './types'
const isProduction = process.env.NODE_ENV === 'production'
// comments
const Cusdis = dynamic(
// @ts-ignore
Expand Down Expand Up @@ -217,27 +216,13 @@ const createLayout = (opts: PageOpt, _config: NextraBlogTheme) => {
},
_config
)
let layoutUsed = false
const Page = ({ children }: { children: React.ReactChildren }) => {
if (!layoutUsed && isProduction) {
throw new Error(
'[Nextra] Please add the `getLayout` logic to your _app.js, see https://nextjs.org/docs/basic-features/layouts#per-page-layouts.'
)
}
return children
}
const Layout = (page: React.ReactChildren) => {
layoutUsed = true
return (
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem={true}
>
<BlogLayout config={config} contentNodes={page} opts={opts} />
</ThemeProvider>
)
}

const Page = ({ children }: { children: React.ReactChildren }) => children
const Layout = (page: React.ReactChildren) => (
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
<BlogLayout config={config} contentNodes={page} opts={opts} />
</ThemeProvider>
)
Page.getLayout = Layout
return Page
}
Expand Down
20 changes: 5 additions & 15 deletions packages/nextra-theme-docs/src/index.tsx
Expand Up @@ -22,8 +22,6 @@ import './polyfill'
import Breadcrumb from './breadcrumb'
import renderComponent from './utils/render-component'

const isProduction = process.env.NODE_ENV === 'production'

function useDirectoryInfo(pageMap: PageMapItem[]) {
const { locale, defaultLocale, asPath } = useRouter()

Expand Down Expand Up @@ -258,18 +256,10 @@ interface DocsLayoutProps extends PageOpt {
}
const createLayout = (opts: DocsLayoutProps, _config: DocsThemeConfig) => {
const extendedConfig = Object.assign({}, defaultConfig, _config, opts)
let layoutUsed = false
const Page = ({ children }: { children: React.ReactChildren }) => {
if (!layoutUsed && isProduction) {
throw new Error(
'[Nextra] Please add the `getLayout` logic to your _app.js, see https://nextjs.org/docs/basic-features/layouts#per-page-layouts.'
)
}
return children
}
Page.getLayout = (page: any) => {
layoutUsed = true
return (

const Page = ({ children }: { children: React.ReactChildren }) => children

Page.getLayout = (page: any) => (
<ThemeConfigContext.Provider value={extendedConfig}>
<ThemeProvider
attribute="class"
Expand All @@ -284,7 +274,7 @@ const createLayout = (opts: DocsLayoutProps, _config: DocsThemeConfig) => {
</ThemeProvider>
</ThemeConfigContext.Provider>
)
}

return Page
}

Expand Down
11 changes: 11 additions & 0 deletions packages/nextra/__test__/__snapshots__/page-map.test.ts.snap
Expand Up @@ -52,6 +52,11 @@ exports[`Page Process > pageMap en-US 1`] = `
"name": "file-name.with.DOTS",
"route": "/docs/advanced/file-name.with.DOTS",
},
{
"locale": "en-US",
"name": "markdown-import",
"route": "/docs/advanced/markdown-import",
},
{
"locale": "en-US",
"meta": {
Expand All @@ -66,6 +71,7 @@ exports[`Page Process > pageMap en-US 1`] = `
},
"cache": "Cache",
"file-name.with.DOTS": "Filenames with dots",
"markdown-import": "Markdown import",
"more": "More: A Super Super Super Super Long Directory",
"performance": "Performance",
"react-native": "React Native",
Expand Down Expand Up @@ -434,6 +440,11 @@ exports[`Page Process > pageMap zh-CN 1`] = `
"name": "react-native",
"route": "/docs/advanced/react-native",
},
{
"locale": "en-US",
"name": "markdown-import",
"route": "/docs/advanced/markdown-import",
},
],
"name": "advanced",
"route": "/docs/advanced",
Expand Down
18 changes: 12 additions & 6 deletions packages/nextra/src/loader.ts
Expand Up @@ -10,7 +10,7 @@ import { addPage } from './content-dump'
import { parseFileName } from './utils'
import { compileMdx } from './compile'
import { getPageMap, findPagesDir } from './page-map'
import { collectFiles } from './plugin'
import { collectFiles, collectMdx } from './plugin'
import { MARKDOWN_EXTENSION_REGEX, IS_PRODUCTION } from './constants'

// TODO: create this as a webpack plugin.
Expand Down Expand Up @@ -67,18 +67,20 @@ async function loader(
? pageMapCache.get()!
: await collectFiles(pagesDir, '/')

// mdx is imported but is outside the `pages` directory
if (!fileMap[resourcePath]) {
fileMap[resourcePath] = await collectMdx(resourcePath)
context.addMissingDependency(resourcePath)
}

const [pageMap, route, title] = getPageMap(
resourcePath,
pageMapResult,
fileMap,
defaultLocale
)

if (!IS_PRODUCTION) {
// Add the entire directory `pages` as the dependency
// so we can generate the correct page map.
context.addContextDependency(pagesDir)
} else {
if (IS_PRODUCTION) {
// We only add meta files as dependencies for production build,
// so we can do incremental builds.
Object.entries(fileMap).forEach(([filePath, { name, meta, locale }]) => {
Expand All @@ -90,6 +92,10 @@ async function loader(
context.addDependency(filePath)
}
})
} else {
// Add the entire directory `pages` as the dependency,
// so we can generate the correct page map.
context.addContextDependency(pagesDir)
}

// Extract frontMatter information if it exists
Expand Down
44 changes: 25 additions & 19 deletions packages/nextra/src/plugin.ts
Expand Up @@ -13,6 +13,19 @@ import { MARKDOWN_EXTENSION_REGEX } from './constants'
const readdir = promisify(fs.readdir)
const readFile = promisify(fs.readFile)

export const collectMdx = async (filePath: string, route = '') => {
const { name, locale } = parseFileName(filePath)

const content = await readFile(filePath, 'utf8')
const { data } = grayMatter(content)
return {
name,
route,
locale,
...(Object.keys(data).length && { frontMatter: data })
}
}

export async function collectFiles(
dir: string,
route = '/',
Expand All @@ -24,33 +37,26 @@ export async function collectFiles(
await Promise.all(
files.map(async f => {
const filePath = path.resolve(dir, f.name)
const { name, locale, ext } = parseFileName(f.name)
const { name, locale, ext } = parseFileName(filePath)
const fileRoute = slash(path.join(route, name.replace(/^index$/, '')))

if (f.isDirectory()) {
if (fileRoute === '/api') return null
const { items: children } = await collectFiles(
filePath,
fileRoute,
fileMap
)
if (!children || !children.length) return null
if (fileRoute === '/api') return
const { items } = await collectFiles(filePath, fileRoute, fileMap)
if (!items.length) return
return {
name: f.name,
children,
children: items,
route: fileRoute
}
} else if (MARKDOWN_EXTENSION_REGEX.test(ext)) {
const content = await readFile(filePath, 'utf8')
const { data } = grayMatter(content)
fileMap[filePath] = {
name,
route: fileRoute,
locale,
...(Object.keys(data).length && { frontMatter: data })
}
}

if (MARKDOWN_EXTENSION_REGEX.test(ext)) {
fileMap[filePath] = await collectMdx(filePath, fileRoute)
return fileMap[filePath]
} else if (ext === '.json' && name === 'meta') {
}

if (ext === '.json' && name === 'meta') {
const content = await readFile(filePath, 'utf8')
fileMap[filePath] = {
name: 'meta.json',
Expand Down

0 comments on commit 699d131

Please sign in to comment.