Gridea Pro 模板开发指南
Gridea Pro 是一个简洁的静态博客写作客户端。支持文章、闪念、分类、标签、评论管理 —— 让你专注于内容创作本身。
一、目录结构
主题目录/
├── config.json # 主题配置文件(必需)
├── assets/
│ ├── styles/ # 样式目录
│ │ └── main.css # 主样式文件
│ ├── scripts/ # 脚本目录
│ │ └── main.js # 主脚本文件
│ └── media/ # 媒体资源目录
│ └── preview.png # 主题预览图(推荐)
── templates/ # 模板文件目录(必需)
├── includes/ # 公共模板片段
│ ├── head.ejs # 页面头部
│ ├── sidebar.ejs # 侧边栏(可选)
│ ├── header.ejs # 页面头部导航(可选)
│ └── footer.ejs # 页脚
├── index.ejs # 首页(必需)
├── post.ejs # 文章详情页(必需)
├── tags.ejs # 标签云页(必需)
├── tag.ejs # 标签文章列表页(必需)
├── archives.ejs # 归档页(必需)
├── blog.ejs # 博客列表页(可选)
├── about.ejs # 关于页(可选)
├── links.ejs # 友情链接页(可选)
├── memos.ejs # 闪念页(可选)
└── 404.ejs # 404错误页(可选)
二、config.json 配置
{
"name": "主题名称",
"version": "1.0.0",
"author": "作者",
"description": "主题描述",
"engine": "ejs",
"templateEngine": "ejs",
"repository": "",
"customConfig": [
{
"name": "配置项名称",
"label": "显示名称",
"group": "分组名称",
"type": "input | textarea | select | picture-upload | links",
"value": "默认值",
"options": [
{"label": "选项1", "value": "value1"},
{"label": "选项2", "value": "value2"}
],
"note": "配置说明"
}
]
}
配置项类型
| 类型 |
说明 |
| input |
单行文本输入 |
| textarea |
多行文本输入 |
| select |
下拉选择 |
| picture-upload |
图片上传 |
| links |
友情链接列表 |
三、模板引擎(EJS)
基本语法
<%= variable %> <!-- 输出变量(转义) -->
<%- variable %> <!-- 输出变量(不转义,用于HTML) -->
<% code %> <!-- 执行JavaScript代码 -->
<% if (condition) { %> <!-- 条件判断 -->
<p>true</p>
<% } else { %>
<p>false</p>
<% } %>
<% array.forEach(function(item) { %>
<p><%= item.name %></p>
<% }); %>
<%- include('./includes/header') %> <!-- 引入模板文件 -->
引入模板文件
<%- include('./includes/head', { siteTitle: '页面标题' }) %>
<%- include('./includes/sidebar') %>
<%- include('./includes/footer') %>
四、全局变量
site 对象
| 变量 |
说明 |
示例 |
site.customConfig |
主题自定义配置 |
site.customConfig.siteLogo |
site.customConfig.github |
GitHub链接 |
完整URL |
site.customConfig.twitter |
Twitter链接 |
完整URL |
site.customConfig.weibo |
微博链接 |
完整URL |
site.customConfig.weixin |
微信链接 |
完整URL |
site.customConfig.siteLogo |
站点Logo/头像 |
图片URL |
site.customConfig.avatar |
头像 |
图片URL |
site.customConfig.footerInfo |
页脚信息 |
HTML |
site.customConfig.favicon |
站点图标 |
图片URL |
site.customConfig.accentColor |
主题强调色 |
#667eea |
site.customConfig.accentColor2 |
主题强调色2 |
#764ba2 |
site.customConfig.author |
作者名称 |
文本 |
site.customConfig.links |
友情链接列表 |
数组 |
site.customConfig.customCss |
自定义CSS |
CSS代码 |
site.customConfig.customJs |
自定义JavaScript |
JS代码 |
themeConfig 对象
| 变量 |
说明 |
themeConfig.siteName |
站点名称 |
themeConfig.siteDescription |
站点描述 |
themeConfig.domain |
站点域名 |
themeConfig.footerInfo |
页脚信息 |
其他全局变量
| 变量 |
说明 |
类型 |
menus |
导航菜单 |
数组 |
posts |
文章列表 |
数组 |
tags |
标签列表 |
数组 |
memos |
闪念列表 |
数组 |
pagination |
分页对象 |
对象 |
link |
友链对象 |
对象 |
五、文章对象(post)
| 变量 |
说明 |
post.title |
文章标题 |
post.link |
文章链接 |
post.content |
文章内容(HTML) |
post.brief |
文章摘要 |
post.summary |
文章摘要 |
post.dateFormat |
格式化日期 |
post.feature |
特色图片URL |
post.tags |
文章标签数组 |
post.prevPost |
上一篇文章 |
post.nextPost |
下一篇文章 |
post.stats |
文章统计信息 |
post.stats.text |
阅读量文本 |
六、分页对象(pagination)
| 变量 |
说明 |
pagination.prev |
上一页链接 |
pagination.next |
下一页链接 |
七、标签对象(tag)
| 变量 |
说明 |
tag.name |
标签名称 |
tag.link |
标签链接 |
tag.count |
文章数量 |
八、导航菜单(menus)
<% menus.forEach(function(menu) { %>
<a href="<%= menu.link %>"><%= menu.name %></a>
<% }); %>
九、友情链接
<% var _links = site.customConfig.links || []; %>
<% _links.forEach(function(link) { %>
<a href="<%= link.url || link.siteLink %>">
<%= link.name || link.siteName %>
</a>
<% }); %>
十、常用模板结构
标准页面结构
<%- include('./includes/head', { siteTitle: '页面标题' }) %>
<body>
<div class="container">
<%- include('./includes/sidebar') %>
<main class="main-content">
<!-- 页面内容 -->
<%- include('./includes/footer') %>
</main>
</div>
</body>
</html>
文章列表
<% posts.forEach(function(post) { %>
<article>
<h2><a href="<%= post.link %>"><%= post.title %></a></h2>
<p><%= post.brief %></p>
<span><%= post.dateFormat %></span>
</article>
<% }); %>
<% if (typeof pagination !== 'undefined' && pagination) { %>
<% if (pagination.prev) { %>
<a href="<%= pagination.prev %>">上一页</a>
<% } %>
<% if (pagination.next) { %>
<a href="<%= pagination.next %>">下一页</a>
<% } %>
<% } %>
文章详情
<h1><%= post.title %></h1>
<div class="meta">
<span><%= post.dateFormat %></span>
<% post.tags.forEach(function(tag) { %>
<a href="<%= tag.link %>"><%= tag.name %></a>
<% }); %>
</div>
<article>
<%- post.content %>
</article>
<nav>
<% if (post.prevPost) { %>
<a href="<%= post.prevPost.link %>"><%= post.prevPost.title %></a>
<% } %>
<% if (post.nextPost) { %>
<a href="<%= post.nextPost.link %>"><%= post.nextPost.title %></a>
<% } %>
</nav>
十一、主题预览图
在 assets/media/ 目录下放置 preview.png 文件,作为主题预览图。
十二、样式和脚本
CSS 样式
- 放置在
assets/styles/ 目录
- 生成时自动映射到
/styles/ 路径
- 推荐使用 CSS 变量定义主题色
:root {
--primary: #667eea;
--primary-dark: #764ba2;
}
JavaScript 脚本
- 放置在
assets/scripts/ 目录
- 生成时自动映射到
/scripts/ 路径
十三、常用技巧
1. 条件渲染
<% if (site.customConfig.siteLogo) { %>
<img src="<%= site.customConfig.siteLogo %>">
<% } else { %>
<img src="默认头像URL">
<% } %>
2. 默认值回退
<%= post.brief || post.summary || '' %>
3. 自定义 CSS/JS 注入
<% if (site.customConfig.customCss) { %>
<%- '<style>' + site.customConfig.customCss + '<\/style>' %>
<% } %>
<% if (site.customConfig.customJs) { %>
<%- '<script>' + site.customConfig.customJs + '<\/script>' %>
<% } %>
4. 响应式设计
@media (max-width: 1024px) {
/* 平板样式 */
}
@media (max-width: 768px) {
/* 手机样式 */
}
十四、开发流程
- 在
themes/ 目录下创建主题文件夹
- 创建
config.json 配置文件
- 创建
templates/ 目录和模板文件
- 创建
assets/ 目录和样式/脚本文件
- 在 Gridea Pro 中选择该主题
- 修改模板和样式,实时预览
- 点击发布生成静态网站
十五、注意事项
- 模板文件必须使用
.ejs 扩展名
config.json 的 engine 和 templateEngine 必须设置为 ejs
- 样式文件放在
assets/styles/ 目录,不是 assets/css/
- 友链数据通过
site.customConfig.links 访问
- 文章列表通过
posts 变量访问
- 标签列表通过
tags 变量访问
- 分页对象通过
pagination 变量访问
- 使用
<%- %> 输出 HTML 内容,使用 <%= %> 输出转义文本
评论区 (2)
发表评论
共有 2 条评论
教程很详尽,不过个人觉得config.json里要是能加个“color”类型就好了,很多主题需要自定义配色,用input的话用户容易输错格式。
文档写得很清晰,但建议在config.json配置项类型中增加一个“color-picker”,毕竟现在很多主题都支持自定义配色,用input输十六进制码不太友好。