目录级配置写在 folders 字段中:站点在 __everkm/everkm.yaml,主题可在 everkm-theme.yaml 中预设默认值(站点按路径覆盖)。config、default_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 合并结果;面包屑见 __breadcrumbs 与 nav_path。
字段说明
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
url_slug | string | 目录名 slugify | 自定义该目录在 URL 中的路径段;显式配置后即使该目录无 index.md,slug 也会进入子孙文章的 URL 前缀(见 [[#url-generation |
hide_in_url | bool | false | 设为 true 时该目录不参与 URL 路径拼接 |
template | string | — | 该目录下页面默认模板路径 |
query | object | — | 渲染时合并进 __qs 的键值对 |
breadcrumbs | array | — | 面包屑条目数组,每项含 title、url;支持 @i18n:<key> |
hash_scatter | bool | false | 是否将文章 URL 哈希分散到子目录(别名 hash_storage、storage_scatter) |
url_id_suffix | bool | true | 设为 false 时非 index 页 URL 为 {slug}.html,不追加 -{id} |
合并规则
配置来源与优先级
与 config、default_template 相同:主题 folders 为底,站点 everkm.yaml#folders 按路径键覆盖。config 的深度合并(对象递归、数组整段替换)见 站点配置。
effective_folders[path] =
everkm-theme.yaml#folders[path](若存在)
→ everkm.yaml#folders[path] 非空字段 extend 覆盖
同一 path 键上,站点只写 template 时,仍会保留主题预设的 url_slug、url_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(满足其一即可):
- 显式
url_slug:该层在effective_folders[path]中配置了非空url_slug(含主题预设) - 目录 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_tree、nav_path、nav_indicator。其 from_file 参数若用 [[...]] 包裹,与正文 内链 采用相同解析规则(大小写不敏感、歧义报错)。
{{ nav_tree(from_file="[[./SUMMARY.md]]") | json_encode }}