fix(explorer): show file name instead of slug if no file data (closes #1822)

This commit is contained in:
Jacky Zhao 2025-03-12 11:24:28 -07:00
parent bfa938cc62
commit 270a5dc14a
4 changed files with 55 additions and 17 deletions

View file

@ -49,8 +49,15 @@ export const defaultListPageLayout: PageLayout = {
left: [ left: [
Component.PageTitle(), Component.PageTitle(),
Component.MobileOnly(Component.Spacer()), Component.MobileOnly(Component.Spacer()),
Component.Search(), Component.Flex({
Component.Darkmode(), components: [
{
Component: Component.Search(),
grow: true,
},
{ Component: Component.Darkmode() },
],
}),
Component.Explorer(), Component.Explorer(),
], ],
right: [], right: [],

View file

@ -12,6 +12,7 @@ import DepGraph from "../../depgraph"
export type ContentIndexMap = Map<FullSlug, ContentDetails> export type ContentIndexMap = Map<FullSlug, ContentDetails>
export type ContentDetails = { export type ContentDetails = {
slug: FullSlug slug: FullSlug
filePath: FilePath
title: string title: string
links: SimpleSlug[] links: SimpleSlug[]
tags: string[] tags: string[]
@ -126,6 +127,7 @@ export const ContentIndex: QuartzEmitterPlugin<Partial<Options>> = (opts) => {
if (opts?.includeEmptyFiles || (file.data.text && file.data.text !== "")) { if (opts?.includeEmptyFiles || (file.data.text && file.data.text !== "")) {
linkIndex.set(slug, { linkIndex.set(slug, {
slug, slug,
filePath: file.data.filePath!,
title: file.data.frontmatter?.title!, title: file.data.frontmatter?.title!,
links: file.data.links ?? [], links: file.data.links ?? [],
tags: file.data.frontmatter?.tags ?? [], tags: file.data.frontmatter?.tags ?? [],

View file

@ -5,6 +5,7 @@ import { FileTrieNode } from "./fileTrie"
interface TestData { interface TestData {
title: string title: string
slug: string slug: string
filePath: string
} }
describe("FileTrie", () => { describe("FileTrie", () => {
@ -26,6 +27,7 @@ describe("FileTrie", () => {
const data = { const data = {
title: "Test Title", title: "Test Title",
slug: "test", slug: "test",
filePath: "test.md",
} }
trie.add(data) trie.add(data)
@ -36,6 +38,7 @@ describe("FileTrie", () => {
const data = { const data = {
title: "Test Title", title: "Test Title",
slug: "test", slug: "test",
filePath: "test.md",
} }
trie.add(data) trie.add(data)
@ -49,6 +52,7 @@ describe("FileTrie", () => {
const data = { const data = {
title: "Test", title: "Test",
slug: "test", slug: "test",
filePath: "test.md",
} }
trie.add(data) trie.add(data)
@ -61,6 +65,7 @@ describe("FileTrie", () => {
const data = { const data = {
title: "Index", title: "Index",
slug: "index", slug: "index",
filePath: "index.md",
} }
trie.add(data) trie.add(data)
@ -72,11 +77,13 @@ describe("FileTrie", () => {
const data1 = { const data1 = {
title: "Nested", title: "Nested",
slug: "folder/test", slug: "folder/test",
filePath: "folder/test.md",
} }
const data2 = { const data2 = {
title: "Really nested index", title: "Really nested index",
slug: "a/b/c/index", slug: "a/b/c/index",
filePath: "a/b/c/index.md",
} }
trie.add(data1) trie.add(data1)
@ -103,8 +110,8 @@ describe("FileTrie", () => {
describe("filter", () => { describe("filter", () => {
test("should filter nodes based on condition", () => { test("should filter nodes based on condition", () => {
const data1 = { title: "Test1", slug: "test1" } const data1 = { title: "Test1", slug: "test1", filePath: "test1.md" }
const data2 = { title: "Test2", slug: "test2" } const data2 = { title: "Test2", slug: "test2", filePath: "test2.md" }
trie.add(data1) trie.add(data1)
trie.add(data2) trie.add(data2)
@ -117,8 +124,8 @@ describe("FileTrie", () => {
describe("map", () => { describe("map", () => {
test("should apply function to all nodes", () => { test("should apply function to all nodes", () => {
const data1 = { title: "Test1", slug: "test1" } const data1 = { title: "Test1", slug: "test1", filePath: "test1.md" }
const data2 = { title: "Test2", slug: "test2" } const data2 = { title: "Test2", slug: "test2", filePath: "test2.md" }
trie.add(data1) trie.add(data1)
trie.add(data2) trie.add(data2)
@ -134,8 +141,12 @@ describe("FileTrie", () => {
}) })
test("map over folders should work", () => { test("map over folders should work", () => {
const data1 = { title: "Test1", slug: "test1" } const data1 = { title: "Test1", slug: "test1", filePath: "test1.md" }
const data2 = { title: "Test2", slug: "a/b/test2" } const data2 = {
title: "Test2",
slug: "a/b-with-space/test2",
filePath: "a/b with space/test2.md",
}
trie.add(data1) trie.add(data1)
trie.add(data2) trie.add(data2)
@ -150,15 +161,19 @@ describe("FileTrie", () => {
assert.strictEqual(trie.children[0].displayName, "File: Test1") assert.strictEqual(trie.children[0].displayName, "File: Test1")
assert.strictEqual(trie.children[1].displayName, "Folder: a") assert.strictEqual(trie.children[1].displayName, "Folder: a")
assert.strictEqual(trie.children[1].children[0].displayName, "Folder: b") assert.strictEqual(trie.children[1].children[0].displayName, "Folder: b with space")
assert.strictEqual(trie.children[1].children[0].children[0].displayName, "File: Test2") assert.strictEqual(trie.children[1].children[0].children[0].displayName, "File: Test2")
}) })
}) })
describe("entries", () => { describe("entries", () => {
test("should return all entries", () => { test("should return all entries", () => {
const data1 = { title: "Test1", slug: "test1" } const data1 = { title: "Test1", slug: "test1", filePath: "test1.md" }
const data2 = { title: "Test2", slug: "a/b/test2" } const data2 = {
title: "Test2",
slug: "a/b-with-space/test2",
filePath: "a/b with space/test2.md",
}
trie.add(data1) trie.add(data1)
trie.add(data2) trie.add(data2)
@ -170,8 +185,8 @@ describe("FileTrie", () => {
["index", trie.data], ["index", trie.data],
["test1", data1], ["test1", data1],
["a/index", null], ["a/index", null],
["a/b/index", null], ["a/b-with-space/index", null],
["a/b/test2", data2], ["a/b-with-space/test2", data2],
], ],
) )
}) })
@ -182,14 +197,17 @@ describe("FileTrie", () => {
const data1 = { const data1 = {
title: "Root", title: "Root",
slug: "index", slug: "index",
filePath: "index.md",
} }
const data2 = { const data2 = {
title: "Test", title: "Test",
slug: "folder/subfolder/test", slug: "folder/subfolder/test",
filePath: "folder/subfolder/test.md",
} }
const data3 = { const data3 = {
title: "Folder Index", title: "Folder Index",
slug: "abc/index", slug: "abc/index",
filePath: "abc/index.md",
} }
trie.add(data1) trie.add(data1)
@ -208,9 +226,9 @@ describe("FileTrie", () => {
describe("sort", () => { describe("sort", () => {
test("should sort nodes according to sort function", () => { test("should sort nodes according to sort function", () => {
const data1 = { title: "A", slug: "a" } const data1 = { title: "A", slug: "a", filePath: "a.md" }
const data2 = { title: "B", slug: "b" } const data2 = { title: "B", slug: "b", filePath: "b.md" }
const data3 = { title: "C", slug: "c" } const data3 = { title: "C", slug: "c", filePath: "c.md" }
trie.add(data3) trie.add(data3)
trie.add(data1) trie.add(data1)

View file

@ -4,6 +4,7 @@ import { FullSlug, joinSegments } from "./path"
interface FileTrieData { interface FileTrieData {
slug: string slug: string
title: string title: string
filePath: string
} }
export class FileTrieNode<T extends FileTrieData = ContentDetails> { export class FileTrieNode<T extends FileTrieData = ContentDetails> {
@ -11,6 +12,10 @@ export class FileTrieNode<T extends FileTrieData = ContentDetails> {
children: Array<FileTrieNode<T>> children: Array<FileTrieNode<T>>
private slugSegments: string[] private slugSegments: string[]
// prefer showing the file path segment over the slug segment
// so that folders that dont have index files can be shown as is
// without dashes in the slug
private fileSegmentHint?: string
private displayNameOverride?: string private displayNameOverride?: string
data: T | null data: T | null
@ -23,7 +28,10 @@ export class FileTrieNode<T extends FileTrieData = ContentDetails> {
} }
get displayName(): string { get displayName(): string {
return this.displayNameOverride ?? this.data?.title ?? this.slugSegment ?? "" const nonIndexTitle = this.data?.title === "index" ? undefined : this.data?.title
return (
this.displayNameOverride ?? nonIndexTitle ?? this.fileSegmentHint ?? this.slugSegment ?? ""
)
} }
set displayName(name: string) { set displayName(name: string) {
@ -69,6 +77,9 @@ export class FileTrieNode<T extends FileTrieData = ContentDetails> {
// recursive case, we are not at the end of the path // recursive case, we are not at the end of the path
const child = const child =
this.children.find((c) => c.slugSegment === segment) ?? this.makeChild(path, undefined) this.children.find((c) => c.slugSegment === segment) ?? this.makeChild(path, undefined)
const fileParts = file.filePath.split("/")
child.fileSegmentHint = fileParts.at(-path.length)
child.insert(path.slice(1), file) child.insert(path.slice(1), file)
} }
} }