MDX: Make file paths relative to rootDir when resolving files

This commit is contained in:
SonMooSans
2023-12-07 21:54:44 +08:00
parent ebe8d9fa24
commit 69f8abf8ad
5 changed files with 44 additions and 55 deletions
+20
View File
@@ -0,0 +1,20 @@
---
'next-docs-mdx': major
---
**Make file paths relative to `rootDir` when resolving files**
For a more simplified usage, the resolved file paths will be relative to `rootDir`.
You can now generate slugs automatically depending on the root directory you have configured.
```ts
const utils = fromMap(map, {
rootDir: 'ui',
validate: {
frontmatter: frontmatterSchema
}
})
```
The configuration above will generate `/hello` slugs for a file named `/content/ui/hello.mdx`, while the previous one generates `/ui/hello`.
-10
View File
@@ -2,7 +2,6 @@ import { writeFileSync } from 'fs'
import path from 'path'
import { map } from '@/_map'
import { defaultValidators, fromMap, type Utils } from 'next-docs-mdx/map'
import type { FileInfo } from 'next-docs-mdx/types'
import type { StructuredData } from 'next-docs-zeta/mdx-plugins'
import { PHASE_PRODUCTION_BUILD } from 'next/constants'
import { z } from 'zod'
@@ -12,17 +11,10 @@ const frontmatterSchema = defaultValidators.frontmatter.extend({
index: z.boolean().default(false)
})
const getSlugs = (file: FileInfo) =>
file.flattenedPath
.split('/')
.filter(p => !['index', ''].includes(p))
.slice(1)
export const tabs: Record<string, Utils> = {
ui: fromMap(map, {
rootDir: 'ui',
baseUrl: '/docs/ui',
getSlugs,
validate: {
frontmatter: frontmatterSchema
}
@@ -30,7 +22,6 @@ export const tabs: Record<string, Utils> = {
headless: fromMap(map, {
rootDir: 'headless',
baseUrl: '/docs/headless',
getSlugs,
validate: {
frontmatter: frontmatterSchema
}
@@ -38,7 +29,6 @@ export const tabs: Record<string, Utils> = {
mdx: fromMap(map, {
rootDir: 'mdx',
baseUrl: '/docs/mdx',
getSlugs,
validate: {
frontmatter: frontmatterSchema
}
+3 -13
View File
@@ -20,19 +20,9 @@ type UtilsOptions<Langs extends string[] | undefined> = {
*/
baseUrl: string
/**
* Root directory, files outside of the root directory will be ignored
*
* @default ''
*/
rootDir: string
pageTreeOptions: BuildPageTreeOptions
getSlugs: ResolveOptions['getSlugs']
getUrl?: ResolveOptions['getUrl']
validate: ResolveOptions['validate']
} & BuilderOptions
} & BuilderOptions &
Pick<ResolveOptions, 'getSlugs' | 'getUrl' | 'validate' | 'rootDir'>
export type Utils = PageUtils & {
tree: PageTree
@@ -52,7 +42,7 @@ function fromMap<Langs extends string[] | undefined = undefined>(
getSlugs,
getUrl = createGetUrl(baseUrl),
resolveIcon,
pageTreeOptions = { root: rootDir },
pageTreeOptions = { root: '' },
languages,
validate
}: Partial<UtilsOptions<Langs>> = {}
+17 -27
View File
@@ -1,12 +1,9 @@
import path from 'path'
import type { AnyZodObject } from 'zod'
import type { FileInfo, MDXExport, Meta, Page } from './types'
import {
frontmatterSchema,
metaSchema,
type Frontmatter,
type MetaExport
} from './validate/schema'
import path from 'path';
import { joinPaths, splitPath } from 'next-docs-zeta/server';
import type { AnyZodObject } from 'zod';
import type { FileInfo, MDXExport, Meta, Page } from './types';
import { frontmatterSchema, metaSchema, type Frontmatter, type MetaExport } from './validate/schema';
const pageTypes = ['.md', '.mdx']
const metaTypes = ['.json']
@@ -20,7 +17,7 @@ export type ResolveOptions = {
map: Record<string, unknown>
/**
* root directory to resolve files
* root directory to resolve files, all slugs will be relative to the root directory
*
* @default ''
*/
@@ -52,15 +49,13 @@ export const defaultValidators = {
meta: metaSchema
}
function parsePath(p: string): FileInfo {
const parsed = path.parse(p)
function parsePath(p: string, root: string = ''): FileInfo | false {
if (!p.startsWith(root)) return false;
const relativePath = splitPath(p.substring(root.length)).join('/')
const parsed = path.parse(relativePath)
const normalizedDirname = parsed.dir.replaceAll('\\', '/')
let flattenedPath = normalizedDirname + '/' + parsed.name
while (flattenedPath.startsWith('/')) {
flattenedPath = flattenedPath.slice(1)
}
const flattenedPath = joinPaths([normalizedDirname, parsed.name])
const [, locale] = parsed.name.split('.')
return {
@@ -71,7 +66,7 @@ function parsePath(p: string): FileInfo {
flattenedPath,
locale,
type: parsed.ext,
path: p
path: relativePath
}
}
@@ -100,13 +95,8 @@ export function resolveFiles({
const pages: Page[] = []
for (const [path, v] of Object.entries(map)) {
const file = parsePath(path)
if (
rootDir.length > 0 &&
file.dirname != rootDir &&
!file.dirname.startsWith(rootDir + '/')
)
continue
const file = parsePath(path, rootDir)
if (file === false) continue
if (metaTypes.includes(file.type)) {
const meta: Meta = {
@@ -151,4 +141,4 @@ export function resolveFiles({
pages,
metas
}
}
}
+4 -5
View File
@@ -3,9 +3,6 @@ import type { StructuredData } from 'next-docs-zeta/mdx-plugins'
import type { TableOfContents } from 'next-docs-zeta/server'
import type * as Default from './validate/schema'
/**
* The file info, relative to root content directory
*/
export type FileInfo = {
locale?: string
@@ -30,17 +27,19 @@ export type FileInfo = {
name: string
/**
* Original path
* Path relative to `rootDir`
*/
path: string
/**
* A flatten path without extensions and prefixes, like `dir/file`
*
* relative to `rootDir`
*/
flattenedPath: string
/**
* Unique ID for each file, based on `path`
* Unique ID for each file, based on original path which is not relative to `rootDir`
*/
id: string
}