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。