diff --git a/src/runtime/utils/index.ts b/src/runtime/utils/index.ts index f6d573990..9b28d2819 100644 --- a/src/runtime/utils/index.ts +++ b/src/runtime/utils/index.ts @@ -20,9 +20,9 @@ export function findPageBreadcrumb(navigation?: ContentNavigationItem[], path?: }, []) } -type FindPageChildrenOptions = { indexAsChild?: boolean } +type FindPageOptions = { indexAsChild?: boolean } -export function findPageChildren(navigation?: ContentNavigationItem[], path?: string | undefined | null, options?: FindPageChildrenOptions): ContentNavigationItem[] { +export function findPageChildren(navigation?: ContentNavigationItem[], path?: string | undefined | null, options?: FindPageOptions): ContentNavigationItem[] { if (!navigation?.length || !path) { return [] } @@ -41,7 +41,7 @@ export function findPageChildren(navigation?: ContentNavigationItem[], path?: st }, []) } -export function findPageSiblings(navigation?: ContentNavigationItem[], path?: string | undefined | null, options?: FindPageChildrenOptions): ContentNavigationItem[] { +export function findPageSiblings(navigation?: ContentNavigationItem[], path?: string | undefined | null, options?: FindPageOptions): ContentNavigationItem[] { if (!navigation?.length || !path) { return [] } @@ -50,3 +50,39 @@ export function findPageSiblings(navigation?: ContentNavigationItem[], path?: st return findPageChildren(navigation, parentPath, options).filter(c => c.path !== path) } + +export function findPageHeadline(navigation?: ContentNavigationItem[], path?: string | undefined | null, options?: FindPageOptions): string | undefined { + if (!navigation?.length || !path) { + return + } + + for (const link of navigation) { + if (options?.indexAsChild) { + if (link.children) { + const headline = findPageHeadline(link.children, path, options) + if (headline) { + return headline + } + for (const child of link.children) { + if (child.path === path) { + return link.title + } + } + } + } + else { + if (link.children) { + for (const child of link.children) { + const isIndex = child.stem?.endsWith('/index') + if (child.path === path && !isIndex) { + return link.title + } + } + const headline = findPageHeadline(link.children, path, options) + if (headline) { + return headline + } + } + } + } +} diff --git a/test/unit/utils.test.ts b/test/unit/utils.test.ts index dd630f2ec..d9b90b322 100644 --- a/test/unit/utils.test.ts +++ b/test/unit/utils.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect } from 'vitest' -import { findPageBreadcrumb, findPageChildren, findPageSiblings } from '@nuxt/content/utils' +import { findPageBreadcrumb, findPageChildren, findPageSiblings, findPageHeadline } from '@nuxt/content/utils' describe('utils', () => { const navigation = [ @@ -32,6 +32,48 @@ describe('utils', () => { }, ] + const navigation2 = [ + { + title: 'Guide Dir', + path: '/guide', + stem: 'guide', + children: [ + { + title: 'Guide Index', + path: '/guide', + stem: 'guide/index', + }, + { + title: 'Getting Started Dir', + path: '/guide/getting-started', + stem: 'guide/getting-started', + children: [ + { + title: 'Getting Started Index', + path: '/guide/getting-started', + stem: 'guide/getting-started/index', + }, + { + title: 'Getting Started 1', + path: '/guide/getting-started/1', + stem: 'guide/getting-started/1', + }, + { + title: 'Getting Started 2', + path: '/guide/getting-started/2', + stem: 'guide/getting-started/2', + }, + ], + }, + { + title: 'Introduction', + path: '/guide/introduction', + stem: 'guide/introduction', + }, + ], + }, + ] + function removeChildren(array) { return array.map((obj) => { const { children, ...rest } = obj @@ -116,9 +158,9 @@ describe('utils', () => { }) it('findPageChildren', async () => { - const breadcrumb = removeChildren(findPageChildren(navigation, '/guide')) + const pages = removeChildren(findPageChildren(navigation, '/guide')) - expect(breadcrumb).toEqual([ + expect(pages).toEqual([ { title: 'Getting Started', path: '/guide/getting-started', @@ -133,9 +175,9 @@ describe('utils', () => { }) it('findPageChildren with indexAsChild option', async () => { - const breadcrumb = removeChildren(findPageChildren(navigation, '/guide', { indexAsChild: true })) + const pages = removeChildren(findPageChildren(navigation, '/guide', { indexAsChild: true })) - expect(breadcrumb).toEqual([ + expect(pages).toEqual([ { title: 'Guide Index', path: '/guide', @@ -155,9 +197,9 @@ describe('utils', () => { }) it('findPageSiblings', async () => { - const breadcrumb = removeChildren(findPageSiblings(navigation, '/guide/getting-started')) + const pages = removeChildren(findPageSiblings(navigation, '/guide/getting-started')) - expect(breadcrumb).toEqual([ + expect(pages).toEqual([ { title: 'Introduction', path: '/guide/introduction', @@ -167,9 +209,9 @@ describe('utils', () => { }) it('findPageSiblings with indexAsChild option', async () => { - const breadcrumb = removeChildren(findPageSiblings(navigation, '/guide/getting-started', { indexAsChild: true })) + const pages = removeChildren(findPageSiblings(navigation, '/guide/getting-started', { indexAsChild: true })) - expect(breadcrumb).toEqual([ + expect(pages).toEqual([ { title: 'Guide Index', path: '/guide', @@ -182,4 +224,30 @@ describe('utils', () => { }, ]) }) + + it('findPageHeadline', async () => { + const headline = findPageHeadline(navigation2, '/guide/getting-started') + + expect(headline).toEqual('Guide Dir') + }) + + it('findPageHeadline for index with indexAsChild', async () => { + const headline = findPageHeadline(navigation2, '/guide', { indexAsChild: true }) + + expect(headline).toEqual('Guide Dir') + + const headline2 = findPageHeadline(navigation2, '/guide/getting-started', { indexAsChild: true }) + + expect(headline2).toEqual('Getting Started Dir') + }) + + it('findPageHeadline for index without indexAsChild', async () => { + const headline = findPageHeadline(navigation2, '/guide') + + expect(headline).toEqual(undefined) + + const headline2 = findPageHeadline(navigation2, '/guide/getting-started') + + expect(headline2).toEqual('Guide Dir') + }) })