@@ -2,8 +2,8 @@ import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } fro
2
2
import path from "path"
3
3
4
4
import 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"
7
7
import { Root } from "hast"
8
8
import { htmlToJsx } from "../../util/jsx"
9
9
import { i18n } from "../../i18n"
@@ -14,11 +14,13 @@ interface FolderContentOptions {
14
14
* Whether to display number of folders
15
15
*/
16
16
showFolderCount : boolean
17
- sort ?: ( f1 : QuartzPluginData , f2 : QuartzPluginData ) => number
17
+ showSubfolders : boolean
18
+ sort ?: SortFn
18
19
}
19
20
20
21
const defaultOptions : FolderContentOptions = {
21
22
showFolderCount : true ,
23
+ showSubfolders : true ,
22
24
}
23
25
24
26
export default ( ( opts ?: Partial < FolderContentOptions > ) => {
@@ -27,14 +29,47 @@ export default ((opts?: Partial<FolderContentOptions>) => {
27
29
const FolderContent : QuartzComponent = ( props : QuartzComponentProps ) => {
28
30
const { tree, fileData, allFiles, cfg } = props
29
31
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 ) => {
31
38
const fileSlug = stripSlashes ( simplifySlug ( file . slug ! ) )
32
39
const prefixed = fileSlug . startsWith ( folderSlug ) && fileSlug !== folderSlug
33
- const folderParts = folderSlug . split ( path . posix . sep )
34
40
const fileParts = fileSlug . split ( path . posix . sep )
35
41
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
+ }
37
56
} )
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
+
38
73
const cssClasses : string [ ] = fileData . frontmatter ?. cssclasses ?? [ ]
39
74
const classes = [ "popover-hint" , ...cssClasses ] . join ( " " )
40
75
const listProps = {
0 commit comments