QuartzにはデフォルトでExplorerというノートの一覧を左サイドに表示する機能がある
この一覧を更新順にソートしたい
結論
contentIndex.tsx内のdateを削除している行をコメントアウトする
- delete content.date
+ // delete content.datequartz.layout.tsにソート関数を実装してExplorerに与える
import { Options } from "./quartz/components/Explorer"
...
const sortFn: Options["sortFn"] = (a, b) => {
if (a.data?.date && b.data?.date) {
const aDate = new Date(a.data?.date)
const bDate = new Date(b.data?.date)
const order = bDate.getTime() - aDate.getTime()
if (order != 0) return order
}
return a.displayName.localeCompare(b.displayName)
}
...
export const defaultContentPageLayout: PageLayout = {
...
left: [
...
Component.Explorer({ sortFn }),
],
...
}紆余曲折
軽く調べると、quartz.layout.tsからソート関数を差し込めることがわかる
export const defaultContentPageLayout: PageLayout = {
...
left: [
...
Component.Explorer({ sortFn }),
],
}ソート関数は以下のような形をしている
const sortFn: Options["sortFn"] = (a, b) => {
return 1 // or -1
}aとbはFileTrieNode<ContentDetails>型のオブジェクトである
ContentDetailsの定義を見てみると
export type ContentDetails = {
slug: FullSlug
filePath: FilePath
title: string
links: SimpleSlug[]
tags: string[]
content: string
richContent?: string
date?: Date
description?: string
}dateあるじゃん!
じゃあということでソート関数を実装する
const sortFn: Options["sortFn"]: (a, b) => {
const aDate = a.data?.date
const bDate = b.data?.date
if (aDate && bDate) {
const order = bDate.getTime() - aDate.getTime()
if (order != 0) return order
}
return a.displayName.localeCompare(b.displayName)
}これでビルドしてみるとdateはundefinedですよって言われる
なのでdateが格納されるところを見に行く
実は、ExplorerはcontentIndex.jsonを非同期に受け取って表示している
そのjsonが作られているところを見に行くと
const simplifiedIndex = Object.fromEntries(
Array.from(linkIndex).map(([slug, content]) => {
// remove description and from content index as nothing downstream
// actually uses it. we only keep it in the index as we need it
// for the RSS feed
delete content.description
delete content.date
return [slug, content]
}),
)
yield write({
ctx,
content: JSON.stringify(simplifiedIndex),
slug: fp,
ext: ".json",
})なんとdateが消されている!
これをコメントアウトする
今度こそ上手くいっただろうとビルドすると
dateにgetTimeメソッドなんてないですよって言われる
実は、jsonをパースする都合上ContentDetailsのdateはDate型にキャストされずにstring型のままになっている
ソート関数側でDateオブジェクトを作ってやると上手くいった
余談
このあと、フォルダ機能を使わないのと日付を見せてほしいという理由でRecentNotesをいじって使うことにした
その結果ほとんどExplorerと同じロジックを実装することになった
今思えばExplorerの見た目を変えるほうがまだ修正コストが低かったかもしれない