perf: memoize filetree computation (#490)
* perf: memoize filetree computation * format * var -> let
This commit is contained in:
parent
16d33fb771
commit
48452231d5
@ -4,6 +4,7 @@ import explorerStyle from "./styles/explorer.scss"
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import script from "./scripts/explorer.inline"
|
import script from "./scripts/explorer.inline"
|
||||||
import { ExplorerNode, FileNode, Options } from "./ExplorerNode"
|
import { ExplorerNode, FileNode, Options } from "./ExplorerNode"
|
||||||
|
import { QuartzPluginData } from "../plugins/vfile"
|
||||||
|
|
||||||
// Options interface defined in `ExplorerNode` to avoid circular dependency
|
// Options interface defined in `ExplorerNode` to avoid circular dependency
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
@ -27,49 +28,58 @@ const defaultOptions = {
|
|||||||
} satisfies Options
|
} satisfies Options
|
||||||
|
|
||||||
export default ((userOpts?: Partial<Options>) => {
|
export default ((userOpts?: Partial<Options>) => {
|
||||||
function Explorer({ allFiles, displayClass, fileData }: QuartzComponentProps) {
|
// Parse config
|
||||||
// Parse config
|
const opts: Options = { ...defaultOptions, ...userOpts }
|
||||||
const opts: Options = { ...defaultOptions, ...userOpts }
|
|
||||||
|
|
||||||
// Construct tree from allFiles
|
// memoized
|
||||||
const fileTree = new FileNode("")
|
let fileTree: FileNode
|
||||||
allFiles.forEach((file) => fileTree.add(file, 1))
|
let jsonTree: string
|
||||||
|
|
||||||
/**
|
function constructFileTree(allFiles: QuartzPluginData[]) {
|
||||||
* Keys of this object must match corresponding function name of `FileNode`,
|
if (!fileTree) {
|
||||||
* while values must be the argument that will be passed to the function.
|
// Construct tree from allFiles
|
||||||
*
|
fileTree = new FileNode("")
|
||||||
* e.g. entry for FileNode.sort: `sort: opts.sortFn` (value is sort function from options)
|
allFiles.forEach((file) => fileTree.add(file, 1))
|
||||||
*/
|
|
||||||
const functions = {
|
|
||||||
map: opts.mapFn,
|
|
||||||
sort: opts.sortFn,
|
|
||||||
filter: opts.filterFn,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute all functions (sort, filter, map) that were provided (if none were provided, only default "sort" is applied)
|
/**
|
||||||
if (opts.order) {
|
* Keys of this object must match corresponding function name of `FileNode`,
|
||||||
// Order is important, use loop with index instead of order.map()
|
* while values must be the argument that will be passed to the function.
|
||||||
for (let i = 0; i < opts.order.length; i++) {
|
*
|
||||||
const functionName = opts.order[i]
|
* e.g. entry for FileNode.sort: `sort: opts.sortFn` (value is sort function from options)
|
||||||
if (functions[functionName]) {
|
*/
|
||||||
// for every entry in order, call matching function in FileNode and pass matching argument
|
const functions = {
|
||||||
// e.g. i = 0; functionName = "filter"
|
map: opts.mapFn,
|
||||||
// converted to: (if opts.filterFn) => fileTree.filter(opts.filterFn)
|
sort: opts.sortFn,
|
||||||
|
filter: opts.filterFn,
|
||||||
|
}
|
||||||
|
|
||||||
// @ts-ignore
|
// Execute all functions (sort, filter, map) that were provided (if none were provided, only default "sort" is applied)
|
||||||
// typescript cant statically check these dynamic references, so manually make sure reference is valid and ignore warning
|
if (opts.order) {
|
||||||
fileTree[functionName].call(fileTree, functions[functionName])
|
// Order is important, use loop with index instead of order.map()
|
||||||
|
for (let i = 0; i < opts.order.length; i++) {
|
||||||
|
const functionName = opts.order[i]
|
||||||
|
if (functions[functionName]) {
|
||||||
|
// for every entry in order, call matching function in FileNode and pass matching argument
|
||||||
|
// e.g. i = 0; functionName = "filter"
|
||||||
|
// converted to: (if opts.filterFn) => fileTree.filter(opts.filterFn)
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
// typescript cant statically check these dynamic references, so manually make sure reference is valid and ignore warning
|
||||||
|
fileTree[functionName].call(fileTree, functions[functionName])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get all folders of tree. Initialize with collapsed state
|
||||||
|
const folders = fileTree.getFolderPaths(opts.folderDefaultState === "collapsed")
|
||||||
|
|
||||||
|
// Stringify to pass json tree as data attribute ([data-tree])
|
||||||
|
jsonTree = JSON.stringify(folders)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get all folders of tree. Initialize with collapsed state
|
function Explorer({ allFiles, displayClass, fileData }: QuartzComponentProps) {
|
||||||
const folders = fileTree.getFolderPaths(opts.folderDefaultState === "collapsed")
|
constructFileTree(allFiles)
|
||||||
|
|
||||||
// Stringify to pass json tree as data attribute ([data-tree])
|
|
||||||
const jsonTree = JSON.stringify(folders)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={`explorer ${displayClass}`}>
|
<div class={`explorer ${displayClass}`}>
|
||||||
<button
|
<button
|
||||||
|
Loading…
Reference in New Issue
Block a user