Skip to content

Commit 4845223

Browse files
authored
perf: memoize filetree computation (#490)
* perf: memoize filetree computation * format * var -> let
1 parent 16d33fb commit 4845223

File tree

1 file changed

+44
-34
lines changed

1 file changed

+44
-34
lines changed

quartz/components/Explorer.tsx

Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import explorerStyle from "./styles/explorer.scss"
44
// @ts-ignore
55
import script from "./scripts/explorer.inline"
66
import { ExplorerNode, FileNode, Options } from "./ExplorerNode"
7+
import { QuartzPluginData } from "../plugins/vfile"
78

89
// Options interface defined in `ExplorerNode` to avoid circular dependency
910
const defaultOptions = {
@@ -27,49 +28,58 @@ const defaultOptions = {
2728
} satisfies Options
2829

2930
export default ((userOpts?: Partial<Options>) => {
30-
function Explorer({ allFiles, displayClass, fileData }: QuartzComponentProps) {
31-
// Parse config
32-
const opts: Options = { ...defaultOptions, ...userOpts }
31+
// Parse config
32+
const opts: Options = { ...defaultOptions, ...userOpts }
3333

34-
// Construct tree from allFiles
35-
const fileTree = new FileNode("")
36-
allFiles.forEach((file) => fileTree.add(file, 1))
34+
// memoized
35+
let fileTree: FileNode
36+
let jsonTree: string
3737

38-
/**
39-
* Keys of this object must match corresponding function name of `FileNode`,
40-
* while values must be the argument that will be passed to the function.
41-
*
42-
* e.g. entry for FileNode.sort: `sort: opts.sortFn` (value is sort function from options)
43-
*/
44-
const functions = {
45-
map: opts.mapFn,
46-
sort: opts.sortFn,
47-
filter: opts.filterFn,
48-
}
38+
function constructFileTree(allFiles: QuartzPluginData[]) {
39+
if (!fileTree) {
40+
// Construct tree from allFiles
41+
fileTree = new FileNode("")
42+
allFiles.forEach((file) => fileTree.add(file, 1))
43+
44+
/**
45+
* Keys of this object must match corresponding function name of `FileNode`,
46+
* while values must be the argument that will be passed to the function.
47+
*
48+
* e.g. entry for FileNode.sort: `sort: opts.sortFn` (value is sort function from options)
49+
*/
50+
const functions = {
51+
map: opts.mapFn,
52+
sort: opts.sortFn,
53+
filter: opts.filterFn,
54+
}
4955

50-
// Execute all functions (sort, filter, map) that were provided (if none were provided, only default "sort" is applied)
51-
if (opts.order) {
52-
// Order is important, use loop with index instead of order.map()
53-
for (let i = 0; i < opts.order.length; i++) {
54-
const functionName = opts.order[i]
55-
if (functions[functionName]) {
56-
// for every entry in order, call matching function in FileNode and pass matching argument
57-
// e.g. i = 0; functionName = "filter"
58-
// converted to: (if opts.filterFn) => fileTree.filter(opts.filterFn)
56+
// Execute all functions (sort, filter, map) that were provided (if none were provided, only default "sort" is applied)
57+
if (opts.order) {
58+
// Order is important, use loop with index instead of order.map()
59+
for (let i = 0; i < opts.order.length; i++) {
60+
const functionName = opts.order[i]
61+
if (functions[functionName]) {
62+
// for every entry in order, call matching function in FileNode and pass matching argument
63+
// e.g. i = 0; functionName = "filter"
64+
// converted to: (if opts.filterFn) => fileTree.filter(opts.filterFn)
5965

60-
// @ts-ignore
61-
// typescript cant statically check these dynamic references, so manually make sure reference is valid and ignore warning
62-
fileTree[functionName].call(fileTree, functions[functionName])
66+
// @ts-ignore
67+
// typescript cant statically check these dynamic references, so manually make sure reference is valid and ignore warning
68+
fileTree[functionName].call(fileTree, functions[functionName])
69+
}
6370
}
6471
}
65-
}
6672

67-
// Get all folders of tree. Initialize with collapsed state
68-
const folders = fileTree.getFolderPaths(opts.folderDefaultState === "collapsed")
73+
// Get all folders of tree. Initialize with collapsed state
74+
const folders = fileTree.getFolderPaths(opts.folderDefaultState === "collapsed")
6975

70-
// Stringify to pass json tree as data attribute ([data-tree])
71-
const jsonTree = JSON.stringify(folders)
76+
// Stringify to pass json tree as data attribute ([data-tree])
77+
jsonTree = JSON.stringify(folders)
78+
}
79+
}
7280

81+
function Explorer({ allFiles, displayClass, fileData }: QuartzComponentProps) {
82+
constructFileTree(allFiles)
7383
return (
7484
<div class={`explorer ${displayClass}`}>
7585
<button

0 commit comments

Comments
 (0)