11import * as hp from 'helper-js'
2- import * as fs from 'fs'
2+ import * as fs from 'fs-extra '
33import * as path from 'path'
4- import { execSync } from 'child_process'
54import * as chokidar from 'chokidar'
65import * as crypto from 'crypto'
76import * as cheerio from 'cheerio'
@@ -13,11 +12,7 @@ import { docsDir, getLocales } from './utils'
1312const compiledDir = 'src/compiled-docs'
1413
1514const start = ( ) => {
16- if ( fs . existsSync ( compiledDir ) ) {
17- execSync ( `rm ${ compiledDir } -rf` )
18- }
19- fs . mkdirSync ( compiledDir )
20-
15+ fs . emptyDirSync ( compiledDir ) // empty dir; create dir if not existing
2116 const watcher = chokidar . watch ( docsDir )
2217 const data = {
2318 routes : { } ,
@@ -29,6 +24,7 @@ const start = () => {
2924 componentPath : string
3025 path : string
3126 meta : Object
27+ searchData ?: boolean
3228 }
3329 }
3430 }
@@ -49,6 +45,19 @@ const start = () => {
4945 fs . writeFileSync ( path . join ( compiledDir , 'routes.ts' ) , routesContent )
5046 } , 100 ) . action
5147
48+ const updateSearchDataLoader = hp . debounceTrailing ( ( ) => {
49+ let r = `export default {`
50+ for ( const info of Object . values ( data . routes ) ) {
51+ if ( info . searchData ) {
52+ r +=
53+ '\n' +
54+ `"${ info . path } ": async () => (await import("./searchData/${ info . md5Name } .json")).default,`
55+ }
56+ }
57+ r += '}'
58+ fs . outputFileSync ( path . join ( compiledDir , 'searchDataLoader.ts' ) , r )
59+ } , 100 ) . action
60+
5261 console . log ( 'start watching doc files' )
5362 let first = true
5463 const firstDone = hp . debounceTrailing ( async ( ) => {
@@ -77,7 +86,9 @@ const start = () => {
7786 fs . unlinkSync ( componentPath )
7887 } else {
7988 const locales = getLocales ( )
89+ const searchUrls = new Set ( getSearchUrls ( locales ) )
8090 let t = filepath . split ( path . sep )
91+ let searchData = false
8192 const locale = t [ 1 ]
8293 const pathWithoutLocale = t . slice ( 2 ) . join ( '/' )
8394 const fileContent = fs . readFileSync ( filepath ) . toString ( )
@@ -86,6 +97,7 @@ const start = () => {
8697 const html = marked ( codeDemoReplaced )
8798 let injectedComponents : Record < string , string > = { }
8899 const vueTemplate = handleHtmlForVue ( html , filepath , injectedComponents )
100+ const urlPath = genUrl ( locale , pathWithoutLocale )
89101
90102 const structure = resolveMdStructure ( html )
91103
@@ -95,6 +107,7 @@ const start = () => {
95107 const componentContent = tpl
96108 . replace ( '<!-- :template -->' , vueTemplate )
97109 . replace ( "':data'" , JSON . stringify ( structure ) )
110+ . replaceAll ( ':url' , urlPath )
98111 . replace (
99112 / (?< = \n | ^ ) ( < s c r i p t .* ?> ) / ,
100113 '$1\n' +
@@ -115,7 +128,27 @@ const start = () => {
115128 ) . replace ( / : " ( .* ?) " / g, ':$1' )
116129 )
117130 fs . writeFileSync ( componentPath , componentContent )
118- const urlPath = genUrl ( locale , pathWithoutLocale )
131+ if ( searchUrls . has ( urlPath ) ) {
132+ const searchDataPath = path . join (
133+ compiledDir ,
134+ './searchData' ,
135+ md5Name + '.json'
136+ )
137+ searchData = true
138+ const flatSearchData : unknown [ ] = [ ]
139+ const nodeIDMapping = new WeakMap ( )
140+ let nodeIndex = 0
141+ hp . walkTreeData ( structure , ( node , i , parent ) => {
142+ nodeIDMapping . set ( node , nodeIndex )
143+ flatSearchData . push ( {
144+ title : node . name ,
145+ url : urlPath + '#' + node . id ,
146+ pid : parent ? nodeIDMapping . get ( parent ) : null ,
147+ } )
148+ nodeIndex ++
149+ } )
150+ fs . outputJSONSync ( searchDataPath , flatSearchData )
151+ }
119152 const alternate : any = { }
120153 for ( const locale2 of locales ) {
121154 const alternateFile = path . join ( docsDir , locale2 , pathWithoutLocale )
@@ -130,6 +163,7 @@ const start = () => {
130163 componentPath,
131164 path : urlPath ,
132165 meta : routeMeta ,
166+ searchData,
133167 }
134168 // update alternate routes
135169 const alternatePaths = Object . values ( alternate )
@@ -142,6 +176,7 @@ const start = () => {
142176 }
143177 //
144178 updateRoutes ( )
179+ updateSearchDataLoader ( )
145180 //
146181 if ( first ) {
147182 firstDone ( )
@@ -152,13 +187,16 @@ const start = () => {
152187start ( )
153188
154189function genUrl ( locale : string , pathWithoutLocale : string ) {
155- let t = `/${ pathWithoutLocale . replace ( '.md' , '' ) } `
190+ let t = `/${ pathWithoutLocale . replace ( '.md' , '' ) } ` . replace ( / ^ \/ \/ / , '/' )
191+ if ( t === '/' ) {
192+ t = ''
193+ }
156194 if ( locale !== baseConfig . I18N . locale ) {
157195 t = `/${ locale } ` + t
158196 }
159- t = t . replace ( / i n d e x $ / , '' )
160- if ( ! t ) {
161- t = '/'
197+ t = t . replace ( / ( ^ | \/ ) i n d e x / , '$1 ' )
198+ if ( t [ 0 ] !== '/' ) {
199+ t = '/' + t
162200 }
163201 return t
164202}
@@ -340,3 +378,24 @@ function internalDocHrefToUrl(href: string, docPath: string) {
340378 }
341379 return url
342380}
381+
382+ function getSearchUrls ( locales : string [ ] ) {
383+ const r : string [ ] = [ ]
384+ if ( baseConfig . SEARCH ) {
385+ r . push ( ...baseConfig . SEARCH )
386+ }
387+ if ( baseConfig . SUBPATH ) {
388+ for ( const sp of baseConfig . SUBPATH ) {
389+ if ( sp . search ) {
390+ r . push ( ...sp . search )
391+ }
392+ }
393+ }
394+ const r2 : string [ ] = [ ]
395+ for ( const url of r ) {
396+ for ( const locale of locales ) {
397+ r2 . push ( genUrl ( locale , url ) )
398+ }
399+ }
400+ return r2
401+ }
0 commit comments