From 270a5dc14ac3654c3aac94dfca222bab0d091474 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Wed, 12 Mar 2025 11:24:28 -0700 Subject: [PATCH] fix(explorer): show file name instead of slug if no file data (closes #1822) --- quartz.layout.ts | 11 ++++-- quartz/plugins/emitters/contentIndex.tsx | 2 ++ quartz/util/fileTrie.test.ts | 46 ++++++++++++++++-------- quartz/util/fileTrie.ts | 13 ++++++- 4 files changed, 55 insertions(+), 17 deletions(-) diff --git a/quartz.layout.ts b/quartz.layout.ts index 3a39d0b..1c601a2 100644 --- a/quartz.layout.ts +++ b/quartz.layout.ts @@ -49,8 +49,15 @@ export const defaultListPageLayout: PageLayout = { left: [ Component.PageTitle(), Component.MobileOnly(Component.Spacer()), - Component.Search(), - Component.Darkmode(), + Component.Flex({ + components: [ + { + Component: Component.Search(), + grow: true, + }, + { Component: Component.Darkmode() }, + ], + }), Component.Explorer(), ], right: [], diff --git a/quartz/plugins/emitters/contentIndex.tsx b/quartz/plugins/emitters/contentIndex.tsx index 0cc70d8..be460e5 100644 --- a/quartz/plugins/emitters/contentIndex.tsx +++ b/quartz/plugins/emitters/contentIndex.tsx @@ -12,6 +12,7 @@ import DepGraph from "../../depgraph" export type ContentIndexMap = Map export type ContentDetails = { slug: FullSlug + filePath: FilePath title: string links: SimpleSlug[] tags: string[] @@ -126,6 +127,7 @@ export const ContentIndex: QuartzEmitterPlugin> = (opts) => { if (opts?.includeEmptyFiles || (file.data.text && file.data.text !== "")) { linkIndex.set(slug, { slug, + filePath: file.data.filePath!, title: file.data.frontmatter?.title!, links: file.data.links ?? [], tags: file.data.frontmatter?.tags ?? [], diff --git a/quartz/util/fileTrie.test.ts b/quartz/util/fileTrie.test.ts index 456cf23..a4481ed 100644 --- a/quartz/util/fileTrie.test.ts +++ b/quartz/util/fileTrie.test.ts @@ -5,6 +5,7 @@ import { FileTrieNode } from "./fileTrie" interface TestData { title: string slug: string + filePath: string } describe("FileTrie", () => { @@ -26,6 +27,7 @@ describe("FileTrie", () => { const data = { title: "Test Title", slug: "test", + filePath: "test.md", } trie.add(data) @@ -36,6 +38,7 @@ describe("FileTrie", () => { const data = { title: "Test Title", slug: "test", + filePath: "test.md", } trie.add(data) @@ -49,6 +52,7 @@ describe("FileTrie", () => { const data = { title: "Test", slug: "test", + filePath: "test.md", } trie.add(data) @@ -61,6 +65,7 @@ describe("FileTrie", () => { const data = { title: "Index", slug: "index", + filePath: "index.md", } trie.add(data) @@ -72,11 +77,13 @@ describe("FileTrie", () => { const data1 = { title: "Nested", slug: "folder/test", + filePath: "folder/test.md", } const data2 = { title: "Really nested index", slug: "a/b/c/index", + filePath: "a/b/c/index.md", } trie.add(data1) @@ -103,8 +110,8 @@ describe("FileTrie", () => { describe("filter", () => { test("should filter nodes based on condition", () => { - const data1 = { title: "Test1", slug: "test1" } - const data2 = { title: "Test2", slug: "test2" } + const data1 = { title: "Test1", slug: "test1", filePath: "test1.md" } + const data2 = { title: "Test2", slug: "test2", filePath: "test2.md" } trie.add(data1) trie.add(data2) @@ -117,8 +124,8 @@ describe("FileTrie", () => { describe("map", () => { test("should apply function to all nodes", () => { - const data1 = { title: "Test1", slug: "test1" } - const data2 = { title: "Test2", slug: "test2" } + const data1 = { title: "Test1", slug: "test1", filePath: "test1.md" } + const data2 = { title: "Test2", slug: "test2", filePath: "test2.md" } trie.add(data1) trie.add(data2) @@ -134,8 +141,12 @@ describe("FileTrie", () => { }) test("map over folders should work", () => { - const data1 = { title: "Test1", slug: "test1" } - const data2 = { title: "Test2", slug: "a/b/test2" } + const data1 = { title: "Test1", slug: "test1", filePath: "test1.md" } + const data2 = { + title: "Test2", + slug: "a/b-with-space/test2", + filePath: "a/b with space/test2.md", + } trie.add(data1) trie.add(data2) @@ -150,15 +161,19 @@ describe("FileTrie", () => { assert.strictEqual(trie.children[0].displayName, "File: Test1") 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") }) }) describe("entries", () => { test("should return all entries", () => { - const data1 = { title: "Test1", slug: "test1" } - const data2 = { title: "Test2", slug: "a/b/test2" } + const data1 = { title: "Test1", slug: "test1", filePath: "test1.md" } + const data2 = { + title: "Test2", + slug: "a/b-with-space/test2", + filePath: "a/b with space/test2.md", + } trie.add(data1) trie.add(data2) @@ -170,8 +185,8 @@ describe("FileTrie", () => { ["index", trie.data], ["test1", data1], ["a/index", null], - ["a/b/index", null], - ["a/b/test2", data2], + ["a/b-with-space/index", null], + ["a/b-with-space/test2", data2], ], ) }) @@ -182,14 +197,17 @@ describe("FileTrie", () => { const data1 = { title: "Root", slug: "index", + filePath: "index.md", } const data2 = { title: "Test", slug: "folder/subfolder/test", + filePath: "folder/subfolder/test.md", } const data3 = { title: "Folder Index", slug: "abc/index", + filePath: "abc/index.md", } trie.add(data1) @@ -208,9 +226,9 @@ describe("FileTrie", () => { describe("sort", () => { test("should sort nodes according to sort function", () => { - const data1 = { title: "A", slug: "a" } - const data2 = { title: "B", slug: "b" } - const data3 = { title: "C", slug: "c" } + const data1 = { title: "A", slug: "a", filePath: "a.md" } + const data2 = { title: "B", slug: "b", filePath: "b.md" } + const data3 = { title: "C", slug: "c", filePath: "c.md" } trie.add(data3) trie.add(data1) diff --git a/quartz/util/fileTrie.ts b/quartz/util/fileTrie.ts index 8f4bfcb..b39833c 100644 --- a/quartz/util/fileTrie.ts +++ b/quartz/util/fileTrie.ts @@ -4,6 +4,7 @@ import { FullSlug, joinSegments } from "./path" interface FileTrieData { slug: string title: string + filePath: string } export class FileTrieNode { @@ -11,6 +12,10 @@ export class FileTrieNode { children: Array> 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 data: T | null @@ -23,7 +28,10 @@ export class FileTrieNode { } 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) { @@ -69,6 +77,9 @@ export class FileTrieNode { // recursive case, we are not at the end of the path const child = 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) } }