Nextora 站点组合
负责 Nextora 驱动的块主题的组合层:templates/、parts/、patterns/ 以及描述它们的 theme.json 声明。块内部细节见 ../nextora-gutenberg-blocks/SKILL.md;外观和预设数据见 ../nextora-design-system/SKILL.md;子主题引导和资源见 ../nextora-child-themes/SKILL.md。
要加载的参考文档
references/templates-and-patterns.md— 包含真实文件名的模板层级、部件所有权和覆盖规则、模式头部和分类约定、隐藏模式加薄模板配方、查询组合和清理辅助函数、文件系统与数据库自定义、已观察到的缺陷以及下游 WordPress 验收步骤。在步骤 3 之前加载。source-map.md— 其中每个锚点的来源。quality-gates.md— 决定组合是否完成的门禁。
本地文件优先级高于这些参考文档中引用的任何值。
有序工作流
1. 解析主题根目录并读取本地表层
父主题是模板目录,当前活动主题是样式表目录:
get_template_directory(); // 父主题根目录
get_stylesheet_directory(); // 当前活动主题根目录(存在子主题时为子主题)
按此顺序读取:theme.json (customTemplates, templateParts)、templates/、parts/、patterns/、目标的 blocks/*/block.json 名称,以及 inc/ 中的查询或模板辅助函数。子主题对模板或部件的副本会覆盖父主题中同名的文件,因此已存在的内容决定了大部分答案。
2. 在组合任何内容前查找已存在的内容
复用优于创新,按此顺序:
- 已存在的模式,恰好就是该区块。
- 已存在的块(父主题的
nextora/*或子主题自己的),恰好渲染该区块。 - 由已存在块组成的新子主题模式。
- 一个组装这些模式的薄模板。
- 一个子主题部件覆盖 — 仅用于子主题真正拥有的表层。
- 一个新块 — 仅当所需行为或编辑结构无法由任何现有块表达时。
永远不要将模拟文章作为生产内容发布,也不要克隆父主题的联系表单后端:父主题已经提供了 nextora/contact-form 块,示例的联系页面将其组合在子主题的包装组内。
3. 将组合放在正确的模板中
应用 references/templates-and-patterns.md 中的层级:
front-page.html存在时控制首页;home.html是文章索引,不是首页的同义词;index.html是回退。- 归档、单页、搜索和特定页面模板优先于索引回退。
theme.jsoncustomTemplates中声明的名称必须在声明它的主题中有一个匹配的templates/<name>.html。
读取主题自己的 templates/ 列表,而不是猜测文件名:父主题提供 front-page、home、index、archive、single、search、page、page-full-width、about-us、contact-us、frequently-asked-questions、theme-terms-conditions、theme-privacy-policy、404;示例子主题提供其自己的一组不同名称。
4. 决定部件所有权,然后引用部件
一个 wp:template-part 引用首先解析 样式表 目录,因此子主题的 parts/header.html 会在所有使用的地方替换父主题的页眉。
- 如果子主题没有理由拥有页眉/页脚,则保留父主题的页眉/页脚:不要添加复制的部件。
- 如果子主题拥有一个部件,给它一个子主题拥有的主体,并在引用中说明;不要留下指向父主题副本的
theme属性。 - 示例子主题的
parts/header.html和parts/footer.html各是一个块引用(nextsaas/site-header、nextsaas/site-footer);父主题的页眉部件组合了nextora/scrolling-promotion和nextora/header。 - 源代码中的引用语法在子主题中是
{"slug":"header","tagName":"div"},在父主题中是{"slug":"header","tagName":"header","area":"header"}。匹配目标自己的约定;永远不要硬编码文件系统路径。
5. 将模式编写为带有真实头部的 PHP 文件
模式位于 patterns/*.php。它们的注册来自文件头部,而不是来自 register_block_pattern() 调用 — 两个源主题都没有调用它;两者都仅在 PHP 中注册 分类。必需的头部字段和别名规则在 references/templates-and-patterns.md 中:
Title、Slug: <child-slug>/<pattern-slug>(唯一)、Categories和说明何时使用它的Description。- 模式主体是编辑器插入的序列化块标记,从头部注释的
*/之后开始。 - 它必须可解析,仅使用已注册的块,并且在插入后保持可编辑。
6. 为全页组合赋予唯一权限
对于新的全页组合,将区块列表放在一个隐藏的文件系统模式中 — 头部的 Inserter: no — 并从薄模板中引用它:
<!-- wp:template-part {"slug":"header","tagName":"div"} /-->
<!-- wp:pattern {"slug":"nextfolio/page-landing"} /-->
<!-- wp:template-part {"slug":"footer","tagName":"div"} /-->
不要也把区块列表重复到模板中。示例当前在两个地方(patterns/page-home.php 和 templates/front-page.html)保存了相同的列表,而父主题的模板内联了带有 metadata.patternName 的模式标记;这种重复正是此规则为新工作所取代的。当仅编辑现有块时,保留现有的重复 — 仅在区块内容实际改变时才更新其他副本。
7. 使用核心块和显式上下文组合查询
- 归档、文章索引、搜索和文章详情委托给带有
"inherit":true的wp:query,因此主查询提供上下文;示例的index.html、home.html、archive.html和search.html都这样做。 - 从
core/post-template加上core/post-*块构建循环,添加wp:query-pagination,并始终提供wp:query-no-results。 - 使用
wp:query-title、core/post-title、core/post-content、core/comments+core/comment-template+wp:comments-pagination+wp:post-comments-form作为单篇文章表层,而不是经典循环。 - 启动其 自己 循环的块传递经过清理的属性:复用子主题的
inc/blocks/query.php辅助函数(如果存在),否则将页面大小限制在允许值范围内,并针对允许值验证文章类型、分类法和术语。预编译 SQL 不能替代该验证。
8. 保持 theme.json 声明准确
仅为主题拥有的表层声明 customTemplates 和 templateParts 条目,且仅用于不是核心模板的名称。关于示例中观察到的重复声明以及新工作的规则,请参阅 references/templates-and-patterns.md。
9. 考虑站点编辑器
文件系统模板和部件可能被站点编辑器中保存的数据库自定义所掩盖。如果文件编辑未改变前端,则在 touch 文件前查找保存的模板或样式。切勿静默覆盖真实站点的自定义;仅查看或重置可丢弃环境。
10. 在运行的站点上验证
在前端解析每个模板和部件,确认模式插入并保持可编辑,确认所需的 WordPress 最低版本和当前支持的版本,并运行 references/templates-and-patterns.md 中的浏览器步骤。将任何未实际测试的内容标记为未验证。
完成检查
- 每个使用的模板和部件都解析到预期的主题;没有错误的
theme属性将父主题部件固定到子主题模板。 - 没有不必要的新块,没有经典的 PHP 页面模板,没有 mock 生产内容。
- 新的全页组合:隐藏模式中的唯一权限,从薄模板引用;没有重复的区块列表。
- 模式可解析,使用已注册的块,保持唯一的别名,其分类是主题在 PHP 中注册的类别。
- 查询循环使用显式上下文、经过清理的属性和无结果状态。
theme.json仅声明拥有的、非核心的模板名称。- 应用了
quality-gates.md,包括其组合验收部分。
边界
仅限 Markdown 指令:没有运行时脚本、生成器、复制的主题树或安装程序,也不编辑父主题或示例子主题。父主题的模式库和示例的组合是供读取的证据,而不是要复制的文件。