跳转到主要内容

命令面板

一个对话框同时承担页面搜索、页面动作与站点命令:如何打开、包含哪些分组、如何添加自定义命令。

命令面板是站点唯一的模态入口:搜索页面、复制本页 Markdown、切换语言、切换版本、跳转到站点自定义链接,都在这一个对话框里完成。它随本地搜索一起装配:params.offline_search 关闭时,面板连同索引与 Lunr 都不进入页面,见全文检索。

打开面板

打开方式 打开成什么
点顶栏或侧栏的搜索框 完整搜索态
⌘ / Ctrl + K 完整搜索态;再按一次关闭
/ 完整搜索态
反斜杠键 纯命令态(等于预填了 >)
f / c 同上两者,由键盘导航提供
在框里输入 > 开头的查询 纯命令态

/、反斜杠、f、c 都是裸单键,会给输入让行:焦点位于 input、textarea、select 或 contenteditable 中,以及正在用输入法组字时,按键作为普通字符输入。带修饰键的 ⌘/Ctrl + K 可以在输入框里打开面板,但同样会给输入法组字让行。 所有打开面板的快捷键都会让行于其他已打开的原生对话框或可见的 ARIA 对话框, 包括固定定位的对话框;隐藏的 ARIA 对话框不会阻止快捷键。

面板内:↑ ↓ 选择,Enter 执行,Esc 关闭并把焦点交还给打开它的控件。

面板内容

不输入任何内容时,面板按固定顺序列出四组:

分组 内容 谁决定
快速链接 顶栏一级菜单里选出的几个入口 params.ui.quick_links
页面操作 复制 Markdown、查看 Markdown 源码、编辑本页、查看修改历史、新建子页、提 issue、打印整节 仓库配置与本页是否有 Markdown 输出
偏好设置 切换版本 → 切换语言 → 切换主题 站点是否配了多版本、多语言、深浅色菜单
命令 打开 GitHub 仓库,之后是站点自定义命令 params.github_project_repo(缺省回退到 github_repo)与 ui.command_palette.commands

偏好设置三项的顺序与顶栏控件一致(版本、语言、主题),面板与顶栏是同一个次序。选中「切换语言」这类项后,面板不立即跳转,而是就地展开可选项,再选一次。

输入文字时,先是页面结果,按内容根分组(分组名是面包屑的第一段,组间顺序跟随顶栏一级菜单的顺序),命令与动作合并成一组排在最后。

以 > 开头时只列命令与动作,不查页面。不确定某个功能在哪个菜单里时用它定位。

不可用的项在能说明原因时仍然列出。站点没有配置仓库地址,「编辑本页」会带着「不可用」的说明留在列表里,而不是消失。

快速链接从 Hugo 主菜单里按 identifier 选取,不另写一份清单:

hugo.yml
params:
  ui:
    quick_links: [docs, blog]

值是 menus.main 里条目的 identifier。不写这个键时默认取文档栏目与博客栏目(params.ui.docs_section 和 blog_section)。菜单本身怎么配见导航与菜单。

自定义命令

站点自己的命令写在 params.ui.command_palette.commands 下,排在内建命令之后,顺序即书写顺序:

hugo.yml
languages:
  zh:
    params:
      ui:
        command_palette:
          commands:
            - id: theme_issues
              title: OINK 问题反馈
              description: 报告或查看主题与文档问题
              url: https://github.com/pgsty/oink/issues
              icon: fa-brands fa-github
              keywords: [缺陷, 支持, 路线图]

上面是本站在用的那一条。字段共七个。写入其它键或无效记录时,普通预览告警并 丢弃该命令,严格发布构建拒绝这条警告:

  • id 必填,小写字母开头,只能用小写字母、数字、下划线和短横线;不能与内建动作 ID 重名。
  • title 显示在面板里;description 是它下面那行小字;icon 是一对 Font Awesome class。
  • keywords 是数组,参与匹配但不显示,用于收纳读者可能输入的检索词。
  • url 与 action 有且只能有一个。url 只接受 http/https 的完整地址、站内路径,或 # 开头的页内锚点;带主机名的地址在新标签打开。action 引用一个内建动作 ID。
不要用 action: 给内建动作起别名

内建动作已经在面板里,再包一层会让同一个功能以两个名字出现两次。

多语言站点把命令写在 languages.<lang>.params.ui.command_palette.commands 下,标题与关键词才能本地化。顺序由默认语言的那份清单决定:其它语言里同 id 的条目只覆盖字段,新增的 id 追加在末尾。各语言的命令顺序因此一致,读者换语言时命令不会换位置。

配置只能给出链接或引用内建动作,不能注入 JavaScript 回调:面板读取的是一份纯数据清单。

页面动作

面板里的「页面操作」与文档标题旁的拆分按钮是同一套实现:同一份动作描述、同一段 URL 生成逻辑、同一个执行器。按钮左半边复制本页 Markdown,右侧箭头展开全部动作。

要隐藏标题旁的按钮,设置 page_context_menu: false;命令面板中的对应操作仍然保留:

hugo.yml
params:
  ui:
    page_context_menu: false

只隐藏某一页的按钮时,在该页 front matter 中设置 page_context_menu: false 即可。

assistant_links 默认关闭,原因是读者点击时 当前页面的完整 URL(含查询串与锚点)会被发送到第三方,页面正文不会上传。全站通过 params.ui.page_context_menu.assistant_links 启用,页面只能用以下 front matter 收紧策略:

页面 front matter
page_context_menu:
  assistant_links: false

确认该页的标题菜单和命令面板均没有助理入口。跳转行为见 Agent 支持。

links 是额外的外部动作,只出现在标题旁的菜单里,不进面板:

hugo.yml
params:
  ui:
    page_context_menu:
      links:
        - name: 在站内讨论区提问
          url: https://github.com/pgsty/oink/discussions/new?title={title}
          icon: fa-solid fa-comments

{url}、{title}、{markdown_url} 三个占位符会被替换成当前页面的值。

「编辑本页」「查看修改历史」「提 issue」这些动作是否可用,取决于仓库相关的配置,见仓库与页面信息;「复制 Markdown」「查看 Markdown 源码」需要页面开了 markdown 输出,见 Agent 支持。

同一个对话框,两条独立的数据来源:

  • 页面结果 来自本地搜索索引。索引未生成或下载失败时,面板照常打开、照常执行命令,页面那部分显示「页面索引暂不可用,操作仍可使用」。
  • 命令与动作 来自页面里内嵌的一段 JSON 清单,不需要网络。

打印态不装配面板,打印输出里没有它;关闭 offline_search 后同样没有面板,此时 f 与 c 静默,不影响正常输入。

使用当前查询的站点操作

受信任站点 JavaScript 使用的运行时接口自 OINK 1.1 起提供。 使用前检查能力是否存在:v1.0.0 和未启用本地搜索的页面不提供它。集成代码应在主题脚本 之后加载,例如使用 layouts/_partials/hooks/body-end.html。以下示例假定站点实现了 openSiteAssistant,并自行管理服务商设置:

if (window.OinkCommandPalette?.registerSearchTail) {
  const unregister = window.OinkCommandPalette.registerSearchTail({
    id: 'ask-site',
    rows(context) {
      return [{ id: 'ask', title: '询问站点', description: context.query }];
    },
    activate(row, context) {
      context.handoff();
      return openSiteAssistant(context.query, {
        locale: context.locale,
        signal: context.signal,
      });
    },
  });
  // 移除此集成时调用 unregister()。
}

扩展行排在原生结果和操作之后,包括空结果与索引错误状态;空查询、命令、选择和加载状态 不出现扩展行。rows() 应保持纯净且同步,所有字符串都作为文本渲染。激活接收生成该行时 的查询,不会读取更新后的输入值。打开另一个受协调器管理的界面前调用 handoff(),此后 由站点负责新界面的焦点与失败提示。没有新界面的操作直接返回 Promise,不调用 handoff。

Shell 契约 定义了字段、取消、校验和生命周期。 YAML 仍不能包含回调,OINK 默认不添加远程服务或遥测。

验证

先在自己的站点根目录完成严格构建。下方命令中的 public/zh/docs/getting-started/index.html 是示例;请换成自己站点实际生成的文档页, 并按语言配置调整路径前缀。

  1. 构建后确认命令清单进了页面:

    hugo --printPathWarnings --panicOnWarning
    PAGE=public/zh/docs/getting-started/index.html
    test -f "$PAGE" && grep -o 'td-action-manifest' "$PAGE"

    这一步确认操作数据已写入 HTML;其余步骤用于在启用本地搜索后检查命令面板界面。

  2. 打开站点按下 ⌘/Ctrl + K,什么都不输入:应该看到快速链接、页面操作、偏好设置、命令四组,顺序如上。

  3. 输入 >:只剩命令与动作。新加的命令应该排在「打开 GitHub 仓库」之后。

  4. 切到另一种语言重复第 3 步,确认命令的标题变了、顺序没变。

  5. 打印预览(⌘/Ctrl + P)里不应该出现任何面板痕迹。