diff --git a/examples/basic/content/docs/features.mdx b/examples/basic/content/docs/features.mdx index 72bde9c..313e341 100644 --- a/examples/basic/content/docs/features.mdx +++ b/examples/basic/content/docs/features.mdx @@ -128,6 +128,72 @@ lastModified: 2024-01-15 --- +## Sorting Pages and Folders + +Control the order of pages and folders in the sidebar. + +### Sorting Pages + +Add `order` to page frontmatter. Lower numbers appear first. Pages without `order` appear at the end. + +```mdx +--- +title: Introduction +order: 1 +--- +``` + +```mdx +--- +title: Installation +order: 2 +--- +``` + +Alternatively, use the `pages` array in `meta.json` to explicitly order pages within a folder: + +```json +{ + "pages": ["introduction", "installation", "configuration"] +} +``` + +### Sorting Folders + +Add `order` to the folder's `meta.json`. This works even for folders without an index page. + +``` +docs/ +├── getting-started/ +│ └── meta.json ← {"title": "Getting Started", "order": 1} +├── guides/ +│ └── meta.json ← {"title": "Guides", "order": 2} +└── api/ + └── meta.json ← {"title": "API Reference", "order": 3} +``` + +`getting-started/meta.json`: +```json +{ + "title": "Getting Started", + "order": 1 +} +``` + +`guides/meta.json`: +```json +{ + "title": "Guides", + "order": 2 +} +``` + +Folders without `order` appear after all ordered folders. + +Folder sorting is controlled **only** by `meta.json` `order`. The index page frontmatter `order` does not affect folder position — it only controls the page's position within the folder. + +--- + ## Markdown URLs Every page has a `.md` URL that returns raw markdown: diff --git a/packages/chronicle/src/lib/source.ts b/packages/chronicle/src/lib/source.ts index f7e4db1..89de861 100644 --- a/packages/chronicle/src/lib/source.ts +++ b/packages/chronicle/src/lib/source.ts @@ -120,14 +120,30 @@ export function invalidate() { cachedNavMap = null; } +function getFolderPath(node: Folder): string | null { + const firstPage = findFirstPage(node); + if (!firstPage) return null; + const parts = firstPage.url.split('/').filter(Boolean); + parts.pop(); + return '/' + parts.join('/'); +} + +function findFirstPage(node: Folder): { url: string } | null { + for (const child of node.children) { + if (child.type === 'page') return child; + if (child.type === 'folder') { + const found = findFirstPage(child); + if (found) return found; + } + } + return node.index ?? null; +} + function getOrder(node: Node, pageOrderMap: Map, folderOrderMap: Map): number | undefined { if (node.type === 'page') return pageOrderMap.get(node.url); if (node.type === 'folder') { - if (node.index) { - const fromMeta = folderOrderMap.get(node.index.url); - if (fromMeta !== undefined) return fromMeta; - return pageOrderMap.get(node.index.url); - } + const folderPath = getFolderPath(node); + if (folderPath) return folderOrderMap.get(folderPath); } return undefined; }