@@ -2,8 +2,8 @@ import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } fro
22import path from "path"
33
44import style from "../styles/listPage.scss"
5- import { PageList } from "../PageList"
6- import { stripSlashes , simplifySlug } from "../../util/path"
5+ import { byDateAndAlphabetical , PageList , SortFn } from "../PageList"
6+ import { stripSlashes , simplifySlug , joinSegments , FullSlug } from "../../util/path"
77import { Root } from "hast"
88import { htmlToJsx } from "../../util/jsx"
99import { i18n } from "../../i18n"
@@ -14,11 +14,13 @@ interface FolderContentOptions {
1414 * Whether to display number of folders
1515 */
1616 showFolderCount : boolean
17- sort ?: ( f1 : QuartzPluginData , f2 : QuartzPluginData ) => number
17+ showSubfolders : boolean
18+ sort ?: SortFn
1819}
1920
2021const defaultOptions : FolderContentOptions = {
2122 showFolderCount : true ,
23+ showSubfolders : true ,
2224}
2325
2426export default ( ( opts ?: Partial < FolderContentOptions > ) => {
@@ -27,14 +29,47 @@ export default ((opts?: Partial<FolderContentOptions>) => {
2729 const FolderContent : QuartzComponent = ( props : QuartzComponentProps ) => {
2830 const { tree, fileData, allFiles, cfg } = props
2931 const folderSlug = stripSlashes ( simplifySlug ( fileData . slug ! ) )
30- const allPagesInFolder = allFiles . filter ( ( file ) => {
32+ const folderParts = folderSlug . split ( path . posix . sep )
33+
34+ const allPagesInFolder : QuartzPluginData [ ] = [ ]
35+ const allPagesInSubfolders : Map < FullSlug , QuartzPluginData [ ] > = new Map ( )
36+
37+ allFiles . forEach ( ( file ) => {
3138 const fileSlug = stripSlashes ( simplifySlug ( file . slug ! ) )
3239 const prefixed = fileSlug . startsWith ( folderSlug ) && fileSlug !== folderSlug
33- const folderParts = folderSlug . split ( path . posix . sep )
3440 const fileParts = fileSlug . split ( path . posix . sep )
3541 const isDirectChild = fileParts . length === folderParts . length + 1
36- return prefixed && isDirectChild
42+
43+ if ( ! prefixed ) {
44+ return
45+ }
46+
47+ if ( isDirectChild ) {
48+ allPagesInFolder . push ( file )
49+ } else if ( options . showSubfolders ) {
50+ const subfolderSlug = joinSegments (
51+ ...fileParts . slice ( 0 , folderParts . length + 1 ) ,
52+ ) as FullSlug
53+ const pagesInFolder = allPagesInSubfolders . get ( subfolderSlug ) || [ ]
54+ allPagesInSubfolders . set ( subfolderSlug , [ ...pagesInFolder , file ] )
55+ }
3756 } )
57+
58+ allPagesInSubfolders . forEach ( ( files , subfolderSlug ) => {
59+ const hasIndex = allPagesInFolder . some (
60+ ( file ) => subfolderSlug === stripSlashes ( simplifySlug ( file . slug ! ) ) ,
61+ )
62+ if ( ! hasIndex ) {
63+ const subfolderDates = files . sort ( byDateAndAlphabetical ( cfg ) ) [ 0 ] . dates
64+ const subfolderTitle = subfolderSlug . split ( path . posix . sep ) . at ( - 1 ) !
65+ allPagesInFolder . push ( {
66+ slug : subfolderSlug ,
67+ dates : subfolderDates ,
68+ frontmatter : { title : subfolderTitle , tags : [ "folder" ] } ,
69+ } )
70+ }
71+ } )
72+
3873 const cssClasses : string [ ] = fileData . frontmatter ?. cssclasses ?? [ ]
3974 const classes = [ "popover-hint" , ...cssClasses ] . join ( " " )
4075 const listProps = {
0 commit comments