feat: 二级导航、豆瓣适配页、可关闭署名与全站统计

- 一级菜单子项渲染为下拉二级导航(移动端嵌套展开)
- 新增 douban.html 豆瓣收藏适配页(plugin-douban,分栏展示书影音)
- 页脚署名改为可配置名称且可关闭(默认「暖心向阳335」)
- 页脚全站数据统计可配置(文章/分类/标签/评论/访问/字数)
- 文章卡片字数+阅读时长增加 show_word_count 开关
- 修复 SinglePage 描述取用错误(spec.description -> status.excerpt)导致的 /weread、/subscriptions 白屏
- 修复 post-meta 静态类调用被禁(BigInteger.valueOf)导致的首页 500
- 文章分类链接增加间距

Co-Authored-By: WorkBuddy <noreply@workbuddy.ai>
This commit is contained in:
2026-09-28 20:40:21 +08:00
co-authored by WorkBuddy
parent 6b8d9ee338
commit db368f885e
11 changed files with 415 additions and 32 deletions
+12
View File
@@ -14,6 +14,10 @@
- 文章页结构化数据(Schema.org `BlogPosting` JSON-LD)与社交分享标签(canonical / Open Graph / Twitter Card),均可在主题设置中关闭 - 文章页结构化数据(Schema.org `BlogPosting` JSON-LD)与社交分享标签(canonical / Open Graph / Twitter Card),均可在主题设置中关闭
- 内置搜索按钮(依赖官方 `PluginSearchWidget` 插件,未安装则不显示) - 内置搜索按钮(依赖官方 `PluginSearchWidget` 插件,未安装则不显示)
- 阅读进度条、代码块复制、相对时间、回到顶部、移动端菜单等交互 - 阅读进度条、代码块复制、相对时间、回到顶部、移动端菜单等交互
- **二级导航**:菜单项的子项自动渲染为下拉菜单(桌面端 hover/focus 展开,移动端嵌套缩进展开)
- **页脚可关闭的主题署名**:默认「Theme by 暖心向阳335」,可在设置中修改名称或整体关闭
- **页脚全站数据统计**:文章 / 分类 / 标签 / 评论 / 访问量 / 字数,可按项开关,整体可关闭
- **文章卡片字数 + 阅读时长**:可在设置中关闭(需 `halo-plugin-extra-api` 提供数据)
- 多语言:`i18n/default.properties`(回退)+ `i18n/zh_CN.properties` - 多语言:`i18n/default.properties`(回退)+ `i18n/zh_CN.properties`
- 提供 `layout.html` 布局契约,供使用布局契约的插件页面复用主题导航 / 页脚 / 暗色样式 - 提供 `layout.html` 布局契约,供使用布局契约的插件页面复用主题导航 / 页脚 / 暗色样式
@@ -26,6 +30,7 @@
- **plugin-links**:`/links` 友链页;友链申请表单已**直接内嵌**在友链页底部(点击「申请友链」展开,调用插件公共 REST API,含图形验证码);并额外提供 - **plugin-links**:`/links` 友链页;友链申请表单已**直接内嵌**在友链页底部(点击「申请友链」展开,调用插件公共 REST API,含图形验证码);并额外提供
- `links-subscribe.html`:RSS 订阅动态聚合页(使用 `linkFeedFinder`) - `links-subscribe.html`:RSS 订阅动态聚合页(使用 `linkFeedFinder`)
- **halo-weread-plugin**:`weread.html` 微信读书书架页(前端拉取插件 `/shelf-html` 并注入) - **halo-weread-plugin**:`weread.html` 微信读书书架页(前端拉取插件 `/shelf-html` 并注入)
- **plugin-douban**:`douban.html` 豆瓣收藏页(按「读过 / 在读 / 看过 / 在追」分栏展示书影音,使用 `doubanFinder.getMovies(...)`;未安装插件时显示提示)。在控制台新建单页并选择「豆瓣页面」模板即可启用
- **留言板**:`page_guestbook.html` 以评论区作为留言板的单页模板 - **留言板**:`page_guestbook.html` 以评论区作为留言板的单页模板
- **plugin-extra-api**:API 扩展包(无独立页面),主题已适配其 shiki 代码高亮与暗色样式;并在文章卡片 / 详情页展示**字数 + 阅读时长**、归档页展示**全站总字数**、瞬间页展示**单条字数**(通过 `extraApiStatsFinder`,插件未安装时自动隐藏) - **plugin-extra-api**:API 扩展包(无独立页面),主题已适配其 shiki 代码高亮与暗色样式;并在文章卡片 / 详情页展示**字数 + 阅读时长**、归档页展示**全站总字数**、瞬间页展示**单条字数**(通过 `extraApiStatsFinder`,插件未安装时自动隐藏)
@@ -50,6 +55,7 @@ src/ 源码目录(在此编辑)
├── js/post.ts 文章页脚本(代码复制 / 阅读进度) ├── js/post.ts 文章页脚本(代码复制 / 阅读进度)
├── index.html post.html page.html page_about.html ├── index.html post.html page.html page_about.html
├── archives.html category.html tag.html categories.html tags.html author.html ├── archives.html category.html tag.html categories.html tags.html author.html
├── weread.html douban.html links-subscribe.html page_guestbook.html
└── i18n/ 多语言消息 └── i18n/ 多语言消息
theme.yaml 主题元数据(必填) theme.yaml 主题元数据(必填)
settings.yaml 控制台主题设置表单 settings.yaml 控制台主题设置表单
@@ -81,12 +87,18 @@ pnpm check # 格式化 + Lint 修复
| ------- | ------------------ | -------------------------------------------- | | ------- | ------------------ | -------------------------------------------- |
| basic | color_scheme | 默认配色:跟随系统 / 浅色 / 深色 | | basic | color_scheme | 默认配色:跟随系统 / 浅色 / 深色 |
| basic | footer_copyright | 页脚自定义版权(支持 HTML,留空不显示) | | basic | footer_copyright | 页脚自定义版权(支持 HTML,留空不显示) |
| basic | show_theme_credit | 页脚是否显示「Theme by」署名(默认开) |
| basic | theme_credit_text | 署名名称(默认「暖心向阳335」) |
| basic | show_word_count | 文章卡片是否显示字数与阅读时长(需 extra-api)|
| featured| enable | 首页是否展示置顶文章 | | featured| enable | 首页是否展示置顶文章 |
| about | avatar / bio / github_url / twitter_url / contact_email | 关于页(自定义模板 `page_about.html`)内容 | | about | avatar / bio / github_url / twitter_url / contact_email | 关于页(自定义模板 `page_about.html`)内容 |
| seo | enable_metadata | 输出 canonical / Open Graph / Twitter Card | | seo | enable_metadata | 输出 canonical / Open Graph / Twitter Card |
| seo | enable_structured_data | 输出文章页 BlogPosting JSON-LD | | seo | enable_structured_data | 输出文章页 BlogPosting JSON-LD |
| footer | icp_number / icp_url | ICP 备案号与查询链接(默认工信部备案管理系统) | | footer | icp_number / icp_url | ICP 备案号与查询链接(默认工信部备案管理系统) |
| footer | police_number / police_url | 公网安备号与查询链接(默认全国互联网安全管理服务平台) | | footer | police_number / police_url | 公网安备号与查询链接(默认全国互联网安全管理服务平台) |
| stats | enable | 页脚是否显示全站数据统计(默认关) |
| stats | show_posts / show_categories / show_tags / show_comments / show_visits | 各项统计的显隐开关 |
| stats | show_words | 全站总字数(需 extra-api 插件,默认开) |
## 约定与说明 ## 约定与说明
+7
View File
@@ -40,3 +40,10 @@ links.apply=Apply for link
links.apply_sent=Application submitted, awaiting review. links.apply_sent=Application submitted, awaiting review.
links.apply_failed=Submission failed, please check and retry. links.apply_failed=Submission failed, please check and retry.
links.apply_captcha_failed=Captcha failed to load, please refresh. links.apply_captcha_failed=Captcha failed to load, please refresh.
stats.posts={0} posts
stats.categories={0} categories
stats.tags={0} tags
stats.comments={0} comments
stats.visits={0} visits
stats.words={0} words
douban.plugin_required=Douban plugin (plugin-douban) not detected. Please install and enable it, then set your Douban ID in the plugin settings.
+7
View File
@@ -40,3 +40,10 @@ links.apply=申请友链
links.apply_sent=申请已提交,等待管理员审核。 links.apply_sent=申请已提交,等待管理员审核。
links.apply_failed=提交失败,请检查信息后重试。 links.apply_failed=提交失败,请检查信息后重试。
links.apply_captcha_failed=验证码加载失败,请刷新页面重试。 links.apply_captcha_failed=验证码加载失败,请刷新页面重试。
stats.posts={0} 篇文章
stats.categories={0} 个分类
stats.tags={0} 个标签
stats.comments={0} 条评论
stats.visits={0} 次访问
stats.words={0} 字
douban.plugin_required=未检测到豆瓣插件(plugin-douban),请安装并启用后在插件设置中填写豆瓣 ID。
+48
View File
@@ -25,6 +25,22 @@ spec:
value: "" value: ""
placeholder: 支持编写 HTML,留空则不显示 placeholder: 支持编写 HTML,留空则不显示
help: 显示在页脚的自定义版权信息 help: 显示在页脚的自定义版权信息
- $formkit: checkbox
name: show_theme_credit
label: 显示主题署名
value: true
help: 在页脚显示「Theme by」署名;关闭则不显示
- $formkit: text
name: theme_credit_text
label: 署名名称
value: "暖心向阳335"
placeholder: 显示在「Theme by」之后的名称
help: 页脚主题署名的展示名称
- $formkit: checkbox
name: show_word_count
label: 文章卡片显示字数
value: true
help: 在文章卡片与置顶文章上展示字数及阅读时长(需 extra-api 插件提供数据)
- group: featured - group: featured
label: 置顶文章 label: 置顶文章
formSchema: formSchema:
@@ -99,3 +115,35 @@ spec:
label: 公网安备查询链接 label: 公网安备查询链接
value: "https://beian.mps.gov.cn" value: "https://beian.mps.gov.cn"
help: 点击公网安备号跳转的地址,默认全国互联网安全管理服务平台 help: 点击公网安备号跳转的地址,默认全国互联网安全管理服务平台
- group: stats
label: 全站数据
formSchema:
- $formkit: checkbox
name: enable
label: 显示全站数据统计
value: false
help: 在页脚展示站点文章、分类、评论、访问量与字数等统计
- $formkit: checkbox
name: show_posts
label: 文章数
value: true
- $formkit: checkbox
name: show_categories
label: 分类数
value: true
- $formkit: checkbox
name: show_tags
label: 标签数
value: false
- $formkit: checkbox
name: show_comments
label: 评论数
value: true
- $formkit: checkbox
name: show_visits
label: 访问量
value: true
- $formkit: checkbox
name: show_words
label: 全站总字数(需 extra-api 插件)
value: true
+86 -1
View File
@@ -210,7 +210,7 @@ textarea {
flex: 1; flex: 1;
justify-content: center; justify-content: center;
flex-wrap: nowrap; flex-wrap: nowrap;
overflow-x: auto; overflow: visible;
-ms-overflow-style: none; -ms-overflow-style: none;
scrollbar-width: none; scrollbar-width: none;
} }
@@ -240,6 +240,62 @@ textarea {
font-weight: 500; font-weight: 500;
} }
/* 二级导航:带子菜单的项 */
.nav-item {
position: relative;
display: flex;
align-items: center;
}
.nav-has-children > .nav-link::after {
content: "";
display: inline-block;
width: 0;
height: 0;
margin-left: 0.3rem;
vertical-align: middle;
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 5px solid currentColor;
opacity: 0.6;
}
.nav-dropdown {
position: absolute;
top: calc(100% + 0.5rem);
left: 50%;
transform: translateX(-50%);
min-width: 11rem;
display: none;
flex-direction: column;
padding: 0.5rem;
background: var(--color-bg);
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
box-shadow: var(--shadow, 0 12px 32px rgba(0, 0, 0, 0.12));
z-index: 50;
}
.nav-has-children:hover > .nav-dropdown,
.nav-has-children:focus-within > .nav-dropdown {
display: flex;
}
.nav-dropdown-link {
padding: 0.5rem 0.75rem;
border-radius: var(--radius-sm);
color: var(--color-text);
white-space: nowrap;
transition:
background-color var(--transition-fast),
color var(--transition-fast);
}
.nav-dropdown-link:hover {
background: var(--color-bg-secondary);
color: var(--color-primary);
}
.header-actions { .header-actions {
display: flex; display: flex;
align-items: center; align-items: center;
@@ -326,6 +382,12 @@ textarea {
background-color: var(--color-bg-secondary); background-color: var(--color-bg-secondary);
} }
.mobile-nav-sub {
padding-left: calc(var(--spacing-md) + 1rem);
font-size: 0.9rem;
opacity: 0.85;
}
/* ======================================== /* ========================================
主要内容区域 主要内容区域
======================================== */ ======================================== */
@@ -449,6 +511,9 @@ textarea {
.post-category { .post-category {
color: var(--color-text-secondary); color: var(--color-text-secondary);
display: inline-flex;
flex-wrap: wrap;
gap: 0.4rem;
} }
.post-category a { .post-category a {
@@ -571,6 +636,12 @@ textarea {
color: var(--color-border); color: var(--color-border);
} }
.article-category {
display: inline-flex;
flex-wrap: wrap;
gap: 0.4rem;
}
.article-category a { .article-category a {
color: var(--color-text-muted); color: var(--color-text-muted);
} }
@@ -1136,6 +1207,20 @@ a.pagination-item:hover {
height: 0.95rem; height: 0.95rem;
} }
.footer-stats {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 0.35rem 1rem;
margin-top: var(--spacing-md);
font-size: 0.8rem;
color: var(--color-text-muted);
}
.footer-stat {
white-space: nowrap;
}
.post-words, .post-words,
.post-reading { .post-reading {
color: var(--color-text-muted); color: var(--color-text-muted);
+141
View File
@@ -0,0 +1,141 @@
<include src="partials/layout.html">
<template name="head">
<title
th:text="|${singlePage.spec.title} - ${site.title}|"
th:if="${singlePage != null}"
>
豆瓣
</title>
<style>
.douban-intro {
color: var(--color-text-secondary);
margin-bottom: 1.5rem;
line-height: 1.7;
}
.douban-section {
margin: 2rem 0;
}
.douban-section-title {
font-size: 1.15rem;
margin: 0 0 1rem;
padding-bottom: 0.5rem;
border-bottom: 1px solid var(--color-border);
}
.douban-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
gap: 1.25rem;
}
.douban-card {
display: block;
color: var(--color-text);
}
.douban-card:hover .douban-name {
color: var(--color-primary);
}
.douban-cover {
width: 100%;
aspect-ratio: 2 / 3;
object-fit: cover;
border-radius: var(--radius-md);
background: var(--color-bg-secondary);
}
.douban-name {
margin: 0.5rem 0 0;
font-size: 0.9rem;
font-weight: 600;
line-height: 1.4;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.douban-meta {
margin: 0.25rem 0 0;
font-size: 0.78rem;
color: var(--color-text-muted);
}
.douban-score {
color: var(--color-primary);
font-weight: 600;
margin-left: 0.4rem;
}
.douban-empty {
color: var(--color-text-muted);
padding: 2rem 0;
}
</style>
</template>
<div class="container">
<section class="douban">
<h1 th:text="${singlePage.spec.title}" th:if="${singlePage != null}">
豆瓣
</h1>
<p
class="douban-intro"
th:if="${singlePage.status?.excerpt != null}"
th:utext="${singlePage.status.excerpt}"
></p>
<th:block th:if="${pluginFinder.available('plugin-douban')}">
<th:block
th:with="collections=${{ {'type':'book','status':'done','label':'读过'}, {'type':'book','status':'doing','label':'在读'}, {'type':'movie','status':'done','label':'看过'}, {'type':'drama','status':'doing','label':'在追'} }}"
>
<th:block th:each="col : ${collections}">
<th:block
th:with="movies=${doubanFinder.getMovies(24, 0, col.type, col.status)}"
>
<div
class="douban-section"
th:if="${not #lists.isEmpty(movies)}"
>
<h2 class="douban-section-title" th:text="${col.label}">
读过
</h2>
<div class="douban-grid">
<a
th:each="m : ${movies}"
class="douban-card"
th:href="${m.spec.link}"
target="_blank"
rel="noopener noreferrer"
>
<img
class="douban-cover"
th:src="${m.spec.poster}"
th:alt="${m.spec.name}"
loading="lazy"
/>
<p class="douban-name" th:text="${m.spec.name}">名称</p>
<p class="douban-meta">
<span
th:if="${not #strings.isEmpty(m.spec.year)}"
th:text="${m.spec.year}"
>年份</span
>
<span
th:if="${not #strings.isEmpty(m.spec.douban_score)}"
class="douban-score"
th:text="'★ ' + ${m.spec.douban_score}"
>评分</span
>
</p>
</a>
</div>
</div>
</th:block>
</th:block>
</th:block>
</th:block>
<p
class="douban-empty"
th:if="${pluginFinder.available('plugin-douban') == false}"
th:text="#{douban.plugin_required}"
>
未检测到豆瓣插件
</p>
</section>
</div>
</include>
+2 -2
View File
@@ -41,8 +41,8 @@
<h1 th:text="${singlePage.spec.title}" th:if="${singlePage != null}">链接订阅</h1> <h1 th:text="${singlePage.spec.title}" th:if="${singlePage != null}">链接订阅</h1>
<p <p
class="feed-intro" class="feed-intro"
th:if="${singlePage.spec.description != null}" th:if="${singlePage.status?.excerpt != null}"
th:utext="${singlePage.spec.description}" th:utext="${singlePage.status.excerpt}"
></p> ></p>
<div <div
+13 -9
View File
@@ -23,17 +23,21 @@
>1 views</span >1 views</span
> >
</th:block> </th:block>
<th:block th:if="${pluginFinder.available('extra-api')}"> <th:block
th:if="${pluginFinder.available('extra-api') and theme.config?.basic?.show_word_count != false}"
>
<th:block th:with="wc=${extraApiStatsFinder.getPostWordCount({name: post.metadata.name})}"> <th:block th:with="wc=${extraApiStatsFinder.getPostWordCount({name: post.metadata.name})}">
<th:block th:if="${wc != null and wc > 0}"> <th:block th:if="${wc != null and wc > 0}">
<span class="post-meta-sep">·</span> <th:block th:with="rt=${(wc.longValue() + 399) / 400}">
<span class="post-words" th:text="#{post.words(${wc})}">字数</span> <span class="post-meta-sep">·</span>
<span class="post-meta-sep">·</span> <span class="post-words" th:text="#{post.words(${wc.longValue()})}">字数</span>
<span <span class="post-meta-sep">·</span>
class="post-reading" <span
th:text="#{post.reading_time(${#numbers.formatInteger((wc + 399).divide(java.math.BigInteger.valueOf(400)), 0)})}" class="post-reading"
>阅读时长</span th:text="#{post.reading_time(${rt})}"
> >阅读时长</span
>
</th:block>
</th:block> </th:block>
</th:block> </th:block>
</th:block> </th:block>
+93 -18
View File
@@ -58,13 +58,37 @@
>Home</a >Home</a
> >
<th:block th:if="${primaryMenu != null}"> <th:block th:if="${primaryMenu != null}">
<a <th:block th:each="item : ${primaryMenu.menuItems}">
th:each="item : ${primaryMenu.menuItems}" <th:block
th:href="@{${item.status.href}}" th:if="${not #lists.isEmpty(item.children)}"
th:text="${item.status.displayName}" >
th:target="${item.spec.target?.value}" <div class="nav-item nav-has-children">
class="nav-link" <a
></a> class="nav-link"
th:href="@{${item.status.href}}"
th:text="${item.status.displayName}"
th:target="${item.spec.target?.value}"
></a>
<div class="nav-dropdown">
<a
th:each="child : ${item.children}"
class="nav-dropdown-link"
th:href="@{${child.status.href}}"
th:text="${child.status.displayName}"
th:target="${child.spec.target?.value}"
></a>
</div>
</div>
</th:block>
<th:block th:unless="${not #lists.isEmpty(item.children)}">
<a
class="nav-link"
th:href="@{${item.status.href}}"
th:text="${item.status.displayName}"
th:target="${item.spec.target?.value}"
></a>
</th:block>
</th:block>
</th:block> </th:block>
</th:block> </th:block>
</nav> </nav>
@@ -153,13 +177,21 @@
>Home</a >Home</a
> >
<th:block th:if="${primaryMenu != null}"> <th:block th:if="${primaryMenu != null}">
<a <th:block th:each="item : ${primaryMenu.menuItems}">
th:each="item : ${primaryMenu.menuItems}" <a
th:href="@{${item.status.href}}" class="mobile-nav-link"
th:text="${item.status.displayName}" th:href="@{${item.status.href}}"
th:target="${item.spec.target?.value}" th:text="${item.status.displayName}"
class="mobile-nav-link" th:target="${item.spec.target?.value}"
></a> ></a>
<a
th:each="child : ${item.children}"
class="mobile-nav-link mobile-nav-sub"
th:href="@{${child.status.href}}"
th:text="${child.status.displayName}"
th:target="${child.spec.target?.value}"
></a>
</th:block>
</th:block> </th:block>
</th:block> </th:block>
</div> </div>
@@ -176,10 +208,11 @@
th:if="${not #strings.isEmpty(theme.config?.basic?.footer_copyright)}" th:if="${not #strings.isEmpty(theme.config?.basic?.footer_copyright)}"
th:utext="${theme.config.basic.footer_copyright}" th:utext="${theme.config.basic.footer_copyright}"
></div> ></div>
<p class="footer-theme"> <p
Theme by class="footer-theme"
<a href="https://kehua.me" target="_blank" rel="noopener">kehua</a> th:if="${theme.config?.basic?.show_theme_credit != false}"
</p> th:text="#{footer.theme(${theme.config?.basic?.theme_credit_text ?: '暖心向阳335'})}"
>Theme by kehua</p>
<div <div
class="footer-beian" class="footer-beian"
th:if="${not #strings.isEmpty(theme.config?.footer?.icp_number) or not #strings.isEmpty(theme.config?.footer?.police_number)}" th:if="${not #strings.isEmpty(theme.config?.footer?.icp_number) or not #strings.isEmpty(theme.config?.footer?.police_number)}"
@@ -209,6 +242,48 @@
<span th:text="${theme.config?.footer?.police_number}">公网安备</span> <span th:text="${theme.config?.footer?.police_number}">公网安备</span>
</a> </a>
</div> </div>
<div
class="footer-stats"
th:if="${theme.config?.stats?.enable}"
th:with="stats=${siteStatsFinder.getStats()}, tags=${tagFinder.listAll()}"
>
<span
class="footer-stat"
th:if="${theme.config?.stats?.show_posts}"
th:text="#{stats.posts(${stats.post})}"
>文章</span
>
<span
class="footer-stat"
th:if="${theme.config?.stats?.show_categories}"
th:text="#{stats.categories(${stats.category})}"
>分类</span
>
<span
class="footer-stat"
th:if="${theme.config?.stats?.show_tags and tags != null}"
th:text="#{stats.tags(${#lists.size(tags)})}"
>标签</span
>
<span
class="footer-stat"
th:if="${theme.config?.stats?.show_comments}"
th:text="#{stats.comments(${stats.comment})}"
>评论</span
>
<span
class="footer-stat"
th:if="${theme.config?.stats?.show_visits}"
th:text="#{stats.visits(${stats.visit})}"
>访问</span
>
<span
class="footer-stat"
th:if="${theme.config?.stats?.show_words and pluginFinder.available('extra-api')}"
th:text="#{stats.words(${extraApiStatsFinder.getPostWordCount()})}"
>字数</span
>
</div>
<halo:footer /> <halo:footer />
</div> </div>
</footer> </footer>
+2 -2
View File
@@ -29,8 +29,8 @@
<h1 th:text="${singlePage.spec.title}" th:if="${singlePage != null}">微信读书</h1> <h1 th:text="${singlePage.spec.title}" th:if="${singlePage != null}">微信读书</h1>
<p <p
class="weread-intro" class="weread-intro"
th:if="${singlePage.spec.description != null}" th:if="${singlePage.status?.excerpt != null}"
th:utext="${singlePage.spec.description}" th:utext="${singlePage.status.excerpt}"
></p> ></p>
<div class="weread-mount" id="wr-mount"> <div class="weread-mount" id="wr-mount">
+4
View File
@@ -37,3 +37,7 @@ spec:
description: 适配 plugin-links 的 RSS 订阅动态聚合页 description: 适配 plugin-links 的 RSS 订阅动态聚合页
screenshot: screenshot:
file: links-subscribe.html file: links-subscribe.html
- name: 豆瓣页面
description: 适配 plugin-douban(豆瓣/追番)的主题页面,按收藏状态展示条目
screenshot:
file: douban.html