mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-26 23:49:51 +00:00
Zeta: Support build-page-tree API
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
---
|
||||
'next-docs-zeta': major
|
||||
---
|
||||
|
||||
Support build-page-tree API
|
||||
|
||||
The old `buildPageTree` function provided by 'next-docs-zeta/contentlayer' is now removed. Please use build-page-tree API directly.
|
||||
|
||||
```diff
|
||||
- import { buildPageTree } from 'next-docs-zeta/contentlayer'
|
||||
+ import { buildPageTree } from 'next-docs-zeta/build-page-tree'
|
||||
```
|
||||
@@ -1,9 +1,6 @@
|
||||
import { allDocs, allMeta } from 'contentlayer/generated'
|
||||
import {
|
||||
buildPageTree,
|
||||
createUtils,
|
||||
loadContext
|
||||
} from 'next-docs-zeta/contentlayer'
|
||||
import { buildPageTree } from 'next-docs-zeta/build-page-tree'
|
||||
import { createUtils, loadContext } from 'next-docs-zeta/contentlayer'
|
||||
import type { PageTree } from 'next-docs-zeta/server'
|
||||
|
||||
const ctx = loadContext(allMeta, allDocs)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { getPage, getPageUrl, tree } from '@/app/source'
|
||||
import { allDocs } from 'contentlayer/generated'
|
||||
import { allPages, getPage, getPageUrl, tree } from '@/app/source'
|
||||
import type { Metadata } from 'next'
|
||||
import { MDXContent } from 'next-docs-ui/mdx'
|
||||
import { DocsPage } from 'next-docs-ui/page'
|
||||
@@ -31,8 +30,8 @@ export default async function Page({
|
||||
}
|
||||
|
||||
export async function generateStaticParams(): Promise<{ slug: string[] }[]> {
|
||||
return allDocs.map(page => ({
|
||||
slug: page.slug.split('/')
|
||||
return allPages.map(page => ({
|
||||
slug: page.slugs
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
"import": "./dist/breadcrumb.mjs",
|
||||
"types": "./dist/breadcrumb.d.ts"
|
||||
},
|
||||
"./build-page-tree": {
|
||||
"import": "./dist/build-page-tree.mjs",
|
||||
"types": "./dist/build-page-tree.d.ts"
|
||||
},
|
||||
"./toc": {
|
||||
"import": "./dist/toc.mjs",
|
||||
"types": "./dist/toc.d.ts"
|
||||
|
||||
+96
-40
@@ -1,9 +1,58 @@
|
||||
import type { FileNode, FolderNode, PageTree, TreeNode } from '../server'
|
||||
import type { DocsPageBase, MetaPageBase, PagesContext } from './types'
|
||||
import { getKey, pathToName } from './utils'
|
||||
import type { ReactElement } from 'react'
|
||||
import type { FileNode, FolderNode, PageTree, TreeNode } from './server/types'
|
||||
|
||||
type Context = PagesContext & {
|
||||
export type File = {
|
||||
/**
|
||||
* Original path of file
|
||||
*/
|
||||
path: string
|
||||
|
||||
/**
|
||||
* File path without extension & prefix
|
||||
*/
|
||||
flattenedPath: string
|
||||
|
||||
/**
|
||||
* File name without extension
|
||||
*/
|
||||
name: string
|
||||
|
||||
dirname: string
|
||||
}
|
||||
|
||||
export type AbstractMeta = {
|
||||
file: File
|
||||
icon?: string
|
||||
title?: string
|
||||
pages: string[]
|
||||
}
|
||||
|
||||
export type AbstractPage = {
|
||||
file: File
|
||||
icon?: string
|
||||
title: string
|
||||
url: string
|
||||
}
|
||||
|
||||
export type Context = {
|
||||
lang?: string
|
||||
|
||||
getMetaByPath: (flattenPath: string) => AbstractMeta | null
|
||||
getPageByPath: (flattenPath: string) => AbstractPage | null
|
||||
|
||||
resolveIcon: (icon: string) => ReactElement | undefined
|
||||
|
||||
/**
|
||||
* Default pages without specified langauge
|
||||
*/
|
||||
basePages: AbstractPage[]
|
||||
}
|
||||
|
||||
type InternationalizedContext<Languages extends string> = Omit<
|
||||
Context,
|
||||
'lang'
|
||||
> & {
|
||||
languages: Languages[]
|
||||
}
|
||||
|
||||
export type Options = {
|
||||
@@ -18,8 +67,8 @@ const separator = /---(.*?)---/
|
||||
const rest = '...'
|
||||
const extractor = /\.\.\.(.+)/
|
||||
|
||||
function buildMeta(meta: MetaPageBase, ctx: Context): FolderNode {
|
||||
const segments = meta._raw.sourceFileDir.split('/')
|
||||
function buildMeta(meta: AbstractMeta, ctx: Context): FolderNode {
|
||||
const segments = meta.file.dirname.split('/')
|
||||
let index: FileNode | undefined = undefined
|
||||
const filtered = new Set<string>()
|
||||
|
||||
@@ -41,12 +90,12 @@ function buildMeta(meta: MetaPageBase, ctx: Context): FolderNode {
|
||||
item = extract_result[1]
|
||||
}
|
||||
|
||||
const path = meta._raw.sourceFileDir + '/' + item
|
||||
const page = ctx.docsMap.get(path)
|
||||
const path = meta.file.dirname + '/' + item
|
||||
const page = ctx.getPageByPath(path)
|
||||
|
||||
if (page != null) {
|
||||
const node = buildFileNode(page, ctx)
|
||||
filtered.add(page._raw.sourceFilePath)
|
||||
filtered.add(page.file.path)
|
||||
|
||||
if (item === 'index') index = node
|
||||
return node
|
||||
@@ -73,7 +122,7 @@ function buildMeta(meta: MetaPageBase, ctx: Context): FolderNode {
|
||||
if (item === '...') {
|
||||
return getFolderNodes(
|
||||
ctx,
|
||||
meta._raw.sourceFileDir,
|
||||
meta.file.dirname,
|
||||
false,
|
||||
path => !filtered.has(path)
|
||||
).children
|
||||
@@ -83,16 +132,16 @@ function buildMeta(meta: MetaPageBase, ctx: Context): FolderNode {
|
||||
})
|
||||
|
||||
if (index == null) {
|
||||
const page = ctx.docsMap.get(meta._raw.sourceFileDir + '/index')
|
||||
const page = ctx.getPageByPath(meta.file.dirname + '/index')
|
||||
|
||||
if (page != null) index = buildFileNode(page, ctx)
|
||||
}
|
||||
|
||||
return {
|
||||
name: meta.title ?? pathToName(segments),
|
||||
index,
|
||||
type: 'folder',
|
||||
icon: meta.icon && ctx.resolveIcon ? ctx.resolveIcon(meta.icon) : undefined,
|
||||
name: meta.title ?? index?.name ?? pathToName(segments),
|
||||
icon: meta.icon ? ctx.resolveIcon(meta.icon) : undefined,
|
||||
index,
|
||||
children
|
||||
}
|
||||
}
|
||||
@@ -109,17 +158,15 @@ function getFolderNodes(
|
||||
path: string,
|
||||
joinIndex: boolean,
|
||||
filter: (path: string) => boolean = () => true
|
||||
): { index: FileNode | null; children: TreeNode[] } {
|
||||
const pages = ctx.pages.get(ctx.lang ?? '') ?? []
|
||||
let index: FileNode | null = null
|
||||
): { index?: FileNode; children: TreeNode[] } {
|
||||
let index: FileNode | undefined
|
||||
const children: TreeNode[] = []
|
||||
|
||||
for (const page of pages) {
|
||||
if (page._raw.sourceFileDir !== path || !filter(page._raw.sourceFilePath))
|
||||
continue
|
||||
for (const page of ctx.basePages) {
|
||||
if (page.file.dirname !== path || !filter(page.file.path)) continue
|
||||
const node = buildFileNode(page, ctx)
|
||||
|
||||
if (page._raw.flattenedPath === path) {
|
||||
if (page.file.name === 'index') {
|
||||
index = node
|
||||
continue
|
||||
}
|
||||
@@ -127,13 +174,18 @@ function getFolderNodes(
|
||||
children.push(node)
|
||||
}
|
||||
|
||||
const segmentIndex = path.split('/').length
|
||||
const segments = path.split('/')
|
||||
const folders = new Set<string>(
|
||||
pages
|
||||
.filter(page => page._raw.sourceFileDir.startsWith(path + '/'))
|
||||
.map(
|
||||
page => path + '/' + page._raw.sourceFileDir.split('/')[segmentIndex]
|
||||
)
|
||||
ctx.basePages.flatMap(page => {
|
||||
const dirnameSegments = page.file.dirname.split('/')
|
||||
|
||||
if (path.length === 0 && path !== page.file.dirname)
|
||||
return dirnameSegments[0]
|
||||
if (page.file.dirname.startsWith(path + '/'))
|
||||
return path + '/' + dirnameSegments[segments.length]
|
||||
|
||||
return []
|
||||
})
|
||||
)
|
||||
|
||||
for (const folder of folders) {
|
||||
@@ -148,16 +200,16 @@ function getFolderNodes(
|
||||
return { index, children }
|
||||
}
|
||||
|
||||
function buildFileNode(page: DocsPageBase, ctx: Context): FileNode {
|
||||
function buildFileNode(page: AbstractPage, ctx: Context): FileNode {
|
||||
if (ctx.lang) {
|
||||
page = ctx.docsMap.get(getKey(page) + `.${ctx.lang}`) ?? page
|
||||
page = ctx.getPageByPath(page.file.flattenedPath + `.${ctx.lang}`) ?? page
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'page',
|
||||
name: page.title,
|
||||
url: ctx.getUrl(page.slug.split('/'), ctx.lang),
|
||||
icon: page.icon && ctx.resolveIcon ? ctx.resolveIcon(page.icon) : undefined
|
||||
icon: page.icon ? ctx.resolveIcon(page.icon) : undefined,
|
||||
url: page.url
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,20 +218,20 @@ function buildFolderNode(
|
||||
ctx: Context,
|
||||
keepIndex: boolean = false
|
||||
): FolderNode {
|
||||
let meta = ctx.lang ? ctx.metaMap.get(path + `/meta-${ctx.lang}`) : null
|
||||
meta ??= ctx.metaMap.get(path + '/meta')
|
||||
let meta: AbstractMeta | null = null
|
||||
if (ctx.lang) meta = ctx.getMetaByPath(path + `/meta-${ctx.lang}`)
|
||||
meta ??= ctx.getMetaByPath(path + '/meta')
|
||||
|
||||
if (meta != null) {
|
||||
return buildMeta(meta, ctx)
|
||||
}
|
||||
|
||||
const segments = path.split('/')
|
||||
const { index, children } = getFolderNodes(ctx, path, keepIndex)
|
||||
|
||||
return {
|
||||
name: index?.name ?? pathToName(segments),
|
||||
type: 'folder',
|
||||
index: index ?? undefined,
|
||||
name: index?.name ?? pathToName(path.split('/')),
|
||||
index,
|
||||
children
|
||||
}
|
||||
}
|
||||
@@ -189,13 +241,12 @@ function build(root: string, ctx: Context): PageTree {
|
||||
|
||||
return {
|
||||
name: folder.name,
|
||||
url: ctx.getUrl([], ctx.lang),
|
||||
children: folder.children
|
||||
}
|
||||
}
|
||||
|
||||
export function buildPageTree(
|
||||
context: PagesContext,
|
||||
context: Context,
|
||||
{ root = 'docs' }: Partial<Options> = {}
|
||||
): PageTree {
|
||||
return build(root, context)
|
||||
@@ -209,10 +260,10 @@ export function buildPageTree(
|
||||
* @param languages All supported languages
|
||||
*/
|
||||
export function buildI18nPageTree<Languages extends string = string>(
|
||||
context: PagesContext,
|
||||
{ languages, ...context }: InternationalizedContext<Languages>,
|
||||
{ root = 'docs' }: Partial<Options> = {}
|
||||
): Record<Languages, PageTree> {
|
||||
const entries = context.languages.map(lang => {
|
||||
const entries = languages.map(lang => {
|
||||
const tree = build(root, {
|
||||
...context,
|
||||
lang
|
||||
@@ -223,3 +274,8 @@ export function buildI18nPageTree<Languages extends string = string>(
|
||||
|
||||
return Object.fromEntries(entries)
|
||||
}
|
||||
|
||||
function pathToName(path: string[]): string {
|
||||
const name = path[path.length - 1] ?? 'docs'
|
||||
return name.slice(0, 1).toUpperCase() + name.slice(1)
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { buildI18nPageTree, buildPageTree } from '@/build-page-tree'
|
||||
import type { PageTree } from '@/server/types'
|
||||
import { buildI18nPageTree, buildPageTree } from './build-tree'
|
||||
import { loadContext, type ContextOptions } from './load-context'
|
||||
import type { DocsPageBase, MetaPageBase, PagesContext } from './types'
|
||||
import { createUtils, type ContentlayerUtils } from './utils'
|
||||
@@ -36,8 +36,8 @@ export const createContentlayer: CreateContentlayer = (
|
||||
|
||||
return {
|
||||
__pageContext: ctx,
|
||||
tree: (options?.languages != null
|
||||
? buildI18nPageTree(ctx)
|
||||
tree: (options.languages != null
|
||||
? buildI18nPageTree({ ...ctx, languages: options.languages })
|
||||
: // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
buildPageTree(ctx)) as any,
|
||||
...createUtils(ctx)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
export * from './load-context'
|
||||
export * from './build-tree'
|
||||
export { createUtils, ContentlayerUtils } from './utils'
|
||||
export { createContentlayer } from './create-contentlayer'
|
||||
|
||||
|
||||
@@ -1,58 +1,96 @@
|
||||
import type { AbstractMeta, AbstractPage, File } from '@/build-page-tree'
|
||||
import type { RawDocumentData } from 'contentlayer/source-files'
|
||||
import type { ReactElement } from 'react'
|
||||
import type { DocsPageBase, MetaPageBase, PagesContext } from './types'
|
||||
import { getKey, getPageUrl } from './utils'
|
||||
import { getPageUrl } from './utils'
|
||||
|
||||
export type ContextOptions = {
|
||||
languages: string[]
|
||||
/**
|
||||
* @default '/docs'
|
||||
*/
|
||||
|
||||
baseUrl: string
|
||||
/**
|
||||
* Get url from slugs and locale, override the default getUrl function
|
||||
*/
|
||||
getUrl: (slugs: string[], locale?: string) => string
|
||||
|
||||
resolveIcon: PagesContext['resolveIcon']
|
||||
resolveIcon: (icon: string) => ReactElement | undefined
|
||||
}
|
||||
|
||||
export function loadContext<
|
||||
Meta extends MetaPageBase,
|
||||
Docs extends DocsPageBase
|
||||
>(
|
||||
metaPages: Meta[],
|
||||
type MappedPage<Docs extends DocsPageBase> = { page: AbstractPage; ref: Docs }
|
||||
|
||||
export function loadContext<Docs extends DocsPageBase>(
|
||||
metaPages: MetaPageBase[],
|
||||
docsPages: Docs[],
|
||||
{
|
||||
languages = [],
|
||||
baseUrl = '/docs',
|
||||
getUrl,
|
||||
resolveIcon
|
||||
getUrl = (slugs, locale) => getPageUrl(slugs, baseUrl, locale),
|
||||
resolveIcon = () => undefined
|
||||
}: Partial<ContextOptions> = {}
|
||||
): PagesContext<Meta, Docs> {
|
||||
const docsMap = new Map<string, Docs>()
|
||||
const metaMap = new Map<string, Meta>()
|
||||
): PagesContext<Docs> {
|
||||
const basePages: AbstractPage[] = []
|
||||
const pageMap = new Map<string, MappedPage<Docs>>()
|
||||
const metaMap = new Map<string, AbstractMeta>()
|
||||
|
||||
for (const page of docsPages) {
|
||||
docsMap.set(getKey(page), page)
|
||||
const file = getFileData(page._raw)
|
||||
|
||||
const mapped: MappedPage<Docs> = {
|
||||
ref: page,
|
||||
page: {
|
||||
file,
|
||||
title: page.title,
|
||||
icon: page.icon,
|
||||
url: getUrl(page.slug.split('/'), page.locale)
|
||||
}
|
||||
}
|
||||
|
||||
if (!page.locale) basePages.push(mapped.page)
|
||||
pageMap.set(file.flattenedPath, mapped)
|
||||
}
|
||||
|
||||
for (const meta of metaPages) {
|
||||
metaMap.set(meta._raw.flattenedPath, meta)
|
||||
const file = getFileData(meta._raw)
|
||||
|
||||
metaMap.set(file.flattenedPath, {
|
||||
file,
|
||||
pages: meta.pages,
|
||||
icon: meta.icon,
|
||||
title: meta.title
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
i18nMap: getI18nPages(pageMap, languages),
|
||||
getMetaByPath(flattenPath) {
|
||||
return metaMap.get(flattenPath) ?? null
|
||||
},
|
||||
getPageByPath(flattenPath) {
|
||||
return pageMap.get(flattenPath)?.page ?? null
|
||||
},
|
||||
basePages,
|
||||
resolveIcon,
|
||||
languages,
|
||||
pages: getI18nPages(docsMap, languages),
|
||||
docsMap,
|
||||
metaMap,
|
||||
getUrl(slugs, locale) {
|
||||
return getUrl ? getUrl(slugs, locale) : getPageUrl(slugs, baseUrl, locale)
|
||||
}
|
||||
getUrl
|
||||
}
|
||||
}
|
||||
|
||||
function getFileData(raw: RawDocumentData): File {
|
||||
const dotIndex = raw.sourceFileName.lastIndexOf('.')
|
||||
const flattenedPath =
|
||||
raw.sourceFileDir === raw.flattenedPath
|
||||
? raw.flattenedPath + '/index'
|
||||
: raw.flattenedPath
|
||||
|
||||
return {
|
||||
dirname: raw.sourceFileDir,
|
||||
name: raw.sourceFileName.slice(0, dotIndex === -1 ? undefined : dotIndex),
|
||||
flattenedPath,
|
||||
path: raw.sourceFilePath
|
||||
}
|
||||
}
|
||||
|
||||
function getI18nPages<Docs extends DocsPageBase>(
|
||||
docsMap: Map<string, Docs>,
|
||||
docsMap: Map<string, MappedPage<Docs>>,
|
||||
languages: string[]
|
||||
): Map<string, Docs[]> {
|
||||
const pages = new Map<string, Docs[]>()
|
||||
@@ -63,13 +101,15 @@ function getI18nPages<Docs extends DocsPageBase>(
|
||||
}
|
||||
|
||||
for (const [key, value] of docsMap) {
|
||||
if (value.locale) continue
|
||||
if (value.ref.locale) continue
|
||||
|
||||
for (const lang of languages) {
|
||||
pages.get(lang)?.push(docsMap.get(`${key}.${lang}`) ?? value)
|
||||
const v = docsMap.get(`${key}.${lang}`) ?? value
|
||||
|
||||
pages.get(lang)?.push(v.ref)
|
||||
}
|
||||
|
||||
pages.get('')?.push(value)
|
||||
pages.get('')?.push(value.ref)
|
||||
}
|
||||
|
||||
return pages
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Context } from '@/build-page-tree'
|
||||
import type { RawDocumentData } from 'contentlayer/source-files'
|
||||
import type { ReactElement } from 'react'
|
||||
|
||||
export type MetaPageBase = {
|
||||
/** File path relative to `contentDirPath` */
|
||||
@@ -28,17 +28,10 @@ export type DocsPageBase = {
|
||||
slug: string
|
||||
}
|
||||
|
||||
export type PagesContext<
|
||||
Meta extends MetaPageBase = MetaPageBase,
|
||||
Docs extends DocsPageBase = DocsPageBase
|
||||
> = {
|
||||
export type PagesContext<Docs extends DocsPageBase = DocsPageBase> = Context & {
|
||||
/**
|
||||
* Language -> Page[]
|
||||
*/
|
||||
pages: Map<string, Docs[]>
|
||||
languages: string[]
|
||||
docsMap: Map<string, Docs>
|
||||
metaMap: Map<string, Meta>
|
||||
resolveIcon?: (icon: string) => ReactElement | undefined
|
||||
i18nMap: Map<string, Docs[]>
|
||||
getUrl: (slugs: string[], locale?: string) => string
|
||||
}
|
||||
|
||||
@@ -1,15 +1,4 @@
|
||||
import type { DocsPageBase, MetaPageBase, PagesContext } from './types'
|
||||
|
||||
export function pathToName(path: string[]): string {
|
||||
const name = path[path.length - 1] ?? 'docs'
|
||||
return name.slice(0, 1).toUpperCase() + name.slice(1)
|
||||
}
|
||||
|
||||
export function getKey(page: DocsPageBase): string {
|
||||
return page._raw.sourceFileDir === page._raw.flattenedPath
|
||||
? page._raw.flattenedPath + '/index'
|
||||
: page._raw.flattenedPath
|
||||
}
|
||||
import type { DocsPageBase, PagesContext } from './types'
|
||||
|
||||
export function getPageUrl(slug: string[], baseUrl: string, locale?: string) {
|
||||
const url = [baseUrl, locale, ...slug]
|
||||
@@ -43,16 +32,16 @@ export type ContentlayerUtils<Docs extends DocsPageBase> = {
|
||||
}
|
||||
|
||||
export function createUtils<Docs extends DocsPageBase>(
|
||||
context: PagesContext<MetaPageBase, Docs>
|
||||
context: PagesContext<Docs>
|
||||
): ContentlayerUtils<Docs> {
|
||||
return {
|
||||
getPages(language = '') {
|
||||
return context.pages.get(language)
|
||||
return context.i18nMap.get(language)
|
||||
},
|
||||
getPage(slugs = [], language = '') {
|
||||
const path = slugs.join('/')
|
||||
|
||||
return context.pages.get(language)?.find(page => page.slug === path)
|
||||
return context.i18nMap.get(language)?.find(page => page.slug === path)
|
||||
},
|
||||
getPageUrl(slug = [], language) {
|
||||
const slugs = typeof slug === 'string' ? slug.split('/') : slug
|
||||
|
||||
@@ -4,7 +4,7 @@ import tsconfig from './tsconfig.json'
|
||||
export default defineConfig({
|
||||
entry: [
|
||||
'src/{toc,link,breadcrumb,sidebar}.tsx',
|
||||
'src/{middleware,server,mdx-plugins}.ts',
|
||||
'src/{middleware,server,mdx-plugins,build-page-tree}.ts',
|
||||
'src/{search,search-algolia}/{client,server,shared}.ts',
|
||||
'src/contentlayer/{index,configuration}.ts'
|
||||
],
|
||||
|
||||
Generated
+7
-4
@@ -359,9 +359,6 @@ importers:
|
||||
|
||||
packages/next-docs-mdx:
|
||||
dependencies:
|
||||
'@next/mdx':
|
||||
specifier: ^13.5.6
|
||||
version: 13.5.6(@mdx-js/[email protected])(@mdx-js/[email protected])
|
||||
chokidar:
|
||||
specifier: ^3.5.3
|
||||
version: 3.5.3
|
||||
@@ -384,12 +381,18 @@ importers:
|
||||
'@mdx-js/react':
|
||||
specifier: ^2.3.0
|
||||
version: 2.3.0([email protected])
|
||||
'@next/mdx':
|
||||
specifier: 13.5.6
|
||||
version: 13.5.6(@mdx-js/[email protected])(@mdx-js/[email protected])
|
||||
'@types/mdast':
|
||||
specifier: ^3.0.12
|
||||
version: 3.0.12
|
||||
'@types/mdx':
|
||||
specifier: ^2.0.8
|
||||
version: 2.0.8
|
||||
'@types/react':
|
||||
specifier: 18.2.0
|
||||
version: 18.2.0
|
||||
next:
|
||||
specifier: 13.5.6
|
||||
version: 13.5.6(@babel/[email protected])([email protected])([email protected])
|
||||
@@ -1644,7 +1647,7 @@ packages:
|
||||
'@mdx-js/loader': 2.3.0([email protected])
|
||||
'@mdx-js/react': 2.3.0([email protected])
|
||||
source-map: 0.7.4
|
||||
dev: false
|
||||
dev: true
|
||||
|
||||
/@next/[email protected]:
|
||||
resolution: {integrity: sha512-5nvXMzKtZfvcu4BhtV0KH1oGv4XEW+B+jOfmBdpFI3C7FrB/MfujRpWYSBBO64+qbW8pkZiSyQv9eiwnn5VIQA==}
|
||||
|
||||
Reference in New Issue
Block a user