Halo 主题布局契约

适用范围:当前适配 Halo 2.26.0 及以上版本的言答Issue。旧版插件的界面与构建方式可能不同。

Halo 2.26.0 引入 templates/layout.html 的 html(head, content) 契约。插件的四个入口页面均使用这个契约。主题提供契约时,插件内容进入主题布局;主题缺少契约时,由 Halo 的内置布局兜底。添加或修改布局后,需要在 Halo Console 重载主题;Halo 会在安装、更新或重载主题时检测契约,并在主题状态 status.pageLayout 中记录 SUPPORTED/MISSING/INVALID。仅保存新文件不一定刷新该状态。如果重载后仍读取旧模板,再清理该主题的模板缓存(管理员 API:PUT /apis/api.console.halo.run/v1alpha1/themes/{name}/invalidate-cache)。

在主题中添加 templates/layout.html,下面是可以独立使用的最小版本。实际主题可把 header/footer 换成自己的片段,并在 head 中加载自己的样式:

<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org"
      th:lang="${#locale.toLanguageTag}"
      th:fragment="html(head, content)">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title th:if="${head == null}" th:text="${site.title}"></title>
    <th:block th:if="${head != null}">
        <th:block th:replace="${head}" />
    </th:block>
</head>
<body>
    <header><a href="/" th:text="${site.title}"></a></header>
    <main><th:block th:replace="${content}" /></main>
    <footer th:text="${site.title}"></footer>
    <halo:footer />
</body>
</html>

插件提供最终的 <title>,主题收到非空 head 时不要再输出另一个标题。正文片段使用 <section>,可以安全放进主题的 <main>。请保留 <halo:footer />。

主题需要判断当前插件页面时,可使用 _templateId,例如:

<main th:classappend="${_templateId == 'plugin:PluginIssues:issues'} ? 'issue-list-page'">
    <th:block th:replace="${content}" />
</main>

稳定标识有 plugin:PluginIssues:subject、plugin:PluginIssues:issues、plugin:PluginIssues:issue、plugin:PluginIssues:newIssue。

相关文档

页面覆盖与公共片段

Halo 官方布局契约