From d618a4e3f376028902e481b78466e8fbedd860aa Mon Sep 17 00:00:00 2001
From: Jacky Zhao <j.zhao2k19@gmail.com>
Date: Mon, 10 Mar 2025 06:36:10 +0000
Subject: [PATCH] fix(explorer): dont rely on data to get slug, compute it in trie

---
 quartz/util/fileTrie.ts |  101 +++++++++++++++++++++++++-------------------------
 1 files changed, 50 insertions(+), 51 deletions(-)

diff --git a/quartz/util/fileTrie.ts b/quartz/util/fileTrie.ts
index ed87b4f..7195237 100644
--- a/quartz/util/fileTrie.ts
+++ b/quartz/util/fileTrie.ts
@@ -7,55 +7,64 @@
 }
 
 export class FileTrieNode<T extends FileTrieData = ContentDetails> {
-  children: Array<FileTrieNode<T>>
-  slugSegment: string
-  displayName: string
-  data: T | null
-  depth: number
   isFolder: boolean
+  children: Array<FileTrieNode<T>>
 
-  constructor(segment: string, data?: T, depth: number = 0) {
+  private slugSegments: string[]
+  data: T | null
+
+  constructor(segments: string[], data?: T) {
     this.children = []
-    this.slugSegment = segment
-    this.displayName = data?.title ?? segment
+    this.slugSegments = segments
     this.data = data ?? null
-    this.depth = depth
-    this.isFolder = segment === "index"
+    this.isFolder = false
+  }
+
+  get displayName(): string {
+    return this.data?.title ?? this.slugSegment ?? ""
+  }
+
+  get slug(): FullSlug {
+    const path = joinSegments(...this.slugSegments) as FullSlug
+    if (this.isFolder) {
+      return joinSegments(path, "index") as FullSlug
+    }
+
+    return path
+  }
+
+  get slugSegment(): string {
+    return this.slugSegments[this.slugSegments.length - 1]
+  }
+
+  private makeChild(path: string[], file?: T) {
+    const fullPath = [...this.slugSegments, path[0]]
+    const child = new FileTrieNode<T>(fullPath, file)
+    this.children.push(child)
+    return child
   }
 
   private insert(path: string[], file: T) {
-    if (path.length === 0) return
+    if (path.length === 0) {
+      throw new Error("path is empty")
+    }
 
-    const nextSegment = path[0]
-
-    // base case, insert here
+    // if we are inserting, we are a folder
+    this.isFolder = true
+    const segment = path[0]
     if (path.length === 1) {
-      if (nextSegment === "index") {
-        // index case (we are the root and we just found index.md)
+      // base case, we are at the end of the path
+      if (segment === "index") {
         this.data ??= file
-        const title = file.title
-        if (title !== "index") {
-          this.displayName = title
-        }
       } else {
-        // direct child
-        this.children.push(new FileTrieNode(nextSegment, file, this.depth + 1))
-        this.isFolder = true
+        this.makeChild(path, file)
       }
-
-      return
+    } else if (path.length > 1) {
+      // recursive case, we are not at the end of the path
+      const child =
+        this.children.find((c) => c.slugSegment === segment) ?? this.makeChild(path, undefined)
+      child.insert(path.slice(1), file)
     }
-
-    // find the right child to insert into, creating it if it doesn't exist
-    path = path.splice(1)
-    let child = this.children.find((c) => c.slugSegment === nextSegment)
-    if (!child) {
-      child = new FileTrieNode<T>(nextSegment, undefined, this.depth + 1)
-      this.children.push(child)
-      child.isFolder = true
-    }
-
-    child.insert(path, file)
   }
 
   // Add new file to trie
@@ -88,7 +97,7 @@
   }
 
   static fromEntries<T extends FileTrieData>(entries: [FullSlug, T][]) {
-    const trie = new FileTrieNode<T>("")
+    const trie = new FileTrieNode<T>([])
     entries.forEach(([, entry]) => trie.add(entry))
     return trie
   }
@@ -98,22 +107,12 @@
    * in the a flat array including the full path and the node
    */
   entries(): [FullSlug, FileTrieNode<T>][] {
-    const traverse = (
-      node: FileTrieNode<T>,
-      currentPath: string,
-    ): [FullSlug, FileTrieNode<T>][] => {
-      const segments = [currentPath, node.slugSegment]
-      const fullPath = joinSegments(...segments) as FullSlug
-
-      const indexQualifiedPath =
-        node.isFolder && node.depth > 0 ? (joinSegments(fullPath, "index") as FullSlug) : fullPath
-
-      const result: [FullSlug, FileTrieNode<T>][] = [[indexQualifiedPath, node]]
-
-      return result.concat(...node.children.map((child) => traverse(child, fullPath)))
+    const traverse = (node: FileTrieNode<T>): [FullSlug, FileTrieNode<T>][] => {
+      const result: [FullSlug, FileTrieNode<T>][] = [[node.slug, node]]
+      return result.concat(...node.children.map(traverse))
     }
 
-    return traverse(this, "")
+    return traverse(this)
   }
 
   /**

--
Gitblit v1.10.0