Skip to content

Commit 8ae885d

Browse files
larbishfarnabaz
andcommitted
fix(collection): path route matching
Co-authored-by: Farnabaz <farnabaz@gmail.com>
1 parent a2e5c9f commit 8ae885d

File tree

4 files changed

+62
-30
lines changed

4 files changed

+62
-30
lines changed

src/runtime/internal/studio/collection.ts

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,60 @@
11
import { minimatch } from 'minimatch'
2-
import type { CollectionInfo } from '@nuxt/content'
3-
// import { joinURL, withoutLeadingSlash } from 'ufo'
2+
import type { CollectionInfo, ResolvedCollectionSource } from '@nuxt/content'
3+
import { joinURL } from 'ufo'
44
import type { JsonSchema7ObjectType } from 'zod-to-json-schema'
55
import { getOrderedSchemaKeys } from '../schema'
6-
// import { parseSourceBase } from './utils'
6+
import { parseSourceBase } from './utils'
77
import { withoutRoot } from './files'
88

9-
export const getCollectionByPath = (path: string, collections: Record<string, CollectionInfo>): CollectionInfo => {
10-
return Object.values(collections).find((collection) => {
9+
export const getCollectionByFilePath = (path: string, collections: Record<string, CollectionInfo>): { collection: CollectionInfo, matchedSource: ResolvedCollectionSource } => {
10+
let matchedSource: ResolvedCollectionSource
11+
const collection = Object.values(collections).find((collection) => {
1112
if (!collection.source || collection.source.length === 0) {
1213
return
1314
}
1415

1516
const pathWithoutRoot = withoutRoot(path)
17+
const paths = pathWithoutRoot === '/' ? ['index.yml', 'index.yaml', 'index.md', 'index.json'] : [pathWithoutRoot]
18+
return paths.some((p) => {
19+
matchedSource = collection.source.find(source => minimatch(p, source.include))
20+
return matchedSource
21+
})
22+
})
1623

17-
// TODO HANDLE PREFIX
18-
// const prefix = withoutLeadingSlash(collection.source.prefix)
24+
return {
25+
collection,
26+
matchedSource,
27+
}
28+
}
1929

20-
// if (!pathWithoutRoot.startsWith(prefix)) {
21-
// return false
22-
// }
30+
export const getCollectionByRoutePath = (routePath: string, collections: Record<string, CollectionInfo>): { collection: CollectionInfo, matchedSource: ResolvedCollectionSource } => {
31+
let matchedSource: ResolvedCollectionSource
32+
const collection = Object.values(collections).find((collection) => {
33+
if (!collection.source || collection.source.length === 0) {
34+
return
35+
}
2336

24-
// const { fixed } = parseSourceBase(collection.source)
37+
matchedSource = collection.source.find((source) => {
38+
if (!routePath.startsWith(source.prefix)) {
39+
return
40+
}
2541

26-
// path = joinURL(fixed, pathWithoutRoot.substring(withoutLeadingSlash(collection.source.prefix).length))
42+
const pathWithoutPrefix = routePath.substring(source.prefix.length)
2743

28-
const paths = pathWithoutRoot === '/' ? ['index.yml', 'index.yaml', 'index.md', 'index.json'] : [pathWithoutRoot]
29-
return paths.some((p) => {
30-
return collection.source.some(source => minimatch(p, source.include))
44+
const { fixed } = parseSourceBase(source)
45+
46+
const path = joinURL(fixed, pathWithoutPrefix)
47+
48+
return minimatch(path, source.include)
3149
})
50+
51+
return matchedSource
3252
})
53+
54+
return {
55+
collection,
56+
matchedSource,
57+
}
3358
}
3459

3560
export function generateCollectionInsert(collection: CollectionInfo, data: Record<string, unknown>) {

src/runtime/internal/studio/compatibility.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
1-
import type { CollectionInfo, DraftSyncFile } from '@nuxt/content'
1+
import type { CollectionInfo, DraftSyncFile, ResolvedCollectionSource } from '@nuxt/content'
22
import type { JsonSchema7ObjectType } from 'zod-to-json-schema'
3+
import { join } from 'pathe'
4+
import { parseSourceBase } from './utils'
35

4-
export const v2ToV3ParsedFile = (file: DraftSyncFile, collection: CollectionInfo) => {
6+
export const v2ToV3ParsedFile = (file: DraftSyncFile, collection: CollectionInfo, source: ResolvedCollectionSource) => {
7+
const { fixed } = parseSourceBase(source)
8+
const path = file.parsed._path.substring(fixed.length)
9+
const pathInCollection = join(source?.prefix || '', path)
10+
11+
// TODO - Handle data collections (remove path...)
512
const mappedFile: Record<string, unknown> = {
613
id: file.parsed._id,
714
stem: file.parsed._stem,
815
meta: {},
916
extension: file.parsed._extension,
10-
path: file.parsed._path,
17+
path: pathInCollection,
1118
}
1219

1320
const properties = (collection.schema.definitions[collection.name] as JsonSchema7ObjectType).properties

src/runtime/internal/studio/index.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { withLeadingSlash } from 'ufo'
55
import StudioPreviewMode from '../../components/StudioPreviewMode.vue'
66
import { loadDatabaseAdapter } from '../database.client'
77
import { v2ToV3ParsedFile } from './compatibility'
8-
import { getCollectionByPath, generateCollectionInsert, generateRecordDeletion, generateRecordSelectByColumn, generateRecordUpdate } from './collection'
8+
import { getCollectionByFilePath, generateCollectionInsert, generateRecordDeletion, generateRecordSelectByColumn, generateRecordUpdate, getCollectionByRoutePath } from './collection'
99
import { createSingleton, deepAssign, deepDelete, defu, generateStemFromPath, mergeDraft, StudioConfigFiles, withoutRoot } from './utils'
1010
import { callWithNuxt, refreshNuxtData } from '#app'
1111
import { useAppConfig, useNuxtApp, useRuntimeConfig, useRoute, useRouter, ref } from '#imports'
@@ -43,15 +43,15 @@ const initializePreview = async (data: DraftSyncData) => {
4343

4444
const syncDraftFile = async (collections: Record<string, CollectionInfo>, file: DraftSyncFile) => {
4545
// Fetch corresponding collection
46-
const collection = getCollectionByPath(file.path, collections)
46+
const { collection, matchedSource } = getCollectionByFilePath(file.path, collections)
4747
if (!collection) {
4848
console.warn(`Studio Preview: collection not found for file: ${file.path}, skipping insertion.`)
4949
return
5050
}
5151

5252
const db = loadDatabaseAdapter(collection.name)
5353

54-
const v3File = v2ToV3ParsedFile(file, collection)
54+
const v3File = v2ToV3ParsedFile(file, collection, matchedSource)
5555

5656
const query = generateCollectionInsert(collection, v3File)
5757

@@ -167,7 +167,7 @@ export function initIframeCommunication() {
167167
return
168168
}
169169

170-
const collection = getCollectionByPath(withoutRoot(path), collections)
170+
const { collection } = getCollectionByFilePath(withoutRoot(path), collections)
171171
if (!collection) {
172172
console.warn(`Studio Preview: collection not found for file: ${path}, skipping navigation.`)
173173
return
@@ -205,15 +205,15 @@ export function initIframeCommunication() {
205205
}
206206

207207
async function handleFileUpdate(file: PreviewFile, navigate: boolean) {
208-
const collection = getCollectionByPath(file.path, collections)
208+
const { collection, matchedSource } = getCollectionByFilePath(file.path, collections)
209209
if (!collection) {
210210
console.warn(`Studio Preview: collection not found for file: ${file.path}, skipping update.`)
211211
return
212212
}
213213

214214
const stem = generateStemFromPath(file.path)
215215

216-
const v3File = v2ToV3ParsedFile({ path: file.path, parsed: file.parsed }, collection)
216+
const v3File = v2ToV3ParsedFile({ path: file.path, parsed: file.parsed }, collection, matchedSource)
217217

218218
const query = generateRecordUpdate(collection, stem, v3File)
219219

@@ -240,7 +240,7 @@ export function initIframeCommunication() {
240240
}
241241

242242
async function handleFileDeletion(path: string) {
243-
const collection = getCollectionByPath(withoutRoot(path), collections)
243+
const { collection } = getCollectionByFilePath(withoutRoot(path), collections)
244244
if (!collection) {
245245
console.warn(`Studio Preview: collection not found for file: ${path}, skipping deletion.`)
246246
return
@@ -261,23 +261,23 @@ export function initIframeCommunication() {
261261
return
262262
}
263263

264-
const currentPath = route.path
264+
const routePath = route.path
265265

266-
const collection = getCollectionByPath(currentPath, collections)
266+
const { collection } = getCollectionByRoutePath(routePath, collections)
267267
if (!collection || collection.type !== 'page') {
268268
return
269269
}
270270

271271
const db = loadDatabaseAdapter(collection.name)
272272

273-
const query = generateRecordSelectByColumn(collection, 'path', currentPath)
273+
const query = generateRecordSelectByColumn(collection, 'path', routePath)
274274

275275
const file = await db.first(query) as { path: string }
276276
if (!file || !file.path) {
277277
return
278278
}
279279

280-
window.openFileInStudio(currentPath)
280+
window.openFileInStudio(routePath)
281281
}
282282

283283
nuxtApp.hook('page:finish', () => {

src/types/collection.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export interface CollectionInfo {
6363
name: string
6464
pascalName: string
6565
tableName: string
66-
source: CollectionSource[]
66+
source: ResolvedCollectionSource[]
6767
type: CollectionType
6868
schema: JsonSchema7Type & {
6969
$schema?: string

0 commit comments

Comments
 (0)