8.1 KiB
		
	
	
	
	
	
	
	
			
		
		
	
	title, tags
| title | tags | |
|---|---|---|
| Explorer | 
  | 
Quartz features an explorer that allows you to navigate all files and folders on your site. It supports nested folders and is highly customizable.
By default, it shows all folders and files on your page. To display the explorer in a different spot, you can edit the layout.
[!info] The explorer uses local storage by default to save the state of your explorer. This is done to ensure a smooth experience when navigating to different pages.
To clear/delete the explorer state from local storage, delete the
fileTreeentry (guide on how to delete a key from local storage in chromium based browsers can be found here). You can disable this by passinguseSavedState: falseas an argument.
Customization
Most configuration can be done by passing in options to Component.Explorer().
For example, here's what the default configuration looks like:
Component.Explorer({
  title: "Explorer", // title of the explorer component
  folderClickBehavior: "collapse", // what happens when you click a folder ("link" to navigate to folder page on click or "collapse" to collapse folder on click)
  folderDefaultState: "collapsed", // default state of folders ("collapsed" or "open")
  useSavedState: true, // wether to use local storage to save "state" (which folders are opened) of explorer
  // Sort order: folders first, then files. Sort folders and files alphabetically
  sortFn: (a, b) => {
    ... // default implementation shown later
  },
  filterFn: undefined,
  mapFn: undefined,
  // what order to apply functions in
  order: ["filter", "map", "sort"],
})
When passing in your own options, you can omit any or all of these fields if you'd like to keep the default value for that field.
Want to customize it even more?
- Removing table of contents: remove 
Component.Explorer()fromquartz.layout.ts- (optional): After removing the explorer component, you can move the table of contents  component back to the 
leftpart of the layout 
 - (optional): After removing the explorer component, you can move the table of contents  component back to the 
 - Changing 
sort,filterandmapbehavior: explained in #Advanced customization - Component:
- Wrapper (Outer component, generates file tree, etc): 
quartz/components/Explorer.tsx - Explorer node (recursive, either a folder or a file): 
quartz/components/ExplorerNode.tsx 
 - Wrapper (Outer component, generates file tree, etc): 
 - Style: 
quartz/components/styles/explorer.scss - Script: 
quartz/components/scripts/explorer.inline.ts 
Advanced customization
This component allows you to fully customize all of its behavior. You can pass a custom sort, filter and map function.
All functions you can pass work with the FileNode class, which has the following properties:
export class FileNode {
  children: FileNode[]  // children of current node
  name: string  // name of node (only useful for folders)
  file: QuartzPluginData | null // set if node is a file, see `QuartzPluginData` for more detail
  depth: number // depth of current node
  ... // rest of implementation
}
Every function you can pass is optional. By default, only a sort function will be used:
// Sort order: folders first, then files. Sort folders and files alphabetically
Component.Explorer({
  sortFn: (a, b) => {
    if ((!a.file && !b.file) || (a.file && b.file)) {
      return a.name.localeCompare(b.name)
    }
    if (a.file && !b.file) {
      return 1
    } else {
      return -1
    }
  },
})
You can pass your own functions for sortFn, filterFn and mapFn. All functions will be executed in the order provided by the order option (see #Customization). These functions behave similarly to their Array.prototype counterpart, except they modify the entire FileNode tree in place instead of returning a new one.
For more information on how to use sort, filter and map, you can check Array.prototype.sort(), Array.prototype.filter() and Array.prototype.map().
Type definitions look like this:
sortFn: (a: FileNode, b: FileNode) => number
filterFn: (node: FileNode) => boolean
mapFn: (node: FileNode) => void
Tip
You can check if a
FileNodeis a folder or a file like this:if (node.file) { // node is a file } else { // node is a folder }
Basic examples
These examples show the basic usage of sort, map and filter.
Use sort to put files first
Using this example, the explorer will alphabetically sort everything, but put all files above all folders.
Component.Explorer({
  sortFn: (a, b) => {
    if ((!a.file && !b.file) || (a.file && b.file)) {
      return a.name.localeCompare(b.name)
    }
    if (a.file && !b.file) {
      return -1
    } else {
      return 1
    }
  },
})
Change display names (map)
Using this example, the display names of all FileNodes (folders + files) will be converted to full upper case.
Component.Explorer({
  mapFn: (node) => {
    node.name = node.name.toUpperCase()
  },
})
Remove list of elements (filter)
Using this example, you can remove elements from your explorer by providing an array of folders/files using the omit set.
Component.Explorer({
  filterFn: (node) => {
    // set containing names of everything you want to filter out
    const omit = new Set(["authoring content", "tags", "hosting"])
    return !omit.has(node.name.toLowerCase())
  },
})
You can customize this by changing the entries of the omit set. Simply add all folder or file names you want to remove.
Advanced examples
Add emoji prefix
To add emoji prefixes (📁 for folders, 📄 for files), you could use a map function like this:
Component.Explorer({
  mapFn: (node) => {
    // dont change name of root node
    if (node.depth > 0) {
      // set emoji for file/folder
      if (node.file) {
        node.name = "📄 " + node.name
      } else {
        node.name = "📁 " + node.name
      }
    }
  },
}})
Putting it all together
In this example, we're going to customize the explorer by using functions from examples above to #Add emoji prefix , #remove-list-of-elements-filter and #use-sort-to-put-files-first .
Component.Explorer({
  filterFn: sampleFilterFn,
  mapFn: sampleMapFn,
  sortFn: sampleSortFn,
  order: ["filter", "sort", "map"],
})
Notice how we customized the order array here. This is done because the default order applies the sort function last. While this normally works well, it would cause unintended behavior here, since we changed the first characters of all display names. In our example, sort would be applied based off the emoji prefix instead of the first real character.
To fix this, we just changed around the order and apply the sort function before changing the display names in the map function.
Tip
When writing more complicated functions, the
layoutfile can start to look very cramped. You can fix this by defining your functions in another file.import { Options } from "./quartz/components/ExplorerNode" export const mapFn: Options["mapFn"] = (node) => { // implement your function here } export const filterFn: Options["filterFn"] = (node) => { // implement your function here } export const sortFn: Options["sortFn"] = (a, b) => { // implement your function here }You can then import them like this:
import { mapFn, filterFn, sortFn } from "./functions.ts" Component.Explorer({ mapFn: mapFn, filterFn: filterFn, sortFn: sortFn, })