目录配置

2026-06-30

目录级配置写在 folders 字段中:站点在 __everkm/everkm.yaml,主题可在 everkm-theme.yaml 中预设默认值(站点按路径覆盖)。configdefault_template 及两文件的整体归属见 站点配置 · 配置归属

子目录配置与祖先目录合并继承,深层配置覆盖或追加浅层同名字段。

v0.17.0 起:旧版各目录 index.yaml 已废弃,不再被读取。请将配置迁移至 everkm.yaml#folders

基本示例

# __everkm/everkm.yaml
folders:
  "/":
    hide_in_url: true
  "/docs/":
    template: book.html
    query:
      stack: true
    breadcrumbs:
      - title: "@i18n:nav.docs"
        url: /docs/
  "/blog/":
    template: list.html
    url_id_suffix: false

模板中通过全局变量 __qs 读取 query 合并结果;面包屑见 __breadcrumbsnav_path

字段说明

字段类型默认值说明
url_slugstring目录名 slugify自定义该目录在 URL 中的路径段;显式配置后即使该目录无 index.md,slug 也会进入子孙文章的 URL 前缀(见 [[#url-generation
hide_in_urlboolfalse设为 true 时该目录不参与 URL 路径拼接
templatestring该目录下页面默认模板路径
queryobject渲染时合并进 __qs 的键值对
breadcrumbsarray面包屑条目数组,每项含 titleurl;支持 @i18n:<key>
hash_scatterboolfalse是否将文章 URL 哈希分散到子目录(别名 hash_storagestorage_scatter
url_id_suffixbooltrue设为 false 时非 index 页 URL 为 {slug}.html,不追加 -{id}

合并规则

配置来源与优先级

configdefault_template 相同:主题 folders 为底,站点 everkm.yaml#folders 按路径键覆盖config 的深度合并(对象递归、数组整段替换)见 站点配置

effective_folders[path] =
  everkm-theme.yaml#folders[path](若存在)
  → everkm.yaml#folders[path] 非空字段 extend 覆盖

同一 path 键上,站点只写 template 时,仍会保留主题预设的 url_slugurl_id_suffix 等未覆盖字段。

主题开发者在 everkm-theme.yaml 中预设路由与模板,站点运营者只需在 everkm.yaml 写差异。详见 主题元信息

祖先链合并

对文章所在目录(如 /blog/2025/01/),在 effective_folders 上沿祖先链(根→叶)逐级合并:

祖先链: / → /blog/ → /blog/2025/ → /blog/2025/01/
merged = 默认值
对链上每级: 若 effective_folders[path] 存在 → merged.extend(...)
  • 子层显式配置覆盖父层同名字段
  • 子层未配置时继承祖先合并结果
  • 合并按祖先链顺序,不是按 key 字符串长度排序

合并规则

  • 链首不再自动插入「Home」;若需要首页入口,请在 folders["/"].breadcrumbs 中自行声明
  • 子目录 breadcrumbs 非空时按目录深度追加到祖先链末尾,不会整段替换祖先配置
  • 子目录未写 breadcrumbs不会清空祖先已合并的面包屑
  • 若各级均未配置,会按当前页 URL 路径自动生成:每一级目录的 index 页会出现在面包屑中

title 支持 @i18n:<key> 引用。仅当条目未配置 url(或 url 为空) 时,title[[wikilink]] 才会按内链解析(先替换 i18n,再判定内链),并采用目标页面的标题与 URL。

folders:
  "/":
    breadcrumbs:
      - title: "@i18n:nav.home"
        url: ~/
  "/blog/":
    breadcrumbs:
      - title: "[[blog]]"
      - title: "@i18n:nav.blog"

URL 生成

目录路径拼接

url_path = join(各级 effective_slug),跳过 hide_in_url == true 的级
effective_slug = url_slug ?? slugify(该级目录段名)

哪些目录段会进入 URL(满足其一即可):

  1. 显式 url_slug:该层在 effective_folders[path] 中配置了非空 url_slug(含主题预设)
  2. 目录 index 链:该层位于「从根到最深目录 index.md(目录首页)」的路径上,此时未写 url_slug 的层会使用目录名 slugify

未显式 url_slug、且祖先链上没有任何目录 index 的中间层不会出现在 URL 中(磁盘目录名不泄漏)。因此可将内容放在 /blog/2025/ 等深层目录,通过 /blog/url_slug: posts 统一映射到 /posts/...

url_slug 的 bypass 按每层 path 键独立判定,不向子目录继承。父级 /blog/url_slug: posts 时,子级 /blog/2025/ 若无 slug 且无 index,不会重复压入 posts

示例(无目录 index):

# 主题或站点 folders
"/blog/":
  url_slug: posts
文章路径逻辑 URL
/blog/2025/hello.md/posts/hello-{id}.html(或 hello.html,见 url_id_suffix

/blog/2025/ 另有 index.md,则子孙 URL 会多一级 /2025//posts/2025/hello.html

文件名规则

条件URL 文件名示例
目录 index 页index/blog/index.html
普通文 + url_id_suffix: true(默认){slug}-{id}/blog/hello-abc123.html
普通文 + url_id_suffix: false{slug}/blog/hello.html

组合示例

按目录分区 + 短 URL

folders:
  "/blog/":
    url_id_suffix: false
    hash_scatter: true
  • 逻辑 URL: /blog/my-post.html
  • 导出物理路径: /blog/ab/cd/my-post.html(经 __hs=1 触发)

磁盘目录与对外路由解耦(常见于主题预设 + 站点少量覆盖):

# everkm-theme.yaml
folders:
  "/":
    hide_in_url: true
  "/blog/":
    url_slug: posts
    template: list.html
    url_id_suffix: false

# everkm.yaml(可选)
folders:
  "/blog/2025/":
    template: archive.html
  • /blog/2025/hello.md/posts/hello.html(中间 2025 无 index、无 slug,不出现在 URL 中)

导航函数与内链

书籍/文档模板中常用 nav_treenav_pathnav_indicator。其 from_file 参数若用 [[...]] 包裹,与正文 内链 采用相同解析规则(大小写不敏感、歧义报错)。

{{ nav_tree(from_file="[[./SUMMARY.md]]") | json_encode }}