diff --git a/src/components/FileTree.tsx b/src/components/FileTree.tsx index 4d04a52..4c22660 100644 --- a/src/components/FileTree.tsx +++ b/src/components/FileTree.tsx @@ -20,6 +20,7 @@ export const FileTreeNode: Component<{ pathHeadings: Record; depth: number; onClose: () => void; + isHidden?: (node: FileNode) => boolean; }> = (props) => { const navigate = useNavigate(); const isDir = !!props.node.children; @@ -41,7 +42,7 @@ export const FileTreeNode: Component<{ const indent = props.depth * 12; return ( -
+
))}
@@ -81,6 +83,7 @@ export const HeadingNode: Component<{ node: TocNode; basePath: string; depth: number; + isHidden?: (node: TocNode) => boolean; }> = (props) => { const navigate = useNavigate(); const anchor = props.node.id || ""; @@ -112,7 +115,7 @@ export const HeadingNode: Component<{ const indent = props.depth * 12; return ( -
+
))}
diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 6ccba60..3edae62 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -2,6 +2,7 @@ import { Component, createMemo, createSignal, onMount, Show } from "solid-js"; import { generateToc, type FileNode, type TocNode } from "../data-loader"; import { useLocation } from "@solidjs/router"; import { FileTreeNode, HeadingNode } from "./FileTree"; +import { isPathRevealed } from "./stores/journalStream"; export interface SidebarProps { isOpen: boolean; @@ -33,6 +34,32 @@ const SidebarContent: Component = (props) => { props.pathHeadings[pathname] || props.pathHeadings[`${pathname}.md`] || [] ); }); + const revealedHeadings = createMemo(() => { + const pathname = decodeURIComponent(location.pathname); + const set = new Set(); + function traverse(node: TocNode, cb: (node: TocNode) => void) { + cb(node); + node.children?.forEach((child) => traverse(child, cb)); + } + for (const node of currentFileHeadings()) { + traverse(node, (anode) => { + if (isPathRevealed(pathname, anode.title)) { + traverse(anode, (each) => set.add(each.title)); + } + }); + } + return set; + }); + const isFileHidden = (node: FileNode): boolean => { + if (isPathRevealed(node.path)) return false; + if (node.children?.some((child) => !isFileHidden(child))) return false; + return true; + }; + const isHeadingHidden = (node: TocNode): boolean => { + if (revealedHeadings().has(node.title)) return false; + if (node.children?.some((child) => !isHeadingHidden(child))) return false; + return true; + }; return (
@@ -72,6 +99,7 @@ const SidebarContent: Component = (props) => { pathHeadings={props.pathHeadings} depth={0} onClose={props.onClose} + isHidden={isFileHidden} /> ))}
@@ -83,7 +111,12 @@ const SidebarContent: Component = (props) => { 本页 {currentFileHeadings().map((node) => ( - + ))}