尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Quartz Explorer 插件完全指南:文件树侧边栏的安装、配置与深度定制

Quartz Explorer 插件完全指南:文件树侧边栏的安装、配置与深度定制 Quartz Explorer 插件完全指南文件树侧边栏的安装、配置与深度定制【免费下载链接】quartz a fast, batteries-included static-site generator that transforms Markdown content into fully functional websites项目地址: https://gitcode.com/GitHub_Trending/qua/quartzQuartz 的 Explorer 插件为你的静态站点提供可嵌套文件夹的文件树侧边栏是访客快速浏览全站内容结构的核心导航组件。本文以 docs/plugins/Explorer.md 与 docs/features/explorer.md 为骨架结合仓库内FileTrieNode的源码实现系统讲解其安装、布局、YAML 与 TS 双层配置体系以及基于sortFn/filterFn/mapFn的深度定制方案读完后你可以独立完成 Explorer 的部署、个性化与二次开发。一、Explorer 是什么Explorer 是一个显示站点全部文件与文件夹的侧边栏组件支持嵌套文件夹展开/折叠并允许你通过排序、过滤、改名函数高度自定义展示逻辑。它同时也是 Quartz 社区插件生态的示范实现Quartz 官方文档明确指出Explorer 已从内置组件迁移为社区插件这一迁移本身就是展示外部插件如何扩展 Quartz 功能、并作为插件开发者参考实现的最佳案例。从源码结构看Explorer 插件的组件实例通过 componentLoader.ts 中的loadComponentsFromPackage注册到componentRegistry插件按全限定键pluginName/exportName注册若插件仅导出一个组件还会额外以插件名如explorer注册方便布局系统按 kebab-case 直接查找。i18n 词条中也预留了explorer.title的本地化文案见 en-US.ts说明组件标题支持多语言。二、安装与启用Explorer 以社区插件形式从 GitHub 分发安装分两步先安装插件包再在quartz.config.yaml中声明并启用。npm install github:quartz-community/explorer --legacy-peer-deps在quartz.config.yaml的plugins列表中添加条目plugins: - source: github:quartz-community/explorer enabled: true layout: position: left priority: 50也可以使用 Quartz 的插件 CLI 一键完成安装与配置写入npx quartz plugin add github:quartz-community/explorer该命令会把插件写入quartz.config.yaml并安装到.quartz/plugins/目录。若克隆了新项目或搭建 CI 环境可用npx quartz plugin install --from-config批量安装配置中引用但尚未安装的插件用npx quartz plugin prune清理已从配置移除的插件二者均支持--dry-run预览详见 docs/cli/plugin.md。关于source字段docs/configuration.md 提供了对象形式的进阶写法可用于 monorepo 子目录插件或固定分支/标签repoGit 仓库 URL、subdir仓库内插件子目录、ref分支或标签、name覆盖.quartz/plugins/下的目录名。三、侧边栏位置与布局Explorer 默认显示在页面左侧。你可以通过插件条目中的layout.position改变其位置可用的 section 包括header、beforeBody、afterBody、left、right、footer而layout.priority决定同一 section 内多个组件的排列顺序数值越小越靠前详见 docs/layout.md。布局系统在 config-loader.ts 的buildLayoutForEntries中实现每个启用且声明了layout的插件按 position 归入对应插槽再按 priority 排序、并按layout.groups解析 Flex 组合。若你希望 Explorer 从布局中消失直接删除quartz.config.yaml中的explorer条目或把enabled设为false即可移除后若觉得左侧太空可将 TableOfContents 组件移回left区。四、YAML 配置项大部分配置通过 YAML 选项完成位于插件条目的options字段下具体参数如下参数说明可选值默认值titleExplorer 的显示标题任意字符串ExplorerfolderClickBehavior点击文件夹时的行为link跳转到文件夹页或collapse展开/折叠切换linkfolderDefaultState文件夹的默认状态collapsed折叠或open展开collapseduseSavedState是否使用浏览器 localStorage 保存展开/折叠状态true/falsetrue默认配置如下可直接复制使用plugins: - source: github:quartz-community/explorer enabled: true options: title: Explorer folderClickBehavior: collapse # link to navigate or collapse to toggle folderDefaultState: collapsed # collapsed or open useSavedState: true layout: position: left priority: 50各选项可以按需省略省略即使用默认值。4.1 显示名称的确定规则文件夹在侧边栏中的显示名优先取该文件夹下index.md的titlefrontmatter 字段若该文件不存在或不含 frontmatter则回退使用本地文件夹名。这一点与 docs/getting-started/authoring-content.md 中 frontmatter 的约定一致。文件节点同理优先使用其 frontmatter 的title否则使用 slug 段。这个标题优先于路径的回退逻辑在仓库的 fileTrie.ts 中有对应实现displayName的取值顺序是displayNameOverridemapFn 设置→ frontmattertitleindex除外→ 文件路径段提示fileSegmentHint→ slug 段。其中fileSegmentHint会优先使用磁盘上的真实目录名而非 slug这正是为了让没有index.md的文件夹能按原始目录名展示、避免 slug 中的连字符进入界面见 fileTrie.ts 的注释。4.2 状态持久化localStorageExplorer 默认使用 localStorage 保存你的展开/折叠状态以保证跨页面导航时的连续体验。清除该状态的方法是删除 localStorage 中名为fileTree的条目Chromium 系浏览器可通过 DevTools → Application → Local Storage 删除。若你不想持久化状态传入useSavedState: false即可关闭。五、TS 覆盖回调型选项部分选项自定义排序、过滤、改名函数是 JavaScript 回调无法用 YAML 表达必须通过quartz.ts的 TS override 传入。ExternalPlugin.Explorer()接受以下选项参数类型说明sortFn(a, b) number自定义排序函数决定文件与文件夹的展示顺序filterFn(node) boolean自定义过滤函数返回false的节点被排除mapFn(node) void自定义映射函数可原地修改节点属性如显示名orderstring[]操作执行顺序默认[filter, map, sort]最小化的 TS override 示例import * as ExternalPlugin from ./.quartz/plugins // Must be placed before loadQuartzConfig() ExternalPlugin.Explorer({ mapFn: (node) { node.displayName node.displayName.toUpperCase() return node }, })5.1 覆盖的合并与优先级Quartz 采用插件默认值 YAML 选项 quartz.ts 覆盖的优先级顺序。当你在quartz.ts中调用ExternalPlugin.Explorer({...})时选项会被记录并在构建期实例化组件时与 YAML 配置合并quartz.ts中设置的选项优先于quartz.config.yaml。这一点在 config-loader.ts 中体现为显式的对象展开合并{ ...manifest?.defaultOptions, ...entry.options, ...pluginOverrides }pluginOverrides来自 TS 覆盖的注册表排在最后、优先级最高。关键约束是TS 覆盖必须写在loadQuartzConfig()调用之前否则组件在配置加载期已被实例化覆盖将不生效。完整形态的quartz.ts写法同时声明配置与布局导出import { loadQuartzConfig, loadQuartzLayout } from ./quartz/plugins/loader/config-loader import * as ExternalPlugin from ./.quartz/plugins // Advanced: pass callback functions that cant be expressed in YAML ExternalPlugin.Explorer({ sortFn: (a, b) { /* ... */ }, filterFn: (node) { /* ... */ }, mapFn: (node) { /* ... */ }, order: [filter, map, sort], }) const config await loadQuartzConfig() export default config export const layout await loadQuartzLayout()如果安装了两个同名导出的插件例如通过--name安装了多个 Explorer可用plugins映射消歧import * as ExternalPlugin from ./.quartz/plugins ExternalPlugin.plugins[my-explorer].Explorer({ mapFn: ... })六、底层原理FileTrieNodeExplorer 的所有回调都作用于FileTrieNode类。该类的完整实现位于仓库 quartz/util/fileTrie.ts是 Quartz 核心工具之一其主要结构如下export class FileTrieNodeT extends FileTrieData ContentDetails { isFolder: boolean children: ArrayFileTrieNodeT data: T | null get displayName(): string { ... } set displayName(name: string) { ... } get slug(): FullSlug { ... } add(file: T) { ... } // 按 slug 路径插入节点 filter(filterFn) { ... } // 原地过滤子树 map(mapFn) { ... } // 原地映射全部节点 sort(sortFn) { ... } // 原地排序子树 }FileTrieNode是一个按 slug 段组织的前缀树trie根节点代表站点根isFolder在插入子节点时被自动置为true文件数据存放在data字段。插件文档中给出的ContentDetails类型与仓库接口一致export type ContentDetails { slug: FullSlug title: string links: SimpleSlug[] tags: string[] content: string }理解几个实现要点有助于写出正确的回调原地修改filter、map、sort与Array.prototype同名方法语义相似但它们是直接修改整棵树而非返回新数组——filter递归地对每层children做过滤fileTrie.tsmap递归地对每个节点含自身执行函数fileTrie.tssort同样递归应用到每一层fileTrie.ts。因此排序会作用于每个文件夹内的兄弟节点。data仅对真实文件存在文件夹若没有对应的index.md其data为null所以过滤时访问node.data需要判空。slug 语义文件夹节点的 slug 会以index结尾get slug()返回joinSegments(path, index)见 fileTrie.ts路径中不含index的节点不会被findNode命中。碰撞处理当多个源文件映射到同一 slug 时采用后插入者胜出last-insert-wins与发射器plugins/emitters/helpers.ts的语义保持一致相关行为在 fileTrie.test.ts 中有专门的测试用例验证。对FileTrieNode行为的单元测试覆盖了增删改查、嵌套构建、碰撞、fromEntries、findNode、getFolderPaths、sort与ancestryChain等场景可作为你编写自定义回调时的行为参考见 quartz/util/fileTrie.test.ts。七、默认行为与内置排序所有回调均为可选。默认情况下仅启用一个sort函数其逻辑是文件夹优先于文件同类之间按字母序排列// Sort order: folders first, then files. Sort folders and files alphabetically ExternalPlugin.Explorer({ sortFn: (a, b) { if ((!a.isFolder !b.isFolder) || (a.isFolder b.isFolder)) { return a.displayName.localeCompare(b.displayName, undefined, { numeric: true, sensitivity: base, }) } if (!a.isFolder b.isFolder) { return 1 } else { return -1 } }, })注意这里使用了localeCompare的numeric: true数字按数值而非字典序比较和sensitivity: base忽略大小写差异选项。三个回调的类型签名如下type SortFn (a: FileTrieNode, b: FileTrieNode) number type FilterFn (node: FileTrieNode) boolean type MapFn (node: FileTrieNode) voidMapFn返回void而非新节点印证了原地修改的设计——map 的典型用途是改写node.displayNamesetter 会写入displayNameOverride见 fileTrie.ts。八、实战示例8.1 用sort让文件排在前面如果只做简单调整如设置标题、默认折叠用 YAML 即可plugins: - source: github:quartz-community/explorer enabled: true options: # Simple options go in YAML title: Explorer folderDefaultState: collapsed自定义排序必须走 TS override——下面这个例子会按显示名对所有节点做纯字母排序不再区分文件夹优先ExternalPlugin.Explorer({ sortFn: (a, b) { return a.displayName.localeCompare(b.displayName) }, })8.2 用map修改显示名将所有节点文件夹 文件的显示名转为大写ExternalPlugin.Explorer({ mapFn: (node) { node.displayName node.displayName.toUpperCase() return node }, })[!note]mapFn、filterFn、sortFn需要 JavaScript 回调无法在 YAML 中表达必须使用 TS override。8.3 用filter移除指定元素通过一个包含待排除名称的Set过滤节点。此例按显示名过滤你也可以改用node.slug或node.data上的任意字段注意node.data仅对磁盘上真实存在的文件可用无index.md的隐式文件夹节点为nullExternalPlugin.Explorer({ filterFn: (node) { // set containing names of everything you want to filter out const omit new Set([authoring content, tags, advanced]) // can also use node.slug or by anything on node.data // note that node.data is only present for files that exist on disk // (e.g. implicit folder nodes that have no associated index.md) return !omit.has(node.displayName.toLowerCase()) }, })8.4 按标签移除文件文件的标签可通过node.data.tags访问据此可排除带特定标签的页面ExternalPlugin.Explorer({ filterFn: (node) { // exclude files with the tag explorerexclude return node.data?.tags?.includes(explorerexclude) ! true }, })8.5 显示所有元素关闭默认过滤默认情况下 Explorer 会过滤掉tags文件夹。若想显示全部内容把filterFn显式设为undefined即可禁用默认过滤函数ExternalPlugin.Explorer({ filterFn: undefined, // apply no filter function, every file and folder will visible })8.6 高级示例添加 emoji 前缀用 map 函数给文件夹加 、文件加 前缀ExternalPlugin.Explorer({ mapFn: (node) { if (node.isFolder) { node.displayName node.displayName } else { node.displayName node.displayName } }, })8.7 复杂逻辑的代码组织建议当函数变复杂时quartz.ts会显得拥挤。建议把函数定义在组件调用之外再用类型标注保证正确性然后传入import * as ExternalPlugin from ./.quartz/plugins import type { ExplorerOptions } from ./.quartz/plugins const mapFn: ExplorerOptions[mapFn] (node) { // implement your function here } const filterFn: ExplorerOptions[filterFn] (node) { // implement your function here } const sortFn: ExplorerOptions[sortFn] (a, b) { // implement your function here } ExternalPlugin.Explorer({ // ... your other options mapFn, filterFn, sortFn, })所有函数按order选项给定的顺序依次执行默认[filter, map, sort]。由于三者都是原地修改整棵FileTrieNode树执行顺序会影响后续函数看到的数据例如map改名后再sort排序就会基于新名称进行。九、API 速查项目内容分类Component组件类插件函数名ExternalPlugin.Explorer()安装命令npx quartz plugin add github:quartz-community/explorer默认启用是必需否可选组件十、常见问题与建议点击文件夹无反应检查folderClickBehavior——设为link时点击会导航到文件夹页若文件夹没有对应页面请改用collapse。状态混乱或想重置删除 localStorage 中的fileTree键或直接配置useSavedState: false。过滤后文件夹消失filter是递归的会作用于每一层子节点若某文件夹的所有子节点都被过滤该文件夹在 UI 上自然不再显示。想完全自定义可参考 docs/plugins/Explorer.md 的默认配置与回调签名或阅读本仓库 fileTrie.ts 及 fileTrie.test.ts 理解节点行为后再动手若希望编写自己的组件可参考 docs/advanced/making plugins.md。【免费下载链接】quartz a fast, batteries-included static-site generator that transforms Markdown content into fully functional websites项目地址: https://gitcode.com/GitHub_Trending/qua/quartz创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表