diff --git a/assets/mock-data.json b/assets/mock-data.json index 3d9e323..2802ce1 100644 --- a/assets/mock-data.json +++ b/assets/mock-data.json @@ -226,16 +226,14 @@ "post": null, "links": [ { - "id": "link-1", - "name": "Gridea Pro", - "url": "https://github.com/Gridea-Pro/gridea-pro", + "siteName": "Gridea Pro", + "siteLink": "https://github.com/Gridea-Pro/gridea-pro", "description": "基于 Wails 的桌面静态博客写作客户端", "avatar": "https://avatars.githubusercontent.com/u/0" }, { - "id": "link-2", - "name": "某友链示例", - "url": "https://example.com", + "siteName": "某友链示例", + "siteLink": "https://example.com", "description": "一个简短描述", "avatar": "" } diff --git a/references/template-variables.md b/references/template-variables.md index 375921c..9d1c21f 100644 --- a/references/template-variables.md +++ b/references/template-variables.md @@ -10,8 +10,9 @@ 4. [Menu 对象](#menu-对象) 5. [Pagination 对象](#pagination-对象) 6. [Memo 对象](#memo-对象) -7. [各页面可用变量表](#各页面可用变量表) -8. [三引擎语法对照表](#三引擎语法对照表) +7. [Link 对象](#link-对象) +8. [各页面可用变量表](#各页面可用变量表) +9. [三引擎语法对照表](#三引擎语法对照表) --- @@ -121,10 +122,60 @@ --- +## Link 对象 + +友链条目对象。Gridea Pro 把全部友链**同时**暴露为两条路径,两者**指向同一份数据**: + +- `links` —— 顶层变量,所有页面都可用 +- `theme_config.links` —— 经由 `customConfig.links` 合并到 `theme_config` 上,所有页面都可用 + +> ⚠️ 字段名是从 domain.Link 注入时**重命名**过的(参见 `backend/internal/engine/data_builder.go`)。模板中**不能**写 `link.name` / `link.url`,必须用下表的字段名。 + +| 字段 | 类型 | 说明 | +|------|------|------| +| `link.siteName` | string | 站点名称(来源于 `domain.Link.Name`) | +| `link.siteLink` | string | 站点 URL(来源于 `domain.Link.Url`) | +| `link.description` | string | 站点描述,可能为空字符串 | +| `link.avatar` | string | 站点头像 URL,可能为空字符串 | + +### 友链遍历示例 + +```jinja2 +{# 推荐写法 1:直接遍历顶层 links #} +{% if links and links|length > 0 %} + {% for link in links %} + + {% if link.avatar %} + {{ link.siteName }} + {% endif %} +

{{ link.siteName }}

+ {% if link.description %}

{{ link.description }}

{% endif %} +
+ {% endfor %} +{% endif %} + +{# 写法 2:从 theme_config.links 取,效果完全等同 #} +{% for link in theme_config.links %}...{% endfor %} +``` + +### 易错变量速查(友链专用) + +| 错误写法 | 正确写法 | 原因 | +|----------|----------|------| +| `link.name` | `link.siteName` | 注入时被重命名 | +| `link.url` | `link.siteLink` | 注入时被重命名 | +| `link.title` | `link.siteName` | 没有 title 字段 | +| `link.desc` | `link.description` | 没有缩写 | +| `link.icon` | `link.avatar` | 没有 icon 字段 | + +--- + ## 各页面可用变量表 每个模板文件可访问的变量不同,在模板中使用变量前务必确认该页面是否有权访问: +> 注:`links` 变量(同时暴露为 `theme_config.links`)实际上**所有页面**都能访问 —— 这是 Gridea Pro 的设计,方便你在 sidebar / footer 等公共组件里展示友链。下表只在"主要消费方"那一行特别标出。 + | 页面模板 | 可用变量 | |----------|----------| | `index.html` | config, theme_config, menus, posts, tags, pagination, now | @@ -133,7 +184,7 @@ | `tag.html` | config, theme_config, menus, posts, tag, current_tag, tags, now | | `tags.html` | config, theme_config, menus, tags, now | | `about.html` | config, theme_config, menus, tags, now | -| `links.html` | config, theme_config, menus, tags, links, now | +| `links.html` | config, theme_config, menus, tags, **links**, now | | `memos.html` | config, theme_config, menus, memos, tags, now | | `blog.html` | config, theme_config, menus, posts, tags, pagination, now | | `404.html` | config, theme_config, menus, now | @@ -454,6 +505,10 @@ | `config.url` | `config.domain` | 域名字段为 `domain` | | `tag.slug` | `tag.link` | 标签链接字段为 `link` | | `tag.posts_count` | `tag.count` | 标签文章数字段为 `count` | +| `link.name` | `link.siteName` | 友链注入时被重命名(来源 `domain.Link.Name`) | +| `link.url` | `link.siteLink` | 友链注入时被重命名(来源 `domain.Link.Url`) | +| `link.desc` | `link.description` | 友链描述字段为 `description`,无缩写 | +| `link.icon` | `link.avatar` | 友链头像字段为 `avatar`,没有 `icon` | | `theme_config` 写成 `themeConfig` | `theme_config` | 模板中使用下划线命名 | | `pagination.previous` | `pagination.prev` | 上一页字段简写为 `prev` | | `{{ value\|default("x") }}` | `{{ value\|default:"x" }}` | Pongo2 过滤器参数用冒号 | diff --git a/scripts/render_test.py b/scripts/render_test.py index 8471aba..67dc248 100644 --- a/scripts/render_test.py +++ b/scripts/render_test.py @@ -172,13 +172,23 @@ def build_context(mock_data, template_name): Different templates need different context variables. """ # Base context available to all templates + # 复刻 Gridea Pro jinja2_renderer.buildContext 的友链注入: + # 真实运行时把 customConfig.links 同时暴露为顶层 `links` 变量和 `theme_config.links`, + # 主题既可以写 {% for l in links %} 也可以写 {% for l in theme_config.links %}。 + # 字段为 siteName / siteLink / description / avatar(见 backend/internal/engine/data_builder.go)。 + links_data = mock_data.get("links", mock_data.get("friends", [])) + theme_config = dict(mock_data.get("theme_config", {})) # 浅拷贝,避免污染 mock_data + if "links" not in theme_config: + theme_config["links"] = links_data + ctx = { "config": mock_data.get("config", {}), - "theme_config": mock_data.get("theme_config", {}), + "theme_config": theme_config, "menus": mock_data.get("menus", []), "tags": mock_data.get("tags", []), "posts": mock_data.get("posts", []), "memos": mock_data.get("memos", []), + "links": links_data, "pagination": mock_data.get("pagination", {"prev": "", "next": ""}), "now": mock_data.get("now", "2026-02-28T15:30:00+08:00"), } @@ -223,7 +233,8 @@ def build_context(mock_data, template_name): pass # config is enough elif basename == "links": - ctx["links"] = mock_data.get("links", mock_data.get("friends", [])) + # links / theme_config.links 已在 base ctx 中注入,无需特殊处理 + pass elif basename == "memos": pass # memos already in ctx