@@ -68,27 +68,37 @@ const fillTemplateIfNeeded = (pathString, fillSlugOptions) =>
6868 pathString . includes ( '{{' ) ? fillTemplate ( pathString , fillSlugOptions ) : pathString ;
6969
7070/**
71- * Extract the entry folder path from an entry file path. Removes file extension and `/index` suffix
72- * for nested entries.
71+ * Extract the entry folder path from an entry file path. Removes file extension and the filename
72+ * suffix for nested entries (e.g., `/index`, `/_index`, or any custom filename from the `path`
73+ * config).
7374 * @param {string } entryFilePath Entry file path, e.g., `src/content/blog/hello-world.md`.
75+ * @param {string | undefined } subPath Collection's file subPath template, e.g., `{{slug}}/index`.
7476 * @returns {string } Entry folder path, e.g., `src/content/blog/hello-world`.
7577 * @example
7678 * // Simple files
77- * getEntryFolderPath('src/content/blog/hello-world.md')
79+ * getEntryFolderPath('src/content/blog/hello-world.md', '{{slug}}' )
7880 * // => 'src/content/blog/hello-world'
7981 * @example
80- * // Nested files
81- * getEntryFolderPath('src/content/blog/hello-world/index.md')
82+ * // Nested files with `index`
83+ * getEntryFolderPath('src/content/blog/hello-world/index.md', '{{slug}}/index' )
8284 * // => 'src/content/blog/hello-world'
85+ * @example
86+ * // Nested files with `_index`
87+ * getEntryFolderPath('content/learn/my-slug/_index.md', '{{slug}}/_index')
88+ * // => 'content/learn/my-slug'
8389 */
84- const getEntryFolderPath = ( entryFilePath ) => {
90+ const getEntryFolderPath = ( entryFilePath , subPath ) => {
8591 // Remove file extension (always present)
8692 const extensionIndex = entryFilePath . lastIndexOf ( '.' ) ;
8793 let folderPath = entryFilePath . substring ( 0 , extensionIndex ) ;
88-
89- // Remove `/index` suffix for nested entries
90- if ( folderPath . endsWith ( '/index' ) ) {
91- folderPath = folderPath . substring ( 0 , folderPath . length - 6 ) ;
94+ // For nested entries where the path config has a fixed filename suffix (e.g., `{{slug}}/index` or
95+ // `{{slug}}/_index`), strip that last segment to get the folder path. Paths like
96+ // `{{year}}/{{month}}/{{slug}}` are not nested in this sense — the slug IS the last segment, so
97+ // nothing is stripped.
98+ const lastSubPathSegment = subPath ?. includes ( '/' ) ? subPath . split ( '/' ) . at ( - 1 ) : undefined ;
99+
100+ if ( lastSubPathSegment && ! lastSubPathSegment . includes ( '{{' ) ) {
101+ folderPath = folderPath . match ( FOLDER_PATH_REGEX ) ?. groups ?. path ?? folderPath ;
92102 }
93103
94104 return folderPath ;
@@ -200,7 +210,7 @@ export const resolveAssetFolderPaths = ({ folder, fillSlugOptions }) => {
200210 : undefined ;
201211
202212 const subPathFolderPath = subPath ?. match ( FOLDER_PATH_REGEX ) ?. groups ?. path ?? '' ;
203- const entryFolderPath = getEntryFolderPath ( entryFilePath ?? '' ) ;
213+ const entryFolderPath = getEntryFolderPath ( entryFilePath ?? '' , subPath ) ;
204214 const isNestedEntry = subPath ?. includes ( '/' ) ?? false ;
205215
206216 const resolvedInternalPath = resolveInternalPath ( {
0 commit comments