Skip to content

Commit b3fa025

Browse files
authored
fix(queryCollectionSearchSections): fix options types (#3705)
1 parent e8beed8 commit b3fa025

File tree

5 files changed

+62
-7
lines changed

5 files changed

+62
-7
lines changed

docs/content/docs/4.utils/4.query-collection-search-sections.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ The `queryCollectionSearchSections` utility is available in both Vue and Nitro.
2323
## Type
2424

2525
```ts
26-
function queryCollectionSearchSections(collection: keyof Collections, opts?: { ignoredTags?: string[], minHeading?: string, maxHeading?: string }): ChainablePromise<T, Section[]>
26+
function queryCollectionSearchSections<T extends keyof PageCollections>(collection: T, opts?: { ignoredTags?: string[], minHeading?: string, maxHeading?: string, extraFields?: Array<keyof PageCollections[T]> }): ChainablePromise<T, Section[]>
2727

2828
interface ChainablePromise<T extends keyof PageCollections, R> extends Promise<R> {
2929
where(field: keyof PageCollections[T] | string, operator: SQLOperator, value?: unknown): ChainablePromise<T, R>
@@ -45,6 +45,7 @@ Generate searchable sections from the specified collection.
4545
- `ignoredTags`: An array of tag names to ignore when generating sections. Default is an empty array.
4646
- `minHeading`: Minimum heading level to split on (e.g., `'h2'`). Default is `'h1'`.
4747
- `maxHeading`: Maximum heading level to split on (e.g., `'h3'`). Default is `'h6'`.
48+
- `extraFields`: An array of additional fields from the collection items to include in the section objects.
4849
- Returns: A Promise that resolves to an array of searchable sections. Each section is an object with the following properties:
4950
- `id`: A unique identifier for the section.
5051
- `title`: The title of the section (usually the heading text).
@@ -63,6 +64,7 @@ const { data: surround } = await useAsyncData('foo-surround', () => {
6364
ignoredTags: ['code'],
6465
minHeading: 'h2',
6566
maxHeading: 'h3',
67+
extraFields: ['author', 'date'],
6668
})
6769
})
6870
</script>

src/runtime/client.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { H3Event } from 'h3'
22
import { collectionQueryBuilder } from './internal/query'
33
import { generateNavigationTree } from './internal/navigation'
44
import { generateItemSurround } from './internal/surround'
5-
import { generateSearchSections } from './internal/search'
5+
import { type GenerateSearchSectionsOptions, generateSearchSections } from './internal/search'
66
import { fetchQuery } from './internal/api'
77
import type { Collections, PageCollections, CollectionQueryBuilder, SurroundOptions, SQLOperator, QueryGroupFunction, ContentNavigationItem } from '@nuxt/content'
88
import { tryUseNuxtApp } from '#imports'
@@ -27,7 +27,7 @@ export function queryCollectionItemSurroundings<T extends keyof PageCollections>
2727
return chainablePromise(collection, qb => generateItemSurround(qb, path, opts))
2828
}
2929

30-
export function queryCollectionSearchSections(collection: keyof Collections, opts?: { ignoredTags?: string[], separators?: string[] }) {
30+
export function queryCollectionSearchSections<T extends keyof PageCollections>(collection: T, opts?: GenerateSearchSectionsOptions) {
3131
return chainablePromise(collection, qb => generateSearchSections(qb, opts))
3232
}
3333

src/runtime/internal/search.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,21 @@ interface SectionablePage {
2727
body: MDCRoot | MinimarkTree
2828
}
2929

30-
export async function generateSearchSections<T extends PageCollectionItemBase>(queryBuilder: CollectionQueryBuilder<T>, opts?: { ignoredTags?: string[], extraFields?: Array<keyof T>, minHeading?: `h${1 | 2 | 3 | 4 | 5 | 6}`, maxHeading?: `h${1 | 2 | 3 | 4 | 5 | 6}` }) {
30+
export type GenerateSearchSectionsOptions = {
31+
ignoredTags?: string[]
32+
extraFields?: (string | symbol | number)[]
33+
minHeading?: `h${1 | 2 | 3 | 4 | 5 | 6}`
34+
maxHeading?: `h${1 | 2 | 3 | 4 | 5 | 6}`
35+
}
36+
37+
export async function generateSearchSections<T extends PageCollectionItemBase>(queryBuilder: CollectionQueryBuilder<T>, opts?: GenerateSearchSectionsOptions) {
3138
const { ignoredTags = [], extraFields = [], minHeading = 'h1', maxHeading = 'h6' } = opts || {}
3239
const minLevel = headingLevel(minHeading)
3340
const maxLevel = headingLevel(maxHeading)
3441

3542
const documents = await queryBuilder
3643
.where('extension', '=', 'md')
37-
.select('path', 'body', 'description', 'title', ...(extraFields || []))
44+
.select('path', 'body', 'description', 'title', ...(extraFields as Array<keyof T> || []))
3845
.all()
3946

4047
return documents.flatMap(doc => splitPageIntoSections(doc, { ignoredTags, extraFields: extraFields as string[], minLevel, maxLevel }))

src/runtime/server.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { H3Event } from 'h3'
22
import { collectionQueryBuilder } from './internal/query'
33
import { generateNavigationTree } from './internal/navigation'
44
import { generateItemSurround } from './internal/surround'
5-
import { generateSearchSections } from './internal/search'
5+
import { type GenerateSearchSectionsOptions, generateSearchSections } from './internal/search'
66
import { fetchQuery } from './internal/api'
77
import type { Collections, CollectionQueryBuilder, PageCollections, SurroundOptions, SQLOperator, QueryGroupFunction } from '@nuxt/content'
88

@@ -25,7 +25,7 @@ export function queryCollectionItemSurroundings<T extends keyof PageCollections>
2525
return chainablePromise(event, collection, qb => generateItemSurround(qb, path, opts))
2626
}
2727

28-
export function queryCollectionSearchSections(event: H3Event, collection: keyof Collections, opts?: { ignoredTags?: string[], separators?: string[] }) {
28+
export function queryCollectionSearchSections<T extends keyof PageCollections>(event: H3Event, collection: T, opts?: GenerateSearchSectionsOptions) {
2929
return chainablePromise(event, collection, qb => generateSearchSections(qb, opts))
3030
}
3131

test/unit/generateSearchSections.test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,52 @@ describe('generateSearchSections', () => {
226226
{ id: '/test#h3', title: 'H3', titles: ['Test Page', 'H2'], content: 'P3 H4 P4', level: 3 },
227227
])
228228
})
229+
230+
it('should add extra fields to results', async () => {
231+
const mockQueryBuilder = createMockQueryBuilder([{
232+
path: '/test',
233+
title: 'Test Page',
234+
description: 'Page description',
235+
author: 'John Doe',
236+
body: {
237+
type: 'root',
238+
children: [
239+
{
240+
type: 'element',
241+
tag: 'h2',
242+
props: { id: 'section-1' },
243+
children: [{ type: 'text', value: 'Section 1' }],
244+
},
245+
{
246+
type: 'element',
247+
tag: 'p',
248+
children: [{ type: 'text', value: 'Section 1 content' }],
249+
},
250+
],
251+
},
252+
}])
253+
254+
const sections = await generateSearchSections(mockQueryBuilder, { extraFields: ['author'] })
255+
256+
expect(sections).toEqual([
257+
{
258+
id: '/test',
259+
title: 'Test Page',
260+
titles: [],
261+
content: 'Page description',
262+
level: 1,
263+
author: 'John Doe',
264+
},
265+
{
266+
id: '/test#section-1',
267+
title: 'Section 1',
268+
titles: ['Test Page'],
269+
content: 'Section 1 content',
270+
level: 2,
271+
author: 'John Doe',
272+
},
273+
])
274+
})
229275
})
230276

231277
function createMockQueryBuilder(result: unknown[]) {

0 commit comments

Comments
 (0)