@@ -5,7 +5,7 @@ import type {
5
5
menuItemSchema ,
6
6
pageThemeSchema
7
7
} from '../server/schemas'
8
- import type { Folder , MdxFile , PageMapItem } from '../types'
8
+ import type { Folder , MdxFile , MetaJsonFile , PageMapItem } from '../types'
9
9
10
10
const DEFAULT_PAGE_THEME : PageTheme = {
11
11
breadcrumb : true ,
@@ -24,11 +24,12 @@ export type PageTheme = z.infer<typeof pageThemeSchema>
24
24
25
25
type Display = z . infer < typeof displaySchema >
26
26
type IMenuItem = z . infer < typeof menuItemSchema >
27
+ type MetaType = Record < string , any >
27
28
28
29
function extendMeta (
29
- _meta : Record < string , any > = { } ,
30
- fallback : Record < string , any > ,
31
- metadata : Record < string , any > = { }
30
+ _meta : MetaType = { } ,
31
+ fallback : MetaType ,
32
+ metadata : MetaType = { }
32
33
) : Record < string , any > {
33
34
const theme : PageTheme = {
34
35
...fallback . theme ,
@@ -116,74 +117,44 @@ export function normalizePages({
116
117
underCurrentDocsRoot ?: boolean
117
118
pageThemeContext ?: PageTheme
118
119
} ) : NormalizedResult {
119
- let _meta : Record < string , any > | undefined
120
- for ( const item of list ) {
120
+ let meta : MetaType = { }
121
+ let metaKeys : ( keyof MetaType ) [ ] = [ ]
122
+ const items : any [ ] = [ ]
123
+
124
+ for ( const [ index , item ] of list . entries ( ) ) {
121
125
if ( 'data' in item ) {
122
- _meta = item . data
123
- break
126
+ meta = item . data
127
+ metaKeys = Object . keys ( meta ) . filter ( key => key !== '*' )
128
+ for ( const key of metaKeys ) {
129
+ if ( typeof meta [ key ] !== 'string' ) continue
130
+ meta [ key ] = { title : meta [ key ] }
131
+ }
132
+ continue
124
133
}
125
- }
126
- const meta = _meta || { }
127
- const metaKeys = Object . keys ( meta ) . filter ( key => key !== '*' )
128
-
129
- for ( const key of metaKeys ) {
130
- if ( typeof meta [ key ] === 'string' ) {
131
- meta [ key ] = {
132
- title : meta [ key ]
134
+ const prevItem = list [ index - 1 ] as Exclude < PageMapItem , MetaJsonFile >
135
+
136
+ // If there are two items with the same name, they must be a directory and a
137
+ // page. In that case we merge them, and use the page's link.
138
+ if ( prevItem && prevItem . name === item . name ) {
139
+ items [ items . length - 1 ] = {
140
+ ...prevItem ,
141
+ withIndexPage : true ,
142
+ // @ts -expect-error fixme
143
+ frontMatter : item . frontMatter
133
144
}
145
+ continue
134
146
}
147
+ items . push ( item )
135
148
}
136
-
137
- // All directories
138
- // - directories: all directories in the tree structure
139
- // - flatDirectories: all directories in the flat structure, used by search and footer navigation
140
- const directories : Item [ ] = [ ]
141
- const flatDirectories : Item [ ] = [ ]
142
-
143
- // Docs directories
144
- const docsDirectories : DocsItem [ ] = [ ]
145
- const flatDocsDirectories : DocsItem [ ] = [ ]
146
-
147
- // Page directories
148
- const topLevelNavbarItems : ( PageItem | MenuItem ) [ ] = [ ]
149
-
150
- const { title : _title , href : _href , ...fallbackMeta } = meta [ '*' ] || { }
151
-
152
- let activeType : string = fallbackMeta . type
153
- let activeIndex = 0
154
- let activeThemeContext = {
155
- ...pageThemeContext ,
156
- ...fallbackMeta . theme
157
- }
158
- let activePath : Item [ ] = [ ]
159
-
160
149
// Normalize items based on files and _meta.json.
161
- const items : any [ ] = list
162
- . filter ( ( a ) : a is MdxFile | Folder => ! ( 'data' in a ) )
163
- . sort ( ( a , b ) => {
164
- const indexA = metaKeys . indexOf ( a . name )
165
- const indexB = metaKeys . indexOf ( b . name )
166
- if ( indexA === - 1 && indexB === - 1 ) return a . name < b . name ? - 1 : 1
167
- if ( indexA === - 1 ) return 1
168
- if ( indexB === - 1 ) return - 1
169
- return indexA - indexB
170
- } )
171
- . flatMap ( ( currentItem , index , list ) => {
172
- const nextItem = list [ index + 1 ]
173
- // If there are two items with the same name, they must be a directory and a
174
- // page. In that case we merge them, and use the page's link.
175
- if ( nextItem && nextItem . name === currentItem . name ) {
176
- list [ index + 1 ] = {
177
- ...currentItem ,
178
- // @ts -expect-error fixme
179
- withIndexPage : true ,
180
- // @ts -expect-error fixme
181
- frontMatter : nextItem . frontMatter
182
- }
183
- return [ ]
184
- }
185
- return [ currentItem ]
186
- } )
150
+ items . sort ( ( a , b ) => {
151
+ const indexB = metaKeys . indexOf ( b . name )
152
+ const indexA = metaKeys . indexOf ( a . name )
153
+ if ( indexB === - 1 ) {
154
+ return indexA === - 1 ? a . name - b . name : - 1
155
+ }
156
+ return indexA - indexB
157
+ } )
187
158
188
159
for ( const [ index , metaKey ] of metaKeys . entries ( ) ) {
189
160
if ( items . some ( item => item . name === metaKey ) ) continue
@@ -213,6 +184,29 @@ The field key "${metaKey}" in \`_meta\` file refers to a page that cannot be fou
213
184
)
214
185
}
215
186
187
+ // All directories
188
+ // - directories: all directories in the tree structure
189
+ // - flatDirectories: all directories in the flat structure, used by search and footer navigation
190
+ const directories : Item [ ] = [ ]
191
+ const flatDirectories : Item [ ] = [ ]
192
+
193
+ // Docs directories
194
+ const docsDirectories : DocsItem [ ] = [ ]
195
+ const flatDocsDirectories : DocsItem [ ] = [ ]
196
+
197
+ // Page directories
198
+ const topLevelNavbarItems : ( PageItem | MenuItem ) [ ] = [ ]
199
+
200
+ const { title : _title , href : _href , ...fallbackMeta } = meta [ '*' ] || { }
201
+
202
+ let activeType : string = fallbackMeta . type
203
+ let activeIndex = 0
204
+ let activeThemeContext = {
205
+ ...pageThemeContext ,
206
+ ...fallbackMeta . theme
207
+ }
208
+ let activePath : Item [ ] = [ ]
209
+
216
210
for ( const currentItem of items ) {
217
211
// Get the item's meta information.
218
212
const extendedMeta = extendMeta (
0 commit comments