feat: add subfolders to folder page

This commit is contained in:
Thomas Hack 2024-08-15 15:48:14 +02:00
parent e26448eaf3
commit 405f6f5103
2 changed files with 74 additions and 5 deletions

View File

@ -0,0 +1,38 @@
import path from "path"
import { resolveRelative, SimpleSlug } from "../util/path"
import { QuartzComponent, QuartzComponentProps } from "./types"
type Props = {
limit?: number
} & QuartzComponentProps
export const FolderList: QuartzComponent = ({ cfg, fileData, allFolders, limit }: Props) => {
let list: SimpleSlug[] = allFolders.sort(_alphabetical)
if (limit) {
list = list.slice(0, limit)
}
return (
<ul>
{list.map((folderSlug) => {
const title = _getTitle(folderSlug)
return (
<li>
<a href={resolveRelative(fileData.slug!, folderSlug!)}>{title}</a>
</li>
)
})}
</ul>
)
}
function _alphabetical(f1: SimpleSlug, f2: SimpleSlug): number {
const f1Title = _getTitle(f1)
const f2Title = _getTitle(f2)
return f1Title.localeCompare(f2Title)
}
function _getTitle(folderSlug: SimpleSlug): string {
return folderSlug.split(path.posix.sep).at(-1)!
}

View File

@ -3,21 +3,25 @@ import path from "path"
import style from "../styles/listPage.scss"
import { PageList, SortFn } from "../PageList"
import { stripSlashes, simplifySlug } from "../../util/path"
import { FolderList } from "../FolderList"
import { stripSlashes, simplifySlug, SimpleSlug, joinSegments } from "../../util/path"
import { Root } from "hast"
import { htmlToJsx } from "../../util/jsx"
import { i18n } from "../../i18n"
import { QuartzPluginData } from "../../plugins/vfile"
interface FolderContentOptions {
/**
* Whether to display number of folders
*/
showFolderCount: boolean
showSubfolders: boolean
sort?: SortFn
}
const defaultOptions: FolderContentOptions = {
showFolderCount: true,
showSubfolders: true,
}
export default ((opts?: Partial<FolderContentOptions>) => {
@ -26,21 +30,40 @@ export default ((opts?: Partial<FolderContentOptions>) => {
const FolderContent: QuartzComponent = (props: QuartzComponentProps) => {
const { tree, fileData, allFiles, cfg } = props
const folderSlug = stripSlashes(simplifySlug(fileData.slug!))
const allPagesInFolder = allFiles.filter((file) => {
const allPagesInFolder: QuartzPluginData[] = []
const allSubfolders: Set<SimpleSlug> = new Set()
allFiles.forEach((file) => {
const fileSlug = stripSlashes(simplifySlug(file.slug!))
const prefixed = fileSlug.startsWith(folderSlug) && fileSlug !== folderSlug
const folderParts = folderSlug.split(path.posix.sep)
const fileParts = fileSlug.split(path.posix.sep)
const isDirectChild = fileParts.length === folderParts.length + 1
return prefixed && isDirectChild
if (!prefixed) {
return
}
if (isDirectChild) {
allPagesInFolder.push(file)
} else {
const folderSlug = joinSegments(...fileParts.slice(0, folderParts.length + 1))
allSubfolders.add(folderSlug as SimpleSlug)
}
})
const cssClasses: string[] = fileData.frontmatter?.cssclasses ?? []
const classes = ["popover-hint", ...cssClasses].join(" ")
const listProps = {
const pageListProps = {
...props,
sort: options.sort,
allFiles: allPagesInFolder,
}
const folderListProps = {
...props,
allFolders: Array.from(allSubfolders.values()),
}
const content =
(tree as Root).children.length === 0
@ -59,7 +82,15 @@ export default ((opts?: Partial<FolderContentOptions>) => {
</p>
)}
<div>
<PageList {...listProps} />
<PageList {...pageListProps} />
</div>
</div>
<div class="page-listing">
{options.showSubfolders && (
<p>{allSubfolders.size === 1 ? "1 subfolder." : `${allSubfolders.size} subfolders.`}</p>
)}
<div>
<FolderList {...folderListProps} />
</div>
</div>
</div>