1
1
import path from 'path' ;
2
2
import fs from 'fs/promises' ;
3
+ import fm from 'front-matter' ;
3
4
import { watch , type FSWatcher } from 'fs' ;
4
5
import type { Plugin } from 'vite' ;
5
6
6
7
export const DOCS_NAVIGATION = 'navigation.json' ;
8
+ export const ZH_DOCS_NAVIGATION = 'navigation_zh.json' ;
7
9
8
10
const ROOT_PATH = path . join ( __dirname , '../../../' ) ;
9
11
const ROOT_STATIC_PATH = path . join ( ROOT_PATH , 'static/docs' ) ;
@@ -18,41 +20,47 @@ type DocsTree =
18
20
order : number ;
19
21
title : string ;
20
22
path : string ;
23
+ metadata : Record < string , any > ;
21
24
} ;
22
25
23
26
const isPathIn = ( a : string , b : string ) => {
24
27
const relative = path . relative ( b , a ) ;
25
28
return ! relative . startsWith ( '..' ) && ! path . isAbsolute ( relative ) ;
26
29
} ;
27
30
28
- const createDirectory = async (
31
+ const createNavigation = async (
29
32
source : string ,
30
33
root : string | undefined = undefined
31
34
) : Promise < DocsTree [ ] > => {
32
- const docsTree = [ ] ;
35
+ const docsTree : DocsTree [ ] = [ ] ;
33
36
34
37
const files = await fs . readdir ( source , { withFileTypes : true } ) ;
35
38
for ( const file of files ) {
36
39
//Generate a navigation from an en document
37
40
const [ order , title ] = file . name . split ( '.' ) ;
38
- if ( ! order || ! title ) continue ; // 跳过不符合“序号.标题”格式的文件或目录
41
+ // 跳过不符合“序号.标题”格式的文件或目录
42
+ if ( ! order || ! title ) continue ;
39
43
40
44
if ( file . isDirectory ( ) ) {
41
45
const root2 = root ? `${ root } /${ title } ` : title ;
42
- const childrenTree = await createDirectory ( path . join ( source , file . name ) , root2 ) ;
46
+ const childrenTree = await createNavigation ( path . join ( source , file . name ) , root2 ) ;
43
47
docsTree . push ( {
44
48
order : parseInt ( order , 10 ) ,
45
49
title : title . replace ( / - / g, ' ' ) ,
46
50
children : childrenTree
47
51
} ) ;
48
52
} else if ( file . isFile ( ) && file . name . endsWith ( '.md' ) ) {
53
+ const content = await fs . readFile ( path . join ( source , file . name ) , 'utf-8' ) ;
54
+ const { attributes } = fm ( content ) ;
55
+
49
56
const title2 = title . replace ( '.md' , '' ) ;
50
57
// svelte router path
51
- const path = root ? `/docs/${ root } /${ title2 } ` : `/docs/${ title2 } ` ;
58
+ const urlPath = root ? `/docs/${ root } /${ title2 } ` : `/docs/${ title2 } ` ;
52
59
docsTree . push ( {
53
60
order : parseInt ( order , 10 ) ,
54
61
title : title2 . replace ( / - / g, ' ' ) ,
55
- path : path
62
+ path : urlPath ,
63
+ metadata : attributes as Record < string , any >
56
64
} ) ;
57
65
}
58
66
}
@@ -137,7 +145,15 @@ export const docs = ({
137
145
const sourcePath = path . join ( __dirname , source ) ;
138
146
const targetPath = path . join ( __dirname , target ) ;
139
147
const docStaticPath = path . join ( __dirname , staticDir ) ;
140
- const menusJSONPath = path . join ( targetPath , DOCS_NAVIGATION ) ;
148
+ const navJSONPath = path . join ( targetPath , DOCS_NAVIGATION ) ;
149
+ const zhNavJSONPath = path . join ( targetPath , ZH_DOCS_NAVIGATION ) ;
150
+
151
+ const i18nWriteNavigationFile = async ( ) => {
152
+ const enDocsTree = await createNavigation ( path . join ( ROOT_PATH , 'docs' ) ) ;
153
+ const zhDocsTree = await createNavigation ( path . join ( ROOT_PATH , 'docs' , 'zh' ) ) ;
154
+ await fs . writeFile ( navJSONPath , JSON . stringify ( enDocsTree ) ) ;
155
+ await fs . writeFile ( zhNavJSONPath , JSON . stringify ( zhDocsTree ) ) ;
156
+ } ;
141
157
142
158
/** 复制静态文件 */
143
159
const copyStaticFiles = async ( files : [ string , string ] [ ] ) => {
@@ -175,8 +191,6 @@ export const docs = ({
175
191
176
192
/** 监听 docs 目录下的文件变化,实时更新 docs 目录 */
177
193
const buildDocsPage = ( source : string , target : string ) => {
178
- const menusJSONPath = path . join ( target , DOCS_NAVIGATION ) ;
179
-
180
194
const events = new Set < string > ( ) ;
181
195
let timer : NodeJS . Timeout | null = null ;
182
196
@@ -189,8 +203,7 @@ export const docs = ({
189
203
events . clear ( ) ;
190
204
console . debug ( `Docs page ${ Array . from ( cache ) . join ( ',' ) } changed: rebuild...` ) ;
191
205
// 写入新的文档目录
192
- const docsTree = await createDirectory ( source ) ;
193
- await fs . writeFile ( menusJSONPath , JSON . stringify ( docsTree ) ) ;
206
+ await i18nWriteNavigationFile ( ) ;
194
207
cache . forEach ( async ( filename ) => {
195
208
const sourceFile = path . join ( source , filename ) ;
196
209
if ( filename . endsWith ( '.md' ) ) {
@@ -226,8 +239,7 @@ export const docs = ({
226
239
async config ( config , { command } ) {
227
240
isDev = command === 'serve' ;
228
241
// 写入新的文档目录
229
- const docsTree = await createDirectory ( sourcePath ) ;
230
- await fs . writeFile ( menusJSONPath , JSON . stringify ( docsTree ) ) ;
242
+ await i18nWriteNavigationFile ( ) ;
231
243
await removeDocsCache ( targetPath ) ;
232
244
await copyDocsPage ( sourcePath , targetPath ) ;
233
245
} ,
0 commit comments