|
1 | 1 | import { readFileSync, existsSync } from 'node:fs'; |
2 | 2 | import { join } from 'node:path'; |
3 | 3 | import { load } from 'js-yaml'; |
| 4 | +import { generateSidebar } from 'vitepress-sidebar'; |
| 5 | +import type { VitePressSidebarOptions } from 'vitepress-sidebar'; |
4 | 6 |
|
5 | | -// Type definitions for sidebar items |
6 | | -export interface SidebarLeaf { |
7 | | - text: string; |
8 | | - link: string; |
9 | | - collapsed?: boolean; |
10 | | -} |
| 7 | +/** |
| 8 | + * Generates a sidebar with weight-based sorting and standard post-processing. |
| 9 | + * Shared pipeline for docs and community sidebars. |
| 10 | + */ |
| 11 | +export function generateWeightSortedSidebar(config: VitePressSidebarOptions): any { |
| 12 | + const sidebar = generateSidebar([config]); |
| 13 | + const base = config.scanStartPath || ''; |
| 14 | + const resolvePath = config.resolvePath || '/'; |
11 | 15 |
|
12 | | -export interface SidebarBranch { |
13 | | - text: string; |
14 | | - items: (SidebarLeaf | SidebarBranch)[]; |
15 | | - collapsed?: boolean; |
| 16 | + const sorted = sortByWeight(sidebar, base); |
| 17 | + const filtered = removeIndexEntries(sorted); |
| 18 | + const cleaned = removeEmptyItems(filtered); |
| 19 | + addTrailingSlashToLinks(cleaned[resolvePath].items); |
| 20 | + return cleaned; |
16 | 21 | } |
17 | 22 |
|
18 | | -export type SidebarItem = SidebarLeaf | SidebarBranch; |
19 | | - |
20 | | - |
21 | 23 | /** |
22 | 24 | * Recursively removes all _index.md entries from the sidebar |
23 | 25 | */ |
@@ -188,116 +190,6 @@ export function getWeightFromFile(link: string, base?: string): number | null { |
188 | 190 | } |
189 | 191 | } |
190 | 192 |
|
191 | | -/** |
192 | | - * Recursively enhances directory titles by reading from _index.md frontmatter |
193 | | - */ |
194 | | -export function enhanceDirectoryTitles(sidebar: any, base): any { |
195 | | - if (Array.isArray(sidebar)) { |
196 | | - return sidebar.map(item => enhanceDirectoryTitles(item, base)); |
197 | | - } |
198 | | - |
199 | | - if (typeof sidebar !== 'object' || sidebar === null) { |
200 | | - return sidebar; |
201 | | - } |
202 | | - |
203 | | - // Create a copy of the object |
204 | | - const enhanced = { ...sidebar }; |
205 | | - |
206 | | - // If this object has items (indicating it's a directory), enhance it |
207 | | - if (enhanced.items && Array.isArray(enhanced.items)) { |
208 | | - // Look for _index.md file in the items |
209 | | - const indexItem = enhanced.items.find((item: any) => |
210 | | - item.link && (item.link === '_index' || item.link.endsWith('/_index')) |
211 | | - ); |
212 | | - |
213 | | - if (indexItem) { |
214 | | - // Try to read the frontmatter and update the title |
215 | | - const title = getTitleFromIndexFile(indexItem.link, base); |
216 | | - if (title) { |
217 | | - enhanced.text = title; |
218 | | - } |
219 | | - } |
220 | | - |
221 | | - // Recursively process all items |
222 | | - enhanced.items = enhanced.items.map((item: any) => enhanceDirectoryTitles(item, base)); |
223 | | - } |
224 | | - |
225 | | - // If it's a top-level section with items, process those too |
226 | | - if (enhanced.base && enhanced.items) { |
227 | | - enhanced.items = enhanced.items.map((item: any) => enhanceDirectoryTitles(item, base)); |
228 | | - } |
229 | | - |
230 | | - // Process other properties recursively |
231 | | - for (const [key, value] of Object.entries(enhanced)) { |
232 | | - if (key !== 'items' && typeof value === 'object') { |
233 | | - enhanced[key] = enhanceDirectoryTitles(value, base); |
234 | | - } |
235 | | - } |
236 | | - |
237 | | - return enhanced; |
238 | | -} |
239 | | - |
240 | | -/** |
241 | | - * Reads the title from an _index.md file's frontmatter |
242 | | - */ |
243 | | -export function getTitleFromIndexFile(link: string, base?: string): string | null { |
244 | | - try { |
245 | | - // Construct the file path |
246 | | - let filePath: string; |
247 | | - |
248 | | - if (link === '_index') { |
249 | | - // For root _index files |
250 | | - filePath = join(process.cwd(), 'hugo', 'content', base, '_index.md'); |
251 | | - } else if (link.endsWith('/_index')) { |
252 | | - // For nested _index files |
253 | | - const relativePath = link.replace('/_index', ''); |
254 | | - filePath = join(process.cwd(), 'hugo', 'content', base, relativePath, '_index.md'); |
255 | | - } else { |
256 | | - return null; |
257 | | - } |
258 | | - |
259 | | - // Check if file exists |
260 | | - if (!existsSync(filePath)) { |
261 | | - return null; |
262 | | - } |
263 | | - |
264 | | - // Read the file content |
265 | | - const content = readFileSync(filePath, 'utf-8'); |
266 | | - |
267 | | - // Extract frontmatter |
268 | | - const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/); |
269 | | - if (!frontmatterMatch) { |
270 | | - return null; |
271 | | - } |
272 | | - |
273 | | - // Parse YAML frontmatter |
274 | | - const frontmatter = load(frontmatterMatch[1]) as any; |
275 | | - |
276 | | - // Return the title if it exists |
277 | | - return frontmatter?.title || null; |
278 | | - |
279 | | - } catch (error) { |
280 | | - console.warn(`Error reading title from ${link}:`, error); |
281 | | - return null; |
282 | | - } |
283 | | -} |
284 | | - |
285 | | - |
286 | | -/** |
287 | | - * Function to recursively extract all items from a section |
288 | | - */ |
289 | | -export function extractItems(section: any): SidebarItem[] { |
290 | | - if (Array.isArray(section)) { |
291 | | - return section as SidebarItem[]; |
292 | | - } |
293 | | - if (section && typeof section === 'object' && 'items' in section) { |
294 | | - return section.items as SidebarItem[]; |
295 | | - } |
296 | | - return []; |
297 | | -} |
298 | | - |
299 | | - |
300 | | - |
301 | 193 | /** |
302 | 194 | * Recursively removes all items fields from the sidebar object that are empty arrays |
303 | 195 | */ |
|
0 commit comments