-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathutils.ts
More file actions
101 lines (92 loc) · 3.02 KB
/
utils.ts
File metadata and controls
101 lines (92 loc) · 3.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import fs from 'node:fs/promises'
import path from 'node:path'
import type { NavItem } from '@rspress/shared'
import { loadFrontMatter } from '@rspress/shared/node-utils'
import { logger } from 'rspress/core'
import { extractTextAndId } from '../../shared/index.js'
import { pathExists } from '../../utils/index.js'
import type { DoomSidebar } from './walk.js'
export async function detectFilePath(rawPath: string, extensions: string[]) {
// The params doesn't have extension name, so we need to try to find the file with the extension name.
let realPath: string | undefined = rawPath
const fileExtname = path.extname(rawPath)
// pathname may contain .json, see issue: https://github.com/web-infra-dev/rspress/issues/951
if (!extensions.includes(fileExtname)) {
const pathWithExtension = extensions.map((ext) => `${rawPath}${ext}`)
const pathExistInfo = await Promise.all(
pathWithExtension.map((p) => pathExists(p)),
)
const findPath = pathWithExtension.find((_, i) => pathExistInfo[i])
// file may be public resource, see issue: https://github.com/web-infra-dev/rspress/issues/1052
if (!fileExtname || findPath) {
realPath = findPath
}
}
return realPath
}
export async function extractInfoFromFrontmatter(
filePath: string,
rootDir: string,
extensions: string[],
): Promise<{
realPath: string | undefined
title: string
overviewHeaders: number[] | undefined
context: string | undefined
weight?: number
}> {
const realPath = await detectFilePath(filePath, extensions)
if (!realPath) {
logger.warn(
`Can't find the file: ${filePath}, please check it in "${path.join(
path.dirname(filePath),
'_meta.json',
)}".`,
)
return {
realPath,
title: '',
overviewHeaders: undefined,
context: undefined,
}
}
const content = await fs.readFile(realPath, 'utf-8')
const fileNameWithoutExt = path.basename(realPath, path.extname(realPath))
// eslint-disable-next-line regexp/no-super-linear-backtracking
const h1RegExp = /^#\s+(.*)$/m
const match = content.match(h1RegExp)
let contentTitle = match?.[1]?.trim()
if (contentTitle) {
contentTitle =
contentTitle.match(
/\{\s*useI18n\s*\(\s*\)\s*\(\s*(['"])([^'"]+)\1\s*\)\s*\}/,
)?.[2] ?? contentTitle
}
const { frontmatter } = loadFrontMatter<{
title?: string
overviewHeaders?: number[]
context?: string
weight?: number
}>(content, filePath, rootDir)
return {
realPath,
title: extractTextAndId(
frontmatter.title || contentTitle || fileNameWithoutExt,
)[0],
overviewHeaders: frontmatter.overviewHeaders,
context: frontmatter.context,
weight: frontmatter.weight,
}
}
export function combineWalkResult(
walks: { nav: NavItem[]; sidebar: Record<string, DoomSidebar[]> }[],
versions: string[],
) {
return walks.reduce(
(acc, cur, curIndex) => ({
nav: { ...acc.nav, [versions[curIndex] || 'default']: cur.nav },
sidebar: { ...acc.sidebar, ...cur.sidebar },
}),
{ nav: {}, sidebar: {} },
)
}