增加i18n支持
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# WarmIsland 暖屿
|
||||
|
||||
具有独特气质的生活博客主题,适用于 [Halo CMS](https://github.com/halo-dev/halo)。
|
||||
暖如灯火,静如留白。暖屿以柔和的色调和舒缓的节奏回归内容本身,为记录与阅读留出一方安静从容的角落。
|
||||
|
||||
> 本项目由 AI 开发完成,人工仅进行部分功能测试及问题找寻
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
@@ -1,29 +0,0 @@
|
||||
(function(){
|
||||
var result = {};
|
||||
var hero = document.querySelector(".hero");
|
||||
if (hero) {
|
||||
var h1 = hero.querySelector("h1");
|
||||
var subtitle = hero.querySelector(".hero-subtitle, .subtitle, h2, p");
|
||||
result.heroTitle = h1 ? h1.textContent.trim() : "no h1 found";
|
||||
result.heroSubtitle = subtitle ? subtitle.textContent.trim() : "no subtitle found";
|
||||
result.heroHTML = hero.innerHTML.substring(0, 500);
|
||||
} else {
|
||||
result.hero = "not found";
|
||||
}
|
||||
var footer = document.querySelector("footer, .footer, #footer");
|
||||
if (footer) {
|
||||
result.footerText = footer.textContent.trim().substring(0, 300);
|
||||
result.footerHeight = getComputedStyle(footer).height;
|
||||
result.footerMarginBottom = getComputedStyle(footer).marginBottom;
|
||||
result.footerPaddingBottom = getComputedStyle(footer).paddingBottom;
|
||||
} else {
|
||||
result.footer = "not found";
|
||||
}
|
||||
var body = document.body;
|
||||
result.bodyMarginBottom = getComputedStyle(body).marginBottom;
|
||||
result.bodyPaddingBottom = getComputedStyle(body).paddingBottom;
|
||||
result.htmlMarginBottom = getComputedStyle(document.documentElement).marginBottom;
|
||||
result.documentHeight = document.documentElement.scrollHeight;
|
||||
result.windowHeight = window.innerHeight;
|
||||
return JSON.stringify(result);
|
||||
})()
|
||||
@@ -1,5 +0,0 @@
|
||||
(function(){
|
||||
return fetch('/apis/api.console.halo.run/v1alpha1/configmaps/warm-island-config')
|
||||
.then(r => r.text())
|
||||
.then(data => data.substring(0, 3000));
|
||||
})()
|
||||
@@ -1,5 +0,0 @@
|
||||
(function(){
|
||||
return fetch('/apis/api.console.halo.run/v1alpha1/themes/warm-island/config')
|
||||
.then(r => r.text())
|
||||
.then(data => data.substring(0, 2000));
|
||||
})()
|
||||
@@ -1,15 +0,0 @@
|
||||
(function(){
|
||||
var selects = document.querySelectorAll('select');
|
||||
var result = [];
|
||||
selects.forEach(function(s, i) {
|
||||
result.push({index: i, value: s.value, name: s.name, options: Array.from(s.options).map(function(o){return o.value + ':' + o.text})});
|
||||
});
|
||||
var inputs = document.querySelectorAll('input');
|
||||
var inputResult = [];
|
||||
inputs.forEach(function(inp, i) {
|
||||
if (inp.type !== 'hidden') {
|
||||
inputResult.push({index: i, type: inp.type, name: inp.name, value: inp.value});
|
||||
}
|
||||
});
|
||||
return JSON.stringify({selects: result, inputs: inputResult.slice(0, 10)});
|
||||
})()
|
||||
@@ -1,8 +0,0 @@
|
||||
(function(){
|
||||
var header = document.querySelector('header');
|
||||
if (!header) return JSON.stringify({header: "not found"});
|
||||
return JSON.stringify({
|
||||
className: header.className,
|
||||
innerHTML: header.innerHTML.substring(0, 500)
|
||||
});
|
||||
})()
|
||||
@@ -1,13 +0,0 @@
|
||||
(function(){
|
||||
var h = document.querySelector(".hero");
|
||||
if (!h) return "No .hero element found";
|
||||
var s = getComputedStyle(h);
|
||||
return JSON.stringify({
|
||||
width: s.width,
|
||||
marginLeft: s.marginLeft,
|
||||
marginTop: s.marginTop,
|
||||
paddingTop: s.paddingTop,
|
||||
left: s.left,
|
||||
position: s.position
|
||||
});
|
||||
})()
|
||||
@@ -1,13 +0,0 @@
|
||||
(function(){
|
||||
var likeBtn = document.querySelector('.wi-like-btn');
|
||||
if (!likeBtn) return JSON.stringify({likeBtn: "not found"});
|
||||
var likeContainer = likeBtn.closest('.wi-post__like');
|
||||
return JSON.stringify({
|
||||
btnClass: likeBtn.className,
|
||||
btnDisabled: likeBtn.disabled,
|
||||
containerClass: likeContainer ? likeContainer.className : "none",
|
||||
text: likeContainer ? likeContainer.textContent.trim() : likeBtn.textContent.trim(),
|
||||
liked: likeBtn.classList.contains('wi-like-btn--liked') || (likeContainer && likeContainer.classList.contains('wi-post__like--liked')),
|
||||
svgFill: likeBtn.querySelector('svg') ? getComputedStyle(likeBtn.querySelector('svg')).fill : "none"
|
||||
});
|
||||
})()
|
||||
@@ -1,17 +0,0 @@
|
||||
(function(){
|
||||
var likeBtn = document.querySelector('.like-btn, .wi-like, [class*="like"], [class*="heart"]');
|
||||
if (!likeBtn) {
|
||||
var buttons = document.querySelectorAll('button');
|
||||
var result = [];
|
||||
buttons.forEach(function(b, i) {
|
||||
result.push({index: i, text: b.textContent.trim(), className: b.className, innerHTML: b.innerHTML.substring(0, 200)});
|
||||
});
|
||||
return JSON.stringify({likeBtn: "not found", buttons: result});
|
||||
}
|
||||
return JSON.stringify({
|
||||
className: likeBtn.className,
|
||||
text: likeBtn.textContent.trim(),
|
||||
innerHTML: likeBtn.innerHTML.substring(0, 300),
|
||||
ariaLabel: likeBtn.getAttribute('aria-label')
|
||||
});
|
||||
})()
|
||||
@@ -1,8 +0,0 @@
|
||||
(function(){
|
||||
return fetch('/apis/api.console.halo.run/v1alpha1/themes/warm-island')
|
||||
.then(r => r.json())
|
||||
.then(data => JSON.stringify({
|
||||
settingName: data.spec.settingName,
|
||||
configMapName: data.spec.configMapName
|
||||
}));
|
||||
})()
|
||||
@@ -1,18 +0,0 @@
|
||||
(function(){
|
||||
var nav = document.querySelector("nav, .navbar, .nav, header nav, .header-nav");
|
||||
if (!nav) return JSON.stringify({nav: "not found"});
|
||||
var s = getComputedStyle(nav);
|
||||
var parent = nav.parentElement;
|
||||
var ps = parent ? getComputedStyle(parent) : null;
|
||||
return JSON.stringify({
|
||||
navClass: nav.className,
|
||||
navWidth: s.width,
|
||||
navMargin: s.margin,
|
||||
navBorderRadius: s.borderRadius,
|
||||
navBorder: s.border,
|
||||
navPadding: s.padding,
|
||||
parentClass: parent ? parent.className : "none",
|
||||
parentWidth: ps ? ps.width : "none",
|
||||
parentBorderRadius: ps ? ps.borderRadius : "none"
|
||||
});
|
||||
})()
|
||||
@@ -1,8 +0,0 @@
|
||||
(function(){
|
||||
var navbar = document.querySelector('.wi-navbar');
|
||||
if (!navbar) return JSON.stringify({navbar: "not found"});
|
||||
return JSON.stringify({
|
||||
className: navbar.className,
|
||||
allClasses: navbar.className
|
||||
});
|
||||
})()
|
||||
@@ -1,5 +0,0 @@
|
||||
(function(){
|
||||
return fetch('/apis/api.console.halo.run/v1alpha1/themes/warm-island')
|
||||
.then(r => r.text())
|
||||
.then(data => data.substring(0, 2000));
|
||||
})()
|
||||
@@ -1,5 +0,0 @@
|
||||
(function(){
|
||||
return fetch('/apis/api.console.halo.run/v1alpha1/themes/warm-island/setting')
|
||||
.then(r => r.text())
|
||||
.then(data => data.substring(0, 1000));
|
||||
})()
|
||||
@@ -1,34 +0,0 @@
|
||||
(function(){
|
||||
var result = {};
|
||||
var h1 = document.querySelector('h1');
|
||||
var content = document.querySelector('.wi-post__content, .post-content, article, .content');
|
||||
if (h1 && content) {
|
||||
var h1Rect = h1.getBoundingClientRect();
|
||||
var contentRect = content.getBoundingClientRect();
|
||||
result.titleBottom = h1Rect.bottom;
|
||||
result.contentTop = contentRect.top;
|
||||
result.gap = contentRect.top - h1Rect.bottom;
|
||||
} else {
|
||||
result.h1Found = !!h1;
|
||||
result.contentFound = !!content;
|
||||
if (h1) {
|
||||
var nextEl = h1.nextElementSibling;
|
||||
result.nextElTag = nextEl ? nextEl.tagName : "none";
|
||||
result.nextElClass = nextEl ? nextEl.className : "none";
|
||||
var h1Rect = h1.getBoundingClientRect();
|
||||
if (nextEl) {
|
||||
var nextRect = nextEl.getBoundingClientRect();
|
||||
result.gap = nextRect.top - h1Rect.bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
var footer = document.querySelector("footer, .footer, #footer");
|
||||
if (footer) {
|
||||
var footerRect = footer.getBoundingClientRect();
|
||||
result.footerBottom = footerRect.bottom;
|
||||
result.windowHeight = window.innerHeight;
|
||||
result.spaceBelowFooter = window.innerHeight - footerRect.bottom;
|
||||
result.docHeight = document.documentElement.scrollHeight;
|
||||
}
|
||||
return JSON.stringify(result);
|
||||
})()
|
||||
@@ -1,13 +0,0 @@
|
||||
(function(){
|
||||
return fetch('/apis/api.console.halo.run/v1alpha1/themes?sort=creationTimestamp%2Cdesc')
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
var items = data.items || [];
|
||||
var result = items.map(t => ({
|
||||
name: t.metadata.name,
|
||||
displayName: t.spec.displayName,
|
||||
active: !!t.spec.activationTime
|
||||
}));
|
||||
return JSON.stringify(result);
|
||||
});
|
||||
})()
|
||||
@@ -1,14 +0,0 @@
|
||||
(function(){
|
||||
return fetch('/apis/api.console.halo.run/v1alpha1/themes?sort=creationTimestamp%2Cdesc')
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
var items = data.items || [];
|
||||
var result = items.map(t => ({
|
||||
name: t.metadata.name,
|
||||
displayName: t.spec.displayName,
|
||||
active: t.spec.activationTime,
|
||||
allKeys: Object.keys(t.spec)
|
||||
}));
|
||||
return JSON.stringify(result);
|
||||
});
|
||||
})()
|
||||
@@ -1,21 +0,0 @@
|
||||
(function(){
|
||||
var btn = document.querySelector('.wi-like-btn');
|
||||
if (!btn) return JSON.stringify({error: "no btn"});
|
||||
var origFetch = window.fetch;
|
||||
var lastRequest = null;
|
||||
window.fetch = function() {
|
||||
lastRequest = {url: arguments[0], options: arguments[1]};
|
||||
return origFetch.apply(this, arguments);
|
||||
};
|
||||
btn.click();
|
||||
return new Promise(function(resolve){
|
||||
setTimeout(function(){
|
||||
resolve(JSON.stringify({
|
||||
lastRequest: lastRequest,
|
||||
btnClass: btn.className,
|
||||
liked: btn.classList.contains('wi-like-btn--liked'),
|
||||
text: btn.closest('.wi-post__like').textContent.trim()
|
||||
}));
|
||||
}, 3000);
|
||||
});
|
||||
})()
|
||||
@@ -1,16 +0,0 @@
|
||||
(function(){
|
||||
var btn = document.querySelector('.wi-like-btn');
|
||||
if (!btn) return "no btn";
|
||||
btn.click();
|
||||
return new Promise(function(resolve){
|
||||
setTimeout(function(){
|
||||
var container = btn.closest('.wi-post__like');
|
||||
resolve(JSON.stringify({
|
||||
btnClass: btn.className,
|
||||
btnDisabled: btn.disabled,
|
||||
text: container ? container.textContent.trim() : btn.textContent.trim(),
|
||||
liked: btn.classList.contains('wi-like-btn--liked')
|
||||
}));
|
||||
}, 2000);
|
||||
});
|
||||
})()
|
||||
+29
-5
@@ -4,6 +4,8 @@
|
||||
|
||||
首次发布 🎉
|
||||
|
||||
- 🗑️ 移除侧边栏功能
|
||||
|
||||
### 核心功能
|
||||
|
||||
- 🎨 暖色调设计语言,呼吸动效光球、毛玻璃导航栏
|
||||
@@ -11,6 +13,23 @@
|
||||
- 📱 响应式布局,移动端专属菜单与交互体验
|
||||
- ✨ 滚动渐入动画、光感跟随效果
|
||||
|
||||
### SEO 与结构化数据
|
||||
|
||||
- 🔍 Open Graph 元标签,优化社交媒体分享预览
|
||||
- 📋 JSON-LD 结构化数据,提升搜索引擎理解与展示
|
||||
|
||||
### 国际化
|
||||
|
||||
- 🌐 i18n 国际化支持(简体中文、繁体中文、英语)
|
||||
- 🔄 跟随浏览器语言自动匹配,也可手动指定
|
||||
|
||||
### 文章页增强
|
||||
|
||||
- 📑 目录展开模式选项(仅展开当前分组 / 全部展开)
|
||||
- 📰 相关文章推荐,帮助读者发现更多内容
|
||||
- 🔗 分享功能(微博 / X / Facebook / Telegram / 复制链接)
|
||||
- 🖼️ 图片懒加载 blur-up 效果,优化加载体验
|
||||
|
||||
### 页面模板
|
||||
|
||||
- 🏠 Hero 首屏(一言 API / 自定义描述 / 背景图片)
|
||||
@@ -30,14 +49,19 @@
|
||||
- 🎯 三种导航栏样式(Glass / Minimal / Float)
|
||||
- 🌓 主题切换按钮
|
||||
|
||||
### 性能与体验
|
||||
|
||||
- ⚡ preconnect / dns-prefetch 资源提示,优化外部资源加载
|
||||
- 🖼️ 图片懒加载 blur-up 渐显效果
|
||||
- 🔤 移除自定义字体和内置字体功能,使用系统默认字体栈,提升加载速度
|
||||
|
||||
### 错误页面
|
||||
|
||||
- 🐘 404 / 500 错误页增强(导航栏 + 页脚),方便访客返回
|
||||
|
||||
### 配置与自定义
|
||||
|
||||
- ⚙️ 丰富的主题设置面板(13 个配置分组)
|
||||
- 🎨 可自定义强调色、圆角风格、容器宽度
|
||||
- 📝 自定义 CSS 支持
|
||||
- 🔧 页脚社交链接和自定义 HTML
|
||||
|
||||
### 错误页面
|
||||
|
||||
- 🐘 404 页面
|
||||
- 🐘 500 页面
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
| `article_show_visit_count` | 开关 | `true` | 显示阅读量统计 |
|
||||
| `article_show_read_time` | 开关 | `false` | 显示预计阅读时间 |
|
||||
| `article_code_theme` | 下拉 | `warm` | 代码高亮主题:`warm` / `cold` |
|
||||
| `article_toc_expand` | 下拉 | `active` | 目录展开模式:`active` / `all` |
|
||||
| `article_show_related` | 开关 | `false` | 显示相关文章推荐 |
|
||||
| `article_related_title` | 文本 | `相关推荐` | 相关文章标题 |
|
||||
| `article_show_share` | 开关 | `true` | 显示分享按钮 |
|
||||
| `article_share_title` | 文本 | `分享` | 分享区域标题 |
|
||||
|
||||
## 详细说明
|
||||
|
||||
@@ -98,6 +103,57 @@ article_code_theme: warm
|
||||
代码高亮支持多种编程语言,包括 JavaScript、Python、Java、Go、Rust、YAML、JSON、Bash 等。语言检测基于代码块的语言标记自动完成。
|
||||
:::
|
||||
|
||||
### 目录展开模式(article_toc_expand)
|
||||
|
||||
控制文章目录的展开方式:
|
||||
|
||||
| 值 | 说明 |
|
||||
| --- | --- |
|
||||
| `active` | 仅展开当前阅读位置所在的分组,其余分组折叠(默认) |
|
||||
| `all` | 全部展开,显示所有层级的目录项 |
|
||||
|
||||
::: tip
|
||||
对于标题层级较多的长文,推荐使用 `active` 模式,可以让读者更聚焦于当前章节。对于短文或标题层级较少的文章,`all` 模式可以一次性展示完整目录结构。
|
||||
:::
|
||||
|
||||
### 相关文章推荐(article_show_related)
|
||||
|
||||
开启后,文章底部会显示相关文章推荐列表,帮助读者发现更多感兴趣的内容。相关文章基于 Halo 的随机推荐算法选取。
|
||||
|
||||
#### 相关文章标题(article_related_title)
|
||||
|
||||
自定义相关文章推荐区域的标题文字,默认为「相关推荐」。仅在 `article_show_related` 开启时显示此配置项。
|
||||
|
||||
```yaml
|
||||
article_show_related: true
|
||||
article_related_title: "猜你喜欢"
|
||||
```
|
||||
|
||||
### 分享功能(article_show_share)
|
||||
|
||||
开启后,文章底部会显示分享按钮,支持以下社交平台:
|
||||
|
||||
| 平台 | 说明 |
|
||||
| --- | --- |
|
||||
| 微博 | 分享到新浪微博 |
|
||||
| X (Twitter) | 分享到 X |
|
||||
| Facebook | 分享到 Facebook |
|
||||
| Telegram | 分享到 Telegram |
|
||||
| 复制链接 | 复制文章链接到剪贴板 |
|
||||
|
||||
#### 分享区域标题(article_share_title)
|
||||
|
||||
自定义分享区域的标题文字,默认为「分享」。仅在 `article_show_share` 开启时显示此配置项。
|
||||
|
||||
```yaml
|
||||
article_show_share: true
|
||||
article_share_title: "分享这篇文章"
|
||||
```
|
||||
|
||||
::: tip
|
||||
分享功能会自动携带文章标题和链接,无需手动配置分享内容。移动端会优先显示适合移动端的分享方式。
|
||||
:::
|
||||
|
||||
## 阅读增强功能
|
||||
|
||||
除了可配置的项目外,文章详情页还包含以下内置功能:
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
| `label_search` | 文本 | `搜索` | 搜索按钮的标签文案 |
|
||||
| `label_theme_switch` | 文本 | `切换主题` | 主题切换按钮的标签文案 |
|
||||
| `label_archives_title` | 文本 | `归档` | 归档页面的标题文案 |
|
||||
| `language` | 下拉 | `auto` | 主题界面语言 |
|
||||
|
||||
## 详细说明
|
||||
|
||||
@@ -72,6 +73,21 @@ label_archives_title: "Archives"
|
||||
标签文案的修改会即时生效,无需重启 Halo。如果使用多语言场景,可以配合 Halo 的多语言插件实现更完整的国际化。
|
||||
:::
|
||||
|
||||
### 语言(language)
|
||||
|
||||
设置主题界面的显示语言,影响导航栏、文章页、错误页等所有主题内置文案。提供以下选项:
|
||||
|
||||
| 值 | 说明 |
|
||||
| --- | --- |
|
||||
| `auto` | 跟随浏览器语言自动匹配(默认) |
|
||||
| `zh_CN` | 简体中文 |
|
||||
| `zh_TW` | 繁體中文 |
|
||||
| `en` | English |
|
||||
|
||||
::: tip
|
||||
选择 `auto` 时,主题会根据访客浏览器的语言设置自动匹配最接近的语言。如果浏览器语言不在支持列表中,将回退到简体中文。
|
||||
:::
|
||||
|
||||
## 相关页面
|
||||
|
||||
- [样式设置](/config/style) — 调整配色、圆角、动画等视觉表现
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
| `accent_color` | 颜色 | `#d4764e` | 全局强调色 |
|
||||
| `border_radius` | 下拉 | `medium` | 圆角风格:`small` / `medium` / `large` |
|
||||
| `layout_container_width` | 下拉 | `medium` | 容器宽度:`narrow` / `medium` / `wide` |
|
||||
| `layout_sidebar` | 开关 | `false` | 启用侧边栏(开发中) |
|
||||
| `animation_enabled` | 开关 | `true` | 全局动画总开关 |
|
||||
| `animation_breath` | 开关 | `true` | 呼吸动画效果 |
|
||||
| `animation_scroll_reveal` | 开关 | `true` | 滚动渐入动画 |
|
||||
@@ -79,12 +78,6 @@ accent_color: "#8b5cf6" # 紫罗兰
|
||||
| `medium` | 中等宽度,兼顾阅读体验与信息密度(默认) |
|
||||
| `wide` | 宽容器,适合图片较多的站点或需要更大展示空间的场景 |
|
||||
|
||||
### 侧边栏(layout_sidebar)
|
||||
|
||||
::: danger
|
||||
侧边栏功能目前仍在开发中,此选项暂不可用。开启后不会产生实际效果,请关注后续版本更新。
|
||||
:::
|
||||
|
||||
### 动画效果
|
||||
|
||||
WarmIsland 提供了丰富的动画效果,所有动画都可以独立开关:
|
||||
@@ -118,11 +111,6 @@ WarmIsland 提供了丰富的动画效果,所有动画都可以独立开关:
|
||||
在此处编写自定义 CSS 代码,会注入到全站所有页面的 `<style>` 标签中。可以用来覆盖主题默认样式或添加全新样式。
|
||||
|
||||
```css
|
||||
/* 示例:修改正文字体 */
|
||||
body {
|
||||
font-family: "LXGW WenKai", sans-serif;
|
||||
}
|
||||
|
||||
/* 示例:自定义卡片悬停效果 */
|
||||
.post-card:hover {
|
||||
transform: translateY(-4px);
|
||||
|
||||
@@ -104,18 +104,18 @@ else if (!stored && prefersDark) { isDark = true; }
|
||||
|
||||
| 变量 | 字体栈 | 用途 |
|
||||
|------|--------|------|
|
||||
| `--font-sans` | `'Noto Serif SC', 'Source Han Serif SC', Georgia, serif` | 标题、强调文字 |
|
||||
| `--font-body` | `'Noto Sans SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif` | 正文、UI 文字 |
|
||||
| `--font-mono` | `'JetBrains Mono', 'Fira Code', monospace` | 代码 |
|
||||
| `--font-sans` | `Georgia, 'Noto Serif SC', 'Source Han Serif SC', serif` | 标题、强调文字 |
|
||||
| `--font-body` | `-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans SC', sans-serif` | 正文、UI 文字 |
|
||||
| `--font-mono` | `'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace` | 代码 |
|
||||
|
||||
### 设计思路
|
||||
|
||||
- **标题用衬线体**:Noto Serif SC 赋予标题优雅的文艺气质
|
||||
- **正文用无衬线体**:Noto Sans SC 保证长文阅读的舒适度
|
||||
- **代码用等宽体**:JetBrains Mono 专为代码设计
|
||||
- **标题用衬线体**:Georgia 赋予标题优雅的文艺气质,回退到系统中文字体
|
||||
- **正文用系统字体**:使用各平台原生系统字体栈,确保最佳阅读体验与加载性能
|
||||
- **代码用等宽体**:优先使用 JetBrains Mono,回退到系统等宽字体
|
||||
|
||||
::: tip
|
||||
这些字体不会自动加载,需要在 Halo 后台或 HTML 中引入对应的字体 CSS。推荐使用 Google Fonts 或国内 CDN 镜像。
|
||||
主题使用系统默认字体栈,无需额外加载字体文件,可显著提升页面加载速度。如需使用自定义字体,可通过 [自定义 CSS](/customize/custom-css) 覆盖 `--font-sans`、`--font-body` 等变量。
|
||||
:::
|
||||
|
||||
## 间距系统
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 快速开始
|
||||
|
||||
WarmIsland(暖屿)是一款为 [Halo](https://halo.run) 打造的生活博客主题,具有独特的暖色调设计语言和丰富的功能模块。
|
||||
WarmIsland(暖屿)是一款为 [Halo](https://halo.run) 打造的博客主题。暖如灯火,静如留白——它以柔和的色调和舒缓的节奏回归内容本身,为记录与阅读留出一方安静从容的角落。
|
||||
|
||||
## 主题特色
|
||||
|
||||
@@ -33,22 +33,6 @@ WarmIsland(暖屿)是一款为 [Halo](https://halo.run) 打造的生活博
|
||||
4. 上传下载的 `.zip` 文件
|
||||
5. 点击 **启用** 激活主题
|
||||
|
||||
### 方式三:Git 克隆安装
|
||||
|
||||
1. SSH 登录服务器,进入 Halo 主题目录:
|
||||
|
||||
```bash
|
||||
cd ~/.halo2/themes
|
||||
```
|
||||
|
||||
2. 克隆主题仓库:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/nxxy335top/halo-theme-WarmIsland.git warm-island
|
||||
```
|
||||
|
||||
3. 在 Halo 后台 **主题** 管理页面中找到 WarmIsland,点击 **启用**
|
||||
|
||||
## 初始配置
|
||||
|
||||
安装并启用主题后,建议按以下顺序进行初始配置:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# WarmIsland 是什么?
|
||||
|
||||
**WarmIsland(暖屿)** 是一款为 [Halo](https://halo.run) 打造的生活博客主题。
|
||||
**WarmIsland(暖屿)** 是一款为 [Halo](https://halo.run) 打造的博客主题。暖如灯火,静如留白——它以柔和的色调和舒缓的节奏回归内容本身,为记录与阅读留出一方安静从容的角落。
|
||||
|
||||
> 本主题由 AI 开发完成。
|
||||
|
||||
@@ -33,11 +33,14 @@
|
||||
|
||||
### 📝 阅读体验
|
||||
|
||||
- **文章目录** — 桌面端侧边悬浮 + 移动端底部抽屉
|
||||
- **文章目录** — 桌面端侧边悬浮 + 移动端底部抽屉,支持展开模式选项
|
||||
- **阅读进度条** — 实时显示阅读进度
|
||||
- **代码高亮** — Prism.js 支持,Warm / Cold 双主题
|
||||
- **图片灯箱** — 点击放大,支持左右切换
|
||||
- **图片懒加载** — blur-up 渐显效果,优化加载体验
|
||||
- **点赞功能** — 一键点赞,状态持久化
|
||||
- **相关文章推荐** — 文章底部推荐相关内容
|
||||
- **分享功能** — 微博 / X / Facebook / Telegram / 复制链接
|
||||
|
||||
### 📱 响应式
|
||||
|
||||
@@ -46,6 +49,12 @@
|
||||
- 文章卡片自动切换为上下布局
|
||||
- 目录自动切换为悬浮按钮 + 抽屉
|
||||
|
||||
### 🔍 SEO 与国际化
|
||||
|
||||
- **Open Graph 元标签** — 优化社交媒体分享预览
|
||||
- **JSON-LD 结构化数据** — 提升搜索引擎理解与展示
|
||||
- **i18n 国际化** — 简体中文、繁体中文、英语,支持跟随浏览器自动匹配
|
||||
|
||||
### 🔌 插件生态
|
||||
|
||||
深度集成 Halo 插件,提供丰富的扩展页面:
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ layout: home
|
||||
hero:
|
||||
name: "WarmIsland"
|
||||
text: "暖屿主题文档"
|
||||
tagline: 具有独特气质的生活博客主题,为 Halo 打造
|
||||
tagline: 暖如灯火,静如留白。暖屿以柔和的色调和舒缓的节奏回归内容本身,为记录与阅读留出一方安静从容的角落。
|
||||
actions:
|
||||
- theme: brand
|
||||
text: 快速开始
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const js = fs.readFileSync('c:\\Users\\Zhang\\Documents\\Halo\\WarmIsland\\check-all.js', 'utf8');
|
||||
console.log(Buffer.from(js).toString('base64'));
|
||||
@@ -1,3 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const js = fs.readFileSync('c:\\Users\\Zhang\\Documents\\Halo\\WarmIsland\\check-all.js', 'utf8');
|
||||
console.log(Buffer.from(js).toString('base64'));
|
||||
@@ -1,3 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const js = fs.readFileSync('c:\\Users\\Zhang\\Documents\\Halo\\WarmIsland\\click-like.js', 'utf8');
|
||||
console.log(Buffer.from(js).toString('base64'));
|
||||
@@ -1,3 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const js = fs.readFileSync('c:\\Users\\Zhang\\Documents\\Halo\\WarmIsland\\check-cm.js', 'utf8');
|
||||
console.log(Buffer.from(js).toString('base64'));
|
||||
@@ -1,3 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const js = fs.readFileSync('c:\\Users\\Zhang\\Documents\\Halo\\WarmIsland\\check-config.js', 'utf8');
|
||||
console.log(Buffer.from(js).toString('base64'));
|
||||
@@ -1,3 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const js = fs.readFileSync('c:\\Users\\Zhang\\Documents\\Halo\\WarmIsland\\check-form.js', 'utf8');
|
||||
console.log(Buffer.from(js).toString('base64'));
|
||||
@@ -1,3 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const js = fs.readFileSync('c:\\Users\\Zhang\\Documents\\Halo\\WarmIsland\\check-header.js', 'utf8');
|
||||
console.log(Buffer.from(js).toString('base64'));
|
||||
@@ -1,3 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const js = fs.readFileSync('c:\\Users\\Zhang\\Documents\\Halo\\WarmIsland\\check-like.js', 'utf8');
|
||||
console.log(Buffer.from(js).toString('base64'));
|
||||
@@ -1,3 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const js = fs.readFileSync('c:\\Users\\Zhang\\Documents\\Halo\\WarmIsland\\test-like-api.js', 'utf8');
|
||||
console.log(Buffer.from(js).toString('base64'));
|
||||
@@ -1,3 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const js = fs.readFileSync('c:\\Users\\Zhang\\Documents\\Halo\\WarmIsland\\click-like-debug.js', 'utf8');
|
||||
console.log(Buffer.from(js).toString('base64'));
|
||||
@@ -1,3 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const js = fs.readFileSync('c:\\Users\\Zhang\\Documents\\Halo\\WarmIsland\\check-like-state.js', 'utf8');
|
||||
console.log(Buffer.from(js).toString('base64'));
|
||||
@@ -1,3 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const js = fs.readFileSync('c:\\Users\\Zhang\\Documents\\Halo\\WarmIsland\\check-names.js', 'utf8');
|
||||
console.log(Buffer.from(js).toString('base64'));
|
||||
@@ -1,3 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const js = fs.readFileSync('c:\\Users\\Zhang\\Documents\\Halo\\WarmIsland\\check-nav.js', 'utf8');
|
||||
console.log(Buffer.from(js).toString('base64'));
|
||||
@@ -1,3 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const js = fs.readFileSync('c:\\Users\\Zhang\\Documents\\Halo\\WarmIsland\\check-navbar-class.js', 'utf8');
|
||||
console.log(Buffer.from(js).toString('base64'));
|
||||
@@ -1,3 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const js = fs.readFileSync('c:\\Users\\Zhang\\Documents\\Halo\\WarmIsland\\check-raw.js', 'utf8');
|
||||
console.log(Buffer.from(js).toString('base64'));
|
||||
@@ -1,3 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const js = fs.readFileSync('c:\\Users\\Zhang\\Documents\\Halo\\WarmIsland\\check-setting.js', 'utf8');
|
||||
console.log(Buffer.from(js).toString('base64'));
|
||||
@@ -1,3 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const js = fs.readFileSync('c:\\Users\\Zhang\\Documents\\Halo\\WarmIsland\\check-spacing.js', 'utf8');
|
||||
console.log(Buffer.from(js).toString('base64'));
|
||||
@@ -1,3 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const js = fs.readFileSync('c:\\Users\\Zhang\\Documents\\Halo\\WarmIsland\\check-theme.js', 'utf8');
|
||||
console.log(Buffer.from(js).toString('base64'));
|
||||
@@ -1,3 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const js = fs.readFileSync('c:\\Users\\Zhang\\Documents\\Halo\\WarmIsland\\check-theme2.js', 'utf8');
|
||||
console.log(Buffer.from(js).toString('base64'));
|
||||
@@ -1,62 +0,0 @@
|
||||
{
|
||||
"cookies": [
|
||||
{
|
||||
"name": "language",
|
||||
"value": "zh-CN",
|
||||
"domain": "localhost",
|
||||
"path": "/",
|
||||
"expires": -1.0,
|
||||
"size": 13,
|
||||
"httpOnly": false,
|
||||
"secure": false,
|
||||
"session": true,
|
||||
"sameSite": "Lax"
|
||||
},
|
||||
{
|
||||
"name": "XSRF-TOKEN",
|
||||
"value": "01a0a3fe-aad4-414d-bc42-3a173c9bc0ab",
|
||||
"domain": "localhost",
|
||||
"path": "/",
|
||||
"expires": -1.0,
|
||||
"size": 46,
|
||||
"httpOnly": true,
|
||||
"secure": false,
|
||||
"session": true
|
||||
},
|
||||
{
|
||||
"name": "NID",
|
||||
"value": "531=aZe-V6TNWj_kuxgiHTVkXjS6ptWqLuE0riVNGyXvxwnE9QdErkY4CznBbrF9lyQLZ9xDo0D8GSLbJHpi3JzQErmBm7pTVjoMnoOZUwYY3-9cwTfXq4tO0d8frwBCQFx7MHorS0Gf9zjpBLbpa0iQiht8sybQAlfsvHQWfyaBAz1dIW5jh9jHrb4ZREMKf5CCLFCBywI",
|
||||
"domain": ".google.com",
|
||||
"path": "/",
|
||||
"expires": 1794719008.977387,
|
||||
"size": 206,
|
||||
"httpOnly": true,
|
||||
"secure": false,
|
||||
"session": false
|
||||
},
|
||||
{
|
||||
"name": "SESSION",
|
||||
"value": "84b72204-3b7b-4594-908f-5b1a8a3db254",
|
||||
"domain": "localhost",
|
||||
"path": "/",
|
||||
"expires": -1.0,
|
||||
"size": 43,
|
||||
"httpOnly": true,
|
||||
"secure": false,
|
||||
"session": true
|
||||
},
|
||||
{
|
||||
"name": "device_id",
|
||||
"value": "63a8d881b6144d6e98511d7e647257bc",
|
||||
"domain": "localhost",
|
||||
"path": "/",
|
||||
"expires": 1787547843.038663,
|
||||
"size": 41,
|
||||
"httpOnly": true,
|
||||
"secure": false,
|
||||
"session": false,
|
||||
"sameSite": "Lax"
|
||||
}
|
||||
],
|
||||
"origins": []
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
common.home=Home
|
||||
common.search=Search
|
||||
common.themeSwitch=Switch Theme
|
||||
common.menu=Menu
|
||||
common.close=Close
|
||||
common.toc=Table of Contents
|
||||
common.openToc=Open Table of Contents
|
||||
common.closeToc=Close Table of Contents
|
||||
common.newer=Newer
|
||||
common.older=Older
|
||||
common.loading=Loading...
|
||||
common.allLoaded=All posts loaded
|
||||
common.allMomentsLoaded=All moments loaded
|
||||
common.noPosts=No posts yet.
|
||||
common.postCount=Total {0} posts
|
||||
common.categoryCount=Total {0} categories
|
||||
common.tagCount=Total {0} tags
|
||||
common.readMore=Read more
|
||||
common.words=words
|
||||
common.readTime=min read
|
||||
common.views=views
|
||||
common.like=Like
|
||||
common.pagination=Pagination
|
||||
common.toggleMenu=Toggle menu
|
||||
common.all=All
|
||||
common.noPhotos=No photos yet.
|
||||
common.noPhotosInGroup=No photos in this group.
|
||||
common.pluginError=Plugin loading error, please check plugin status.
|
||||
common.installPlugin=This feature requires the {0} plugin, <a href="{1}">go to the marketplace to install</a>
|
||||
common.featured=Featured
|
||||
common.latestPosts=Latest Posts
|
||||
common.timeline=Timeline
|
||||
common.viewAll=View all
|
||||
|
||||
navbar.search=Search
|
||||
navbar.themeSwitch=Switch Theme
|
||||
|
||||
hero.pinned=Pinned
|
||||
hero.posts=Posts
|
||||
|
||||
article.previousPost=Previous
|
||||
article.nextPost=Next
|
||||
article.toc=Table of Contents
|
||||
article.wordCount=words
|
||||
article.readTime=min read
|
||||
article.views=views
|
||||
article.relatedPosts=Related Posts
|
||||
|
||||
share.title=Share
|
||||
share.weibo=Weibo
|
||||
share.twitter=X (Twitter)
|
||||
share.facebook=Facebook
|
||||
share.telegram=Telegram
|
||||
share.copyLink=Copy Link
|
||||
share.copied=Copied!
|
||||
share.qrcode=QR Code
|
||||
|
||||
archives.title=Archives
|
||||
|
||||
categories.title=Categories
|
||||
|
||||
tags.title=Tags
|
||||
|
||||
links.title=Friends
|
||||
links.subtitle=Mountains and rivers, a journey of a thousand miles
|
||||
|
||||
moments.title=Moments
|
||||
moments.noMoments=No moments yet, go record your mood \U0001f319
|
||||
|
||||
photos.title=Gallery
|
||||
|
||||
friends.title=Friends Circle
|
||||
|
||||
equipment.title=Equipment
|
||||
|
||||
steam.title=Steam
|
||||
steam.homepage=Steam Homepage
|
||||
steam.level=Level
|
||||
steam.ownedGames=Owned Games
|
||||
steam.totalPlaytime=Total Playtime
|
||||
steam.recentPlaytime=Recent 2 Weeks
|
||||
steam.badges=Badges
|
||||
steam.hours=hours
|
||||
steam.recentlyPlayed=Recently Played
|
||||
steam.gameLibrary=Game Library
|
||||
steam.lastPlayed=Last played {0}
|
||||
|
||||
douban.title=Douban
|
||||
douban.wish=Wish
|
||||
douban.done=Done
|
||||
douban.wishRead=Wish
|
||||
douban.reading=Reading
|
||||
douban.listened=Listened
|
||||
douban.wishPlay=Wish
|
||||
douban.played=Played
|
||||
douban.wishListen=Wish
|
||||
douban.listening=Listening
|
||||
douban.playing=Playing
|
||||
douban.myRating=My:
|
||||
|
||||
messageboard.title=Message Board
|
||||
messageboard.subtitle=Leave your footprints here \U0001f319
|
||||
|
||||
footer.poweredBy=Powered by Halo
|
||||
|
||||
error.404.title=Page Not Found
|
||||
error.404.desc=The page you are looking for seems to have wandered off this island
|
||||
error.404.home=Back to Home
|
||||
error.404.back=Go Back
|
||||
error.500.title=Server Error
|
||||
error.500.desc=The island encountered some issues, please try again later
|
||||
error.500.home=Back to Home
|
||||
error.500.back=Go Back
|
||||
|
||||
sidebar.authorInfo=About Author
|
||||
sidebar.latestPosts=Latest Posts
|
||||
sidebar.recommendedPosts=Recommended
|
||||
sidebar.timeProgress=Time Progress
|
||||
sidebar.dayProgress=Day
|
||||
sidebar.monthProgress=Month
|
||||
sidebar.yearProgress=Year
|
||||
sidebar.categories=Categories
|
||||
sidebar.tags=Tags
|
||||
|
||||
comment.style=Warm
|
||||
comment.showAvatar=Show Avatar
|
||||
@@ -0,0 +1,126 @@
|
||||
common.home=Home
|
||||
common.search=Search
|
||||
common.themeSwitch=Switch Theme
|
||||
common.menu=Menu
|
||||
common.close=Close
|
||||
common.toc=Table of Contents
|
||||
common.openToc=Open Table of Contents
|
||||
common.closeToc=Close Table of Contents
|
||||
common.newer=Newer
|
||||
common.older=Older
|
||||
common.loading=Loading...
|
||||
common.allLoaded=All posts loaded
|
||||
common.noPosts=No posts yet.
|
||||
common.postCount=Total {0} posts
|
||||
common.readMore=Read more
|
||||
common.words=words
|
||||
common.readTime=min read
|
||||
common.views=views
|
||||
common.like=Like
|
||||
common.pagination=Pagination
|
||||
common.toggleMenu=Toggle menu
|
||||
common.allMomentsLoaded=All moments loaded
|
||||
common.categoryCount=Total {0} categories
|
||||
common.tagCount=Total {0} tags
|
||||
common.all=All
|
||||
common.noPhotos=No photos yet.
|
||||
common.noPhotosInGroup=No photos in this group.
|
||||
common.pluginError=Plugin loading error, please check plugin status.
|
||||
common.installPlugin=This feature requires the {0} plugin, <a href="{1}">go to the marketplace to install</a>
|
||||
common.featured=Featured
|
||||
common.latestPosts=Latest Posts
|
||||
common.timeline=Timeline
|
||||
common.viewAll=View all
|
||||
|
||||
navbar.search=Search
|
||||
navbar.themeSwitch=Switch Theme
|
||||
|
||||
hero.pinned=Pinned
|
||||
hero.posts=Posts
|
||||
|
||||
article.previousPost=Previous
|
||||
article.nextPost=Next
|
||||
article.toc=Table of Contents
|
||||
article.wordCount=words
|
||||
article.readTime=min read
|
||||
article.views=views
|
||||
article.relatedPosts=Related Posts
|
||||
|
||||
share.title=Share
|
||||
share.weibo=Weibo
|
||||
share.twitter=X (Twitter)
|
||||
share.facebook=Facebook
|
||||
share.telegram=Telegram
|
||||
share.copyLink=Copy Link
|
||||
share.copied=Copied!
|
||||
share.qrcode=QR Code
|
||||
|
||||
archives.title=Archives
|
||||
|
||||
categories.title=Categories
|
||||
|
||||
tags.title=Tags
|
||||
|
||||
links.title=Friends
|
||||
links.subtitle=Mountains and rivers, a journey of a thousand miles
|
||||
|
||||
moments.title=Moments
|
||||
moments.noMoments=No moments yet, go record your mood \U0001f319
|
||||
|
||||
photos.title=Gallery
|
||||
|
||||
friends.title=Friends Circle
|
||||
|
||||
equipment.title=Equipment
|
||||
|
||||
steam.title=Steam
|
||||
steam.homepage=Steam Homepage
|
||||
steam.level=Level
|
||||
steam.ownedGames=Owned Games
|
||||
steam.totalPlaytime=Total Playtime
|
||||
steam.recentPlaytime=Recent 2 Weeks
|
||||
steam.badges=Badges
|
||||
steam.hours=hours
|
||||
steam.recentlyPlayed=Recently Played
|
||||
steam.gameLibrary=Game Library
|
||||
steam.lastPlayed=Last played {0}
|
||||
|
||||
douban.title=Douban
|
||||
douban.wish=Wish
|
||||
douban.done=Done
|
||||
douban.wishRead=Wish
|
||||
douban.reading=Reading
|
||||
douban.listened=Listened
|
||||
douban.wishPlay=Wish
|
||||
douban.played=Played
|
||||
douban.wishListen=Wish
|
||||
douban.listening=Listening
|
||||
douban.playing=Playing
|
||||
douban.myRating=My:
|
||||
|
||||
messageboard.title=Message Board
|
||||
messageboard.subtitle=Leave your footprints here \U0001f319
|
||||
|
||||
footer.poweredBy=Powered by Halo
|
||||
|
||||
error.404.title=Page Not Found
|
||||
error.404.desc=The page you are looking for seems to have wandered off this island
|
||||
error.404.home=Back to Home
|
||||
error.404.back=Go Back
|
||||
error.500.title=Server Error
|
||||
error.500.desc=The island encountered some issues, please try again later
|
||||
error.500.home=Back to Home
|
||||
error.500.back=Go Back
|
||||
|
||||
sidebar.authorInfo=About Author
|
||||
sidebar.latestPosts=Latest Posts
|
||||
sidebar.recommendedPosts=Recommended
|
||||
sidebar.timeProgress=Time Progress
|
||||
sidebar.dayProgress=Day
|
||||
sidebar.monthProgress=Month
|
||||
sidebar.yearProgress=Year
|
||||
sidebar.categories=Categories
|
||||
sidebar.tags=Tags
|
||||
|
||||
comment.style=Warm
|
||||
comment.showAvatar=Show Avatar
|
||||
@@ -0,0 +1,126 @@
|
||||
common.home=\u9996\u9875
|
||||
common.search=\u641c\u7d22
|
||||
common.themeSwitch=\u5207\u6362\u4e3b\u9898
|
||||
common.menu=\u83dc\u5355
|
||||
common.close=\u5173\u95ed
|
||||
common.toc=\u76ee\u5f55
|
||||
common.openToc=\u6253\u5f00\u76ee\u5f55
|
||||
common.closeToc=\u5173\u95ed\u76ee\u5f55
|
||||
common.newer=\u8f83\u65b0
|
||||
common.older=\u8f83\u65e7
|
||||
common.loading=\u52a0\u8f7d\u4e2d...
|
||||
common.allLoaded=\u5df2\u52a0\u8f7d\u5168\u90e8\u6587\u7ae0
|
||||
common.noPosts=\u6682\u65e0\u6587\u7ae0
|
||||
common.postCount=\u5171 {0} \u7bc7\u6587\u7ae0
|
||||
common.readMore=\u9605\u8bfb\u66f4\u591a
|
||||
common.words=\u5b57
|
||||
common.readTime=\u5206\u949f
|
||||
common.views=\u9605\u8bfb
|
||||
common.like=\u70b9\u8d5e
|
||||
common.pagination=\u5206\u9875
|
||||
common.toggleMenu=\u5207\u6362\u83dc\u5355
|
||||
common.allMomentsLoaded=\u5df2\u52a0\u8f7d\u5168\u90e8\u77ac\u95f4
|
||||
common.categoryCount=\u5171 {0} \u4e2a\u5206\u7c7b
|
||||
common.tagCount=\u5171 {0} \u4e2a\u6807\u7b7e
|
||||
common.all=\u5168\u90e8
|
||||
common.noPhotos=\u6682\u65e0\u56fe\u7247
|
||||
common.noPhotosInGroup=\u8be5\u5206\u7ec4\u6682\u65e0\u56fe\u7247
|
||||
common.pluginError=\u63d2\u4ef6\u52a0\u8f7d\u5f02\u5e38\uff0c\u8bf7\u68c0\u67e5\u63d2\u4ef6\u72b6\u6001
|
||||
common.installPlugin=\u8be5\u529f\u80fd\u9700\u8981\u5b89\u88c5\u300c{0}\u300d\u63d2\u4ef6\uff0c<a href="{1}">\u524d\u5f80\u5e94\u7528\u5e02\u573a\u5b89\u88c5</a>
|
||||
common.featured=\u7cbe\u9009
|
||||
common.latestPosts=\u6700\u65b0\u6587\u7ae0
|
||||
common.timeline=\u65f6\u95f4\u7ebf
|
||||
common.viewAll=\u67e5\u770b\u5168\u90e8
|
||||
|
||||
navbar.search=\u641c\u7d22
|
||||
navbar.themeSwitch=\u5207\u6362\u4e3b\u9898
|
||||
|
||||
hero.pinned=\u7f6e\u9876
|
||||
hero.posts=\u6587\u7ae0
|
||||
|
||||
article.previousPost=\u4e0a\u4e00\u7bc7
|
||||
article.nextPost=\u4e0b\u4e00\u7bc7
|
||||
article.toc=\u76ee\u5f55
|
||||
article.wordCount=\u5b57
|
||||
article.readTime=\u5206\u949f
|
||||
article.views=\u9605\u8bfb
|
||||
article.relatedPosts=\u76f8\u5173\u63a8\u8350
|
||||
|
||||
share.title=\u5206\u4eab
|
||||
share.weibo=\u5fae\u535a
|
||||
share.twitter=X
|
||||
share.facebook=Facebook
|
||||
share.telegram=Telegram
|
||||
share.copyLink=\u590d\u5236\u94fe\u63a5
|
||||
share.copied=\u5df2\u590d\u5236
|
||||
share.qrcode=\u4e8c\u7ef4\u7801
|
||||
|
||||
archives.title=\u5f52\u6863
|
||||
|
||||
categories.title=\u5206\u7c7b
|
||||
|
||||
tags.title=\u6807\u7b7e
|
||||
|
||||
links.title=\u53cb\u94fe
|
||||
links.subtitle=\u5c71\u6c34\u4e00\u7a0b\uff0c\u4e09\u751f\u6709\u5e78
|
||||
|
||||
moments.title=\u52a8\u6001
|
||||
moments.noMoments=\u8fd8\u6ca1\u6709\u77ac\u95f4\uff0c\u5feb\u53bb\u8bb0\u5f55\u5f53\u4e0b\u7684\u5fc3\u60c5\u5427 \U0001f319
|
||||
|
||||
photos.title=\u76f8\u518c
|
||||
|
||||
friends.title=\u53cb\u4eba\u5708
|
||||
|
||||
equipment.title=\u88c5\u5907
|
||||
|
||||
steam.title=Steam
|
||||
steam.homepage=Steam \u4e3b\u9875
|
||||
steam.level=\u7b49\u7ea7
|
||||
steam.ownedGames=\u62e5\u6709\u6e38\u620f
|
||||
steam.totalPlaytime=\u603b\u6e38\u73a9\u65f6\u957f
|
||||
steam.recentPlaytime=\u8fd1\u4e24\u5468
|
||||
steam.badges=\u5fbd\u7ae0
|
||||
steam.hours=\u5c0f\u65f6
|
||||
steam.recentlyPlayed=\u6700\u8fd1\u6e38\u73a9
|
||||
steam.gameLibrary=\u6e38\u620f\u5e93
|
||||
steam.lastPlayed=\u6700\u540e\u6e38\u73a9 {0}
|
||||
|
||||
douban.title=\u8c46\u74e3
|
||||
douban.wish=\u60f3\u770b
|
||||
douban.done=\u770b\u8fc7
|
||||
douban.wishRead=\u60f3\u8bfb
|
||||
douban.reading=\u5728\u8bfb
|
||||
douban.listened=\u542c\u8fc7
|
||||
douban.wishPlay=\u60f3\u73a9
|
||||
douban.played=\u73a9\u8fc7
|
||||
douban.wishListen=\u60f3\u542c
|
||||
douban.listening=\u5728\u542c
|
||||
douban.playing=\u5728\u73a9
|
||||
douban.myRating=\u6211\u7684\uff1a
|
||||
|
||||
messageboard.title=\u7559\u8a00\u677f
|
||||
messageboard.subtitle=\u5728\u8fd9\u91cc\u7559\u4e0b\u4f60\u7684\u8db3\u8ff9 \U0001f319
|
||||
|
||||
footer.poweredBy=Powered by Halo
|
||||
|
||||
error.404.title=\u9875\u9762\u672a\u627e\u5230
|
||||
error.404.desc=\u4f60\u5bfb\u627e\u7684\u9875\u9762\u4f3c\u4e4e\u5df2\u7ecf\u8ff7\u8def\u4e86
|
||||
error.404.home=\u8fd4\u56de\u9996\u9875
|
||||
error.404.back=\u8fd4\u56de\u4e0a\u9875
|
||||
error.500.title=\u670d\u52a1\u5668\u9519\u8bef
|
||||
error.500.desc=\u5c0f\u5c9b\u9047\u5230\u4e86\u4e00\u4e9b\u95ee\u9898\uff0c\u8bf7\u7a0d\u540e\u518d\u8bd5
|
||||
error.500.home=\u8fd4\u56de\u9996\u9875
|
||||
error.500.back=\u8fd4\u56de\u4e0a\u9875
|
||||
|
||||
sidebar.authorInfo=\u535a\u4e3b\u4fe1\u606f
|
||||
sidebar.latestPosts=\u6700\u65b0\u6587\u7ae0
|
||||
sidebar.recommendedPosts=\u63a8\u8350\u6587\u7ae0
|
||||
sidebar.timeProgress=\u65f6\u5149\u8fdb\u5ea6
|
||||
sidebar.dayProgress=\u65e5
|
||||
sidebar.monthProgress=\u6708
|
||||
sidebar.yearProgress=\u5e74
|
||||
sidebar.categories=\u5206\u7c7b
|
||||
sidebar.tags=\u6807\u7b7e
|
||||
|
||||
comment.style=\u6e29\u6696
|
||||
comment.showAvatar=\u663e\u793a\u5934\u50cf
|
||||
@@ -0,0 +1,126 @@
|
||||
common.home=\u9996\u9801
|
||||
common.search=\u641c\u5c0b
|
||||
common.themeSwitch=\u5207\u63db\u4e3b\u984c
|
||||
common.menu=\u9078\u55ae
|
||||
common.close=\u95dc\u9589
|
||||
common.toc=\u76ee\u9304
|
||||
common.openToc=\u6253\u958b\u76ee\u9304
|
||||
common.closeToc=\u95dc\u9589\u76ee\u9304
|
||||
common.newer=\u8f03\u65b0
|
||||
common.older=\u8f03\u820a
|
||||
common.loading=\u8f09\u5165\u4e2d...
|
||||
common.allLoaded=\u5df2\u8f09\u5165\u5168\u90e8\u6587\u7ae0
|
||||
common.noPosts=\u66ab\u7121\u6587\u7ae0
|
||||
common.postCount=\u5171 {0} \u7bc7\u6587\u7ae0
|
||||
common.readMore=\u95b1\u8b80\u66f4\u591a
|
||||
common.words=\u5b57
|
||||
common.readTime=\u5206\u9418
|
||||
common.views=\u95b1\u8b80
|
||||
common.like=\u6309\u8b9a
|
||||
common.pagination=\u5206\u9801
|
||||
common.toggleMenu=\u5207\u63db\u9078\u55ae
|
||||
common.allMomentsLoaded=\u5df2\u8f09\u5165\u5168\u90e8\u77ac\u9593
|
||||
common.categoryCount=\u5171 {0} \u500b\u5206\u985e
|
||||
common.tagCount=\u5171 {0} \u500b\u6a19\u7c64
|
||||
common.all=\u5168\u90e8
|
||||
common.noPhotos=\u66ab\u7121\u5716\u7247
|
||||
common.noPhotosInGroup=\u8a72\u5206\u7d44\u66ab\u7121\u5716\u7247
|
||||
common.pluginError=\u5916\u639b\u7a0b\u5f0f\u8f09\u5165\u7570\u5e38\uff0c\u8acb\u6aa2\u67e5\u5916\u639b\u7a0b\u5f0f\u72c0\u614b
|
||||
common.installPlugin=\u8a72\u529f\u80fd\u9700\u8981\u5b89\u88dd\u300c{0}\u300d\u5916\u639b\u7a0b\u5f0f\uff0c<a href="{1}">\u524d\u5f80\u61c9\u7528\u5e02\u5834\u5b89\u88dd</a>
|
||||
common.featured=\u7cbe\u9078
|
||||
common.latestPosts=\u6700\u65b0\u6587\u7ae0
|
||||
common.timeline=\u6642\u9593\u7dda
|
||||
common.viewAll=\u67e5\u770b\u5168\u90e8
|
||||
|
||||
navbar.search=\u641c\u5c0b
|
||||
navbar.themeSwitch=\u5207\u63db\u4e3b\u984c
|
||||
|
||||
hero.pinned=\u7f6e\u9802
|
||||
hero.posts=\u6587\u7ae0
|
||||
|
||||
article.previousPost=\u4e0a\u4e00\u7bc7
|
||||
article.nextPost=\u4e0b\u4e00\u7bc7
|
||||
article.toc=\u76ee\u9304
|
||||
article.wordCount=\u5b57
|
||||
article.readTime=\u5206\u9418
|
||||
article.views=\u95b1\u8b80
|
||||
article.relatedPosts=\u76f8\u95dc\u63a8\u85a6
|
||||
|
||||
share.title=\u5206\u4eab
|
||||
share.weibo=\u5fae\u535a
|
||||
share.twitter=X
|
||||
share.facebook=Facebook
|
||||
share.telegram=Telegram
|
||||
share.copyLink=\u8907\u88fd\u9023\u7d50
|
||||
share.copied=\u5df2\u8907\u88fd
|
||||
share.qrcode=\u4e8c\u7dad\u78bc
|
||||
|
||||
archives.title=\u6b78\u6a94
|
||||
|
||||
categories.title=\u5206\u985e
|
||||
|
||||
tags.title=\u6a19\u7c64
|
||||
|
||||
links.title=\u53cb\u93c8
|
||||
links.subtitle=\u5c71\u6c34\u4e00\u7a0b\uff0c\u4e09\u751f\u6709\u5e78
|
||||
|
||||
moments.title=\u52d5\u614b
|
||||
moments.noMoments=\u9084\u6c92\u6709\u77ac\u9593\uff0c\u5feb\u53bb\u8a18\u9304\u7576\u4e0b\u7684\u5fc3\u60c5\u5427 \U0001f319
|
||||
|
||||
photos.title=\u76f8\u7c3f
|
||||
|
||||
friends.title=\u53cb\u4eba\u5708
|
||||
|
||||
equipment.title=\u88dd\u5099
|
||||
|
||||
steam.title=Steam
|
||||
steam.homepage=Steam \u4e3b\u9801
|
||||
steam.level=\u7b49\u7d1a
|
||||
steam.ownedGames=\u64c1\u6709\u904a\u6232
|
||||
steam.totalPlaytime=\u7e3d\u904a\u73a9\u6642\u9577
|
||||
steam.recentPlaytime=\u8fd1\u5169\u9031
|
||||
steam.badges=\u5fbd\u7ae0
|
||||
steam.hours=\u5c0f\u6642
|
||||
steam.recentlyPlayed=\u6700\u8fd1\u904a\u73a9
|
||||
steam.gameLibrary=\u904a\u6232\u5eab
|
||||
steam.lastPlayed=\u6700\u5f8c\u904a\u73a9 {0}
|
||||
|
||||
douban.title=\u8c46\u74e3
|
||||
douban.wish=\u60f3\u770b
|
||||
douban.done=\u770b\u904e
|
||||
douban.wishRead=\u60f3\u8b80
|
||||
douban.reading=\u5728\u8b80
|
||||
douban.listened=\u807d\u904e
|
||||
douban.wishPlay=\u60f3\u73a9
|
||||
douban.played=\u73a9\u904e
|
||||
douban.wishListen=\u60f3\u807d
|
||||
douban.listening=\u5728\u807d
|
||||
douban.playing=\u5728\u73a9
|
||||
douban.myRating=\u6211\u7684\uff1a
|
||||
|
||||
messageboard.title=\u7559\u8a00\u677f
|
||||
messageboard.subtitle=\u5728\u9019\u88cf\u7559\u4e0b\u4f60\u7684\u8db3\u8de1 \U0001f319
|
||||
|
||||
footer.poweredBy=Powered by Halo
|
||||
|
||||
error.404.title=\u9801\u9762\u672a\u627e\u5230
|
||||
error.404.desc=\u4f60\u5c0b\u627e\u7684\u9801\u9762\u4f3c\u4e4e\u5df2\u7d93\u8ff7\u8def\u4e86
|
||||
error.404.home=\u8fd4\u56de\u9996\u9801
|
||||
error.404.back=\u8fd4\u56de\u4e0a\u9801
|
||||
error.500.title=\u4f3a\u670d\u5668\u932f\u8aa4
|
||||
error.500.desc=\u5c0f\u5cf6\u9047\u5230\u4e86\u4e00\u4e9b\u554f\u984c\uff0c\u8acb\u7a0d\u5f8c\u518d\u8a66
|
||||
error.500.home=\u8fd4\u56de\u9996\u9801
|
||||
error.500.back=\u8fd4\u56de\u4e0a\u9801
|
||||
|
||||
sidebar.authorInfo=\u535a\u4e3b\u8cc7\u8a0a
|
||||
sidebar.latestPosts=\u6700\u65b0\u6587\u7ae0
|
||||
sidebar.recommendedPosts=\u63a8\u85a6\u6587\u7ae0
|
||||
sidebar.timeProgress=\u6642\u5149\u9032\u5ea6
|
||||
sidebar.dayProgress=\u65e5
|
||||
sidebar.monthProgress=\u6708
|
||||
sidebar.yearProgress=\u5e74
|
||||
sidebar.categories=\u5206\u985e
|
||||
sidebar.tags=\u6a19\u7c64
|
||||
|
||||
comment.style=\u6eab\u6696
|
||||
comment.showAvatar=\u986f\u793a\u982d\u50cf
|
||||
@@ -126,5 +126,6 @@
|
||||
<a class="wi-error__back" href="javascript:history.back()">返回上页</a>
|
||||
</div>
|
||||
</div>
|
||||
<script>(function(){var lang=navigator.language||'';var locale=lang.startsWith('zh-TW')||lang.startsWith('zh-HK')?'zh_TW':lang.startsWith('zh')?'zh_CN':'en';var i18n={zh_CN:{title:'页面走丢了',desc:'你寻找的页面似乎不在这个小岛上',home:'回到首页',back:'返回上页',pageTitle:'页面走丢了'},zh_TW:{title:'頁面走丟了',desc:'你尋找的頁面似乎不在這個小島上',home:'回到首頁',back:'返回上頁',pageTitle:'頁面走丟了'},en:{title:'Page Not Found',desc:'The page you are looking for seems to have wandered off this island',home:'Back to Home',back:'Go Back',pageTitle:'Page Not Found'}};var t=i18n[locale];var el=document.querySelector('.wi-error__title');if(el)el.textContent=t.title;var desc=document.querySelector('.wi-error__desc');if(desc)desc.textContent=t.desc;var home=document.querySelector('.wi-error__home');if(home)home.textContent=t.home;var back=document.querySelector('.wi-error__back');if(back)back.textContent=t.back;document.title=t.pageTitle+' - WarmIsland';})();</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -126,5 +126,6 @@
|
||||
<a class="wi-error__back" href="javascript:history.back()">返回上页</a>
|
||||
</div>
|
||||
</div>
|
||||
<script>(function(){var lang=navigator.language||'';var locale=lang.startsWith('zh-TW')||lang.startsWith('zh-HK')?'zh_TW':lang.startsWith('zh')?'zh_CN':'en';var i18n={zh_CN:{title:'服务器开小差了',desc:'小岛遇到了一些问题,稍后再来看看吧',home:'回到首页',back:'返回上页',pageTitle:'服务器开小差了'},zh_TW:{title:'伺服器開小差了',desc:'小島遇到了一些問題,稍後再來看看吧',home:'回到首頁',back:'返回上頁',pageTitle:'伺服器開小差了'},en:{title:'Server Error',desc:'The island encountered some issues, please try again later',home:'Back to Home',back:'Go Back',pageTitle:'Server Error'}};var t=i18n[locale];var el=document.querySelector('.wi-error__title');if(el)el.textContent=t.title;var desc=document.querySelector('.wi-error__desc');if(desc)desc.textContent=t.desc;var home=document.querySelector('.wi-error__home');if(home)home.textContent=t.home;var back=document.querySelector('.wi-error__back');if(back)back.textContent=t.back;document.title=t.pageTitle+' - WarmIsland';})();</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+44
-22
@@ -22,15 +22,26 @@ spec:
|
||||
- $formkit: text
|
||||
name: label_search
|
||||
label: 搜索按钮标签
|
||||
value: 搜索
|
||||
- $formkit: text
|
||||
name: label_theme_switch
|
||||
label: 主题切换标签
|
||||
value: 切换主题
|
||||
- $formkit: text
|
||||
name: label_archives_title
|
||||
label: 归档页标题
|
||||
value: 归档
|
||||
- $formkit: select
|
||||
name: language
|
||||
label: 语言
|
||||
options:
|
||||
- label: 跟随浏览器
|
||||
value: auto
|
||||
- label: 简体中文
|
||||
value: zh_CN
|
||||
- label: 繁體中文
|
||||
value: zh_TW
|
||||
- label: English
|
||||
value: en
|
||||
value: auto
|
||||
help: 设置主题界面语言,选择"跟随浏览器"将根据浏览器语言自动匹配
|
||||
- group: style
|
||||
label: 总体样式
|
||||
formSchema:
|
||||
@@ -75,11 +86,6 @@ spec:
|
||||
- label: Wide
|
||||
value: wide
|
||||
value: medium
|
||||
- $formkit: switch
|
||||
name: layout_sidebar
|
||||
label: 启用侧边栏
|
||||
value: false
|
||||
help: 侧边栏功能开发中,暂不可用
|
||||
- $formkit: switch
|
||||
name: animation_enabled
|
||||
label: 启用动效
|
||||
@@ -191,11 +197,9 @@ spec:
|
||||
- $formkit: text
|
||||
name: home_pinned_title
|
||||
label: 置顶模块标题
|
||||
value: 置顶
|
||||
- $formkit: text
|
||||
name: home_posts_title
|
||||
label: 文章模块标题
|
||||
value: 文章
|
||||
- $formkit: switch
|
||||
name: home_card_show_visit
|
||||
label: 文章卡片显示阅读量
|
||||
@@ -228,27 +232,21 @@ spec:
|
||||
- $formkit: text
|
||||
name: home_label_newer
|
||||
label: 分页-较新标签
|
||||
value: 较新
|
||||
- $formkit: text
|
||||
name: home_label_older
|
||||
label: 分页-较旧标签
|
||||
value: 较旧
|
||||
- $formkit: text
|
||||
name: home_label_loading
|
||||
label: 无限滚动-加载中文案
|
||||
value: 加载中...
|
||||
- $formkit: text
|
||||
name: home_label_all_loaded
|
||||
label: 无限滚动-全部加载文案
|
||||
value: 已加载全部文章
|
||||
- $formkit: text
|
||||
name: home_label_no_posts
|
||||
label: 暂无文章文案
|
||||
value: 暂无文章。
|
||||
- $formkit: text
|
||||
name: home_label_post_count
|
||||
label: 文章数量文案({total}为占位符)
|
||||
value: 共 {total} 篇文章
|
||||
- group: article
|
||||
label: 文章
|
||||
formSchema:
|
||||
@@ -306,13 +304,42 @@ spec:
|
||||
- label: Cold
|
||||
value: cold
|
||||
value: warm
|
||||
- $formkit: select
|
||||
name: article_toc_expand
|
||||
label: 目录展开模式
|
||||
options:
|
||||
- label: 仅展开当前分组
|
||||
value: active
|
||||
- label: 全部展开
|
||||
value: all
|
||||
value: active
|
||||
help: 控制文章目录的展开方式
|
||||
- $formkit: switch
|
||||
name: article_show_related
|
||||
id: article_show_related
|
||||
label: 显示相关文章推荐
|
||||
value: false
|
||||
- $formkit: text
|
||||
name: article_related_title
|
||||
key: article_related_title
|
||||
label: 相关文章标题
|
||||
if: "$get(article_show_related).value === true"
|
||||
- $formkit: switch
|
||||
name: article_show_share
|
||||
id: article_show_share
|
||||
label: 显示分享按钮
|
||||
value: true
|
||||
- $formkit: text
|
||||
name: article_share_title
|
||||
key: article_share_title
|
||||
label: 分享区域标题
|
||||
if: "$get(article_show_share).value !== false"
|
||||
- group: moments
|
||||
label: 瞬间
|
||||
formSchema:
|
||||
- $formkit: text
|
||||
name: moments_page_title
|
||||
label: 页面标题
|
||||
value: 瞬间
|
||||
- $formkit: select
|
||||
name: moments_style
|
||||
label: 展示样式
|
||||
@@ -343,7 +370,6 @@ spec:
|
||||
- $formkit: text
|
||||
name: photos_page_title
|
||||
label: 页面标题
|
||||
value: 图库
|
||||
- $formkit: select
|
||||
name: photos_style
|
||||
label: 展示样式
|
||||
@@ -375,7 +401,6 @@ spec:
|
||||
- $formkit: text
|
||||
name: links_page_title
|
||||
label: 页面标题
|
||||
value: 友情链接
|
||||
- $formkit: select
|
||||
name: links_style
|
||||
label: 展示样式
|
||||
@@ -393,18 +418,15 @@ spec:
|
||||
- $formkit: text
|
||||
name: friends_page_title
|
||||
label: 页面标题
|
||||
value: 朋友圈
|
||||
- group: messageboard
|
||||
label: 留言板
|
||||
formSchema:
|
||||
- $formkit: text
|
||||
name: messageboard_title
|
||||
label: 留言板标题
|
||||
value: 留言板
|
||||
- $formkit: textarea
|
||||
name: messageboard_subtitle
|
||||
label: 留言板副标题
|
||||
value: 在这里留下你的足迹吧 🌙
|
||||
- group: comment
|
||||
label: 评论
|
||||
formSchema:
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
>
|
||||
<div class="wi-container">
|
||||
<div class="wi-section__header">
|
||||
<h2 class="wi-section__title" th:text="${theme.config?.home?.home_featured_title ?: '精选'}">精选</h2>
|
||||
<h2 class="wi-section__title" th:text="${theme.config?.home?.home_featured_title ?: #messages.msg('common.featured')}">精选</h2>
|
||||
</div>
|
||||
<div class="wi-featured">
|
||||
<a
|
||||
@@ -32,7 +32,7 @@
|
||||
<span
|
||||
class="wi-featured__pinned"
|
||||
th:if="${post.spec.pinned}"
|
||||
>置顶</span>
|
||||
th:text="#{hero.pinned}">Pinned</span>
|
||||
</div>
|
||||
<h3
|
||||
class="wi-featured__title"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
>
|
||||
<div class="wi-container">
|
||||
<div class="wi-section__header">
|
||||
<h2 class="wi-section__title" th:text="${theme.config?.home?.home_latest_title ?: '最新文章'}">最新文章</h2>
|
||||
<h2 class="wi-section__title" th:text="${theme.config?.home?.home_latest_title ?: #messages.msg('common.latestPosts')}">Latest Posts</h2>
|
||||
</div>
|
||||
<div
|
||||
class="wi-latest"
|
||||
@@ -58,8 +58,8 @@
|
||||
th:if="${posts.hasPrevious()}"
|
||||
th:href="@{${posts.prevUrl}}"
|
||||
class="wi-pagination__prev"
|
||||
th:text="${theme.config?.home?.home_label_newer ?: '较新'}"
|
||||
>← 较新</a>
|
||||
th:text="${theme.config?.home?.home_label_newer ?: #messages.msg('common.newer')}"
|
||||
>← Newer</a>
|
||||
<span
|
||||
class="wi-pagination__info"
|
||||
th:text="|${posts.page} / ${posts.totalPages}|"
|
||||
@@ -68,8 +68,8 @@
|
||||
th:if="${posts.hasNext()}"
|
||||
th:href="@{${posts.nextUrl}}"
|
||||
class="wi-pagination__next"
|
||||
th:text="${theme.config?.home?.home_label_older ?: '较旧'}"
|
||||
>较旧 →</a>
|
||||
th:text="${theme.config?.home?.home_label_older ?: #messages.msg('common.older')}"
|
||||
>Older →</a>
|
||||
</nav>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
>
|
||||
<div class="wi-container">
|
||||
<div class="wi-section__header">
|
||||
<h2 class="wi-section__title" th:text="${theme.config?.home?.home_message_wall_title ?: '留言墙'}">留言墙</h2>
|
||||
<h2 class="wi-section__title" th:text="${theme.config?.home?.home_message_wall_title ?: #messages.msg('messageboard.title')}">留言墙</h2>
|
||||
<span class="wi-section__accent"></span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -28,20 +28,20 @@
|
||||
|
||||
<div class="wi-mobile-menu__footer">
|
||||
<button
|
||||
th:if="${pluginFinder.available('PluginSearchWidget')}"
|
||||
th:if="${pluginFinder.available('PluginSearchWidget') and theme.config?.navbar?.navbar_show_search != false}"
|
||||
class="wi-mobile-menu__action-btn"
|
||||
type="button"
|
||||
aria-label="Search"
|
||||
onclick="SearchWidget.open()"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
|
||||
<span th:text="${theme.config?.basic?.label_search ?: '搜索'}">搜索</span>
|
||||
<span th:text="${theme.config?.basic?.label_search ?: #messages.msg('common.search')}">Search</span>
|
||||
</button>
|
||||
|
||||
<button class="wi-mobile-menu__action-btn wi-mobile-menu__theme-btn" type="button" aria-label="Toggle theme">
|
||||
<svg class="wi-mobile-menu__icon-moon" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/></svg>
|
||||
<svg class="wi-mobile-menu__icon-sun" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/></svg>
|
||||
<span class="wi-mobile-menu__theme-label" th:text="${theme.config?.basic?.label_theme_switch ?: '切换主题'}">切换主题</span>
|
||||
<span class="wi-mobile-menu__theme-label" th:text="${theme.config?.basic?.label_theme_switch ?: #messages.msg('common.themeSwitch')}">Switch Theme</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,7 @@ const pageConfig = findPageBySlug("moments");
|
||||
<th:block th:if="${pluginFinder.available('PluginMoments')}">
|
||||
<section class="wi-moments-section">
|
||||
<div class="wi-container">
|
||||
<h2 class="wi-moments-section__title" th:text="${pageConfig?.title ?: theme.config?.moments?.moments_title ?: '瞬间'}">瞬间</h2>
|
||||
<h2 class="wi-moments-section__title" th:text="${pageConfig?.title ?: theme.config?.moments?.moments_title ?: #messages.msg('moments.title')}">瞬间</h2>
|
||||
<div
|
||||
class="wi-moments-section__list"
|
||||
th:attr="data-style=${theme.config?.moments?.moments_style ?: 'timeline'}"
|
||||
@@ -29,7 +29,7 @@ const pageConfig = findPageBySlug("moments");
|
||||
</th:block>
|
||||
</div>
|
||||
<a th:href="@{'/moments'}" class="wi-moments-section__more">
|
||||
<span th:text="${theme.config?.home?.home_label_view_all ?: '查看全部'}">查看全部</span>
|
||||
<span th:text="${theme.config?.home?.home_label_view_all ?: #messages.msg('common.viewAll')}">查看全部</span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M5 12h14M12 5l7 7-7 7"/>
|
||||
</svg>
|
||||
|
||||
@@ -44,14 +44,14 @@ import ThemeSwitcher from "./ThemeSwitcher.vue";
|
||||
th:if="${pluginFinder.available('PluginSearchWidget') and theme.config?.navbar?.navbar_show_search != false}"
|
||||
class="wi-navbar__action-btn"
|
||||
type="button"
|
||||
th:aria-label="${theme.config?.basic?.label_search ?: '搜索'}"
|
||||
th:aria-label="${theme.config?.basic?.label_search ?: #messages.msg('common.search')}"
|
||||
onclick="SearchWidget.open()"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
|
||||
</button>
|
||||
|
||||
<th:block th:if="${theme.config?.navbar?.navbar_show_theme_switch != false}">
|
||||
<span th:attr="data-label=${theme.config?.basic?.label_theme_switch ?: '切换主题'}" style="display:inline-flex">
|
||||
<span th:attr="data-label=${theme.config?.basic?.label_theme_switch ?: #messages.msg('common.themeSwitch')}" style="display:inline-flex">
|
||||
<ThemeSwitcher client:idle />
|
||||
</span>
|
||||
</th:block>
|
||||
|
||||
@@ -9,7 +9,7 @@ const pageConfig = findPageBySlug("photos");
|
||||
<th:block th:if="${pluginFinder.available('PluginPhotos')}">
|
||||
<section class="wi-photos-section">
|
||||
<div class="wi-container">
|
||||
<h2 class="wi-photos-section__title" th:text="${pageConfig?.title ?: theme.config?.photos?.photos_title ?: '图库'}">图库</h2>
|
||||
<h2 class="wi-photos-section__title" th:text="${pageConfig?.title ?: theme.config?.photos?.photos_title ?: #messages.msg('photos.title')}">图库</h2>
|
||||
<div
|
||||
class="wi-photos-section__grid"
|
||||
th:attr="data-style=${theme.config?.photos?.photos_style ?: 'masonry'}, data-columns=${theme.config?.photos?.photos_columns ?: 3}"
|
||||
@@ -37,7 +37,7 @@ const pageConfig = findPageBySlug("photos");
|
||||
</th:block>
|
||||
</div>
|
||||
<a th:href="@{'/photos'}" class="wi-photos-section__more">
|
||||
<span th:text="${theme.config?.home?.home_label_view_all ?: '查看全部'}">查看全部</span>
|
||||
<span th:text="${theme.config?.home?.home_label_view_all ?: #messages.msg('common.viewAll')}">查看全部</span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M5 12h14M12 5l7 7-7 7"/>
|
||||
</svg>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
>
|
||||
<div class="wi-container">
|
||||
<div class="wi-section__header">
|
||||
<h2 class="wi-section__title" th:text="${theme.config?.home?.home_timeline_title ?: '时间线'}">时间线</h2>
|
||||
<h2 class="wi-section__title" th:text="${theme.config?.home?.home_timeline_title ?: #messages.msg('common.timeline')}">时间线</h2>
|
||||
<span class="wi-section__accent"></span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ const { pageTitle, contentClass, wide, home } = Astro.props;
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="zh" th:lang="${theme.config?.basic?.language ?: #locale.language}" th:classappend="${theme.config?.animation?.animation_enabled == false} ? 'wi-no-animations'">
|
||||
<html class={home ? 'wi-home-snap' : ''} th:lang="${#locale.toLanguageTag()}" th:classappend="${theme.config?.animation?.animation_enabled == false} ? 'wi-no-animations'" th:attr="data-lang=${theme.config?.basic?.language}">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
@@ -56,17 +56,47 @@ const { pageTitle, contentClass, wide, home } = Astro.props;
|
||||
th:href="${theme.config?.basic?.favicon ?: '/favicon.ico'}"
|
||||
/>
|
||||
<link rel="alternate" type="application/rss+xml" th:title="${site.title}" th:href="@{/feed.xml}" />
|
||||
<style th:if="${theme.config?.style?.accent_color}" th:utext="${':root { --accent: ' + theme.config?.style?.accent_color + '; --accent-hover: ' + theme.config?.style?.accent_color + '; }'}"></style>
|
||||
<style th:if="${theme.config?.style?.border_radius == 'small'}" th:utext="${':root { --radius-sm: 4px; --radius-md: 8px; --radius-lg: 16px; }'}"></style>
|
||||
<style th:if="${theme.config?.style?.border_radius == 'medium' or theme.config?.style?.border_radius == null}" th:utext="${':root { --radius-sm: 8px; --radius-md: 12px; --radius-lg: 24px; }'}"></style>
|
||||
<style th:if="${theme.config?.style?.border_radius == 'large'}" th:utext="${':root { --radius-sm: 12px; --radius-md: 20px; --radius-lg: 36px; }'}"></style>
|
||||
<style th:if="${theme.config?.style?.layout_container_width == 'narrow'}" th:utext="${'.wi-content-wrap { max-width: 680px; } .wi-content-wrap--wide { max-width: 1000px; } .wi-main--wide { max-width: 1200px; }'}"></style>
|
||||
<style th:if="${theme.config?.style?.layout_container_width == 'medium' or theme.config?.style?.layout_container_width == null}" th:utext="${'.wi-content-wrap { max-width: 800px; } .wi-content-wrap--wide { max-width: 1200px; } .wi-main--wide { max-width: 1400px; }'}"></style>
|
||||
<style th:if="${theme.config?.style?.layout_container_width == 'wide'}" th:utext="${'.wi-content-wrap { max-width: 900px; } .wi-content-wrap--wide { max-width: 1400px; } .wi-main--wide { max-width: 1600px; }'}"></style>
|
||||
<style th:if="${theme.config?.style?.custom_css}" th:utext="${theme.config?.style?.custom_css}"></style>
|
||||
<link rel="preconnect" href="https://cdn.jsdelivr.net" />
|
||||
<link rel="dns-prefetch" href="https://cdn.jsdelivr.net" />
|
||||
<style is:inline th:if="${theme.config?.style?.accent_color}" th:utext="${':root { --accent: ' + theme.config?.style?.accent_color + '; --accent-hover: ' + theme.config?.style?.accent_color + '; }'}">/*accent*/</style>
|
||||
<style is:inline th:if="${theme.config?.style?.border_radius == 'small'}" th:utext="${':root { --radius-sm: 4px; --radius-md: 8px; --radius-lg: 16px; }'}">/*radius*/</style>
|
||||
<style is:inline th:if="${theme.config?.style?.border_radius == 'medium' or theme.config?.style?.border_radius == null}" th:utext="${':root { --radius-sm: 8px; --radius-md: 12px; --radius-lg: 24px; }'}">/*radius*/</style>
|
||||
<style is:inline th:if="${theme.config?.style?.border_radius == 'large'}" th:utext="${':root { --radius-sm: 12px; --radius-md: 20px; --radius-lg: 36px; }'}">/*radius*/</style>
|
||||
<style is:inline th:if="${theme.config?.style?.layout_container_width == 'narrow'}" th:utext="${'.wi-content-wrap { max-width: 680px; } .wi-content-wrap--wide { max-width: 1000px; } .wi-main--wide { max-width: 1200px; }'}">/*width*/</style>
|
||||
<style is:inline th:if="${theme.config?.style?.layout_container_width == 'medium' or theme.config?.style?.layout_container_width == null}" th:utext="${'.wi-content-wrap { max-width: 800px; } .wi-content-wrap--wide { max-width: 1200px; } .wi-main--wide { max-width: 1400px; }'}">/*width*/</style>
|
||||
<style is:inline th:if="${theme.config?.style?.layout_container_width == 'wide'}" th:utext="${'.wi-content-wrap { max-width: 900px; } .wi-content-wrap--wide { max-width: 1400px; } .wi-main--wide { max-width: 1600px; }'}">/*width*/</style>
|
||||
<style is:inline th:if="${theme.config?.style?.custom_css}" th:utext="${theme.config?.style?.custom_css}">/*custom*/</style>
|
||||
<slot name="head" />
|
||||
</head>
|
||||
<body class="wi-body">
|
||||
<script is:inline>
|
||||
(function(){
|
||||
var lang=document.documentElement.getAttribute("data-lang");
|
||||
if(lang&&lang!=="auto"){
|
||||
var tag=lang.replace(/_/g,"-");
|
||||
var cookies=document.cookie.split(";");
|
||||
var current="";
|
||||
for(var i=0;i<cookies.length;i++){
|
||||
var c=cookies[i].trim();
|
||||
if(c.indexOf("language=")===0){current=c.substring(9);break;}
|
||||
}
|
||||
if(current!==tag){
|
||||
document.cookie="language="+tag+";path=/;max-age=31536000;SameSite=Lax";
|
||||
window.location.reload();
|
||||
}
|
||||
}else if(lang==="auto"){
|
||||
var cookies2=document.cookie.split(";");
|
||||
var hasCookie=false;
|
||||
for(var j=0;j<cookies2.length;j++){
|
||||
if(cookies2[j].trim().indexOf("language=")===0){hasCookie=true;break;}
|
||||
}
|
||||
if(hasCookie){
|
||||
document.cookie="language=;path=/;max-age=0;SameSite=Lax";
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<Navbar />
|
||||
<main class:list={["wi-main", { "wi-main--wide": wide || home, "wi-main--home": home }]}>
|
||||
{home ? (
|
||||
@@ -124,4 +154,11 @@ html.wi-no-animations .wi-reveal {
|
||||
transform: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.wi-post__content img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
@@ -4,14 +4,14 @@ import Layout from "../layouts/Layout.astro";
|
||||
|
||||
<Layout>
|
||||
<Fragment slot="head">
|
||||
<title th:text="|${theme.config?.basic?.label_archives_title ?: '归档'} - ${site.title}|"></title>
|
||||
<title th:text="|${theme.config?.basic?.label_archives_title ?: #messages.msg('archives.title')} - ${site.title}|"></title>
|
||||
</Fragment>
|
||||
|
||||
<div class="wi-archives">
|
||||
<header class="wi-archives__header">
|
||||
<h1 class="wi-archives__title" th:text="${theme.config?.basic?.label_archives_title ?: '归档'}">归档</h1>
|
||||
<h1 class="wi-archives__title" th:text="${theme.config?.basic?.label_archives_title ?: #messages.msg('archives.title')}">归档</h1>
|
||||
<span class="wi-page-accent"></span>
|
||||
<p class="wi-archives__subtitle" th:text="${#strings.replace(theme.config?.home?.home_label_post_count ?: '共 {total} 篇文章', '{total}', #strings.toString(archives.total))}"></p>
|
||||
<p class="wi-archives__subtitle" th:text="${#strings.replace(#messages.msg('common.postCount'), '{0}', #strings.toString(archives.total))}"></p>
|
||||
</header>
|
||||
|
||||
<section class="wi-archives__timeline" aria-label="Archive timeline">
|
||||
@@ -57,8 +57,8 @@ import Layout from "../layouts/Layout.astro";
|
||||
<div
|
||||
th:if="${archives.total == 0}"
|
||||
class="wi-archives__empty"
|
||||
th:text="${theme.config?.home?.home_label_no_posts ?: '暂无文章。'}"
|
||||
>暂无文章。</div>
|
||||
th:text="${theme.config?.home?.home_label_no_posts ?: #messages.msg('common.noPosts')}"
|
||||
>No posts yet.</div>
|
||||
</section>
|
||||
|
||||
<nav
|
||||
@@ -70,8 +70,8 @@ import Layout from "../layouts/Layout.astro";
|
||||
th:if="${archives.hasPrevious()}"
|
||||
th:href="@{${archives.prevUrl}}"
|
||||
class="wi-archives__page-link wi-archives__page-link--prev"
|
||||
th:text="${theme.config?.home?.home_label_newer ?: '较新'}"
|
||||
>← 较新</a>
|
||||
th:text="${theme.config?.home?.home_label_newer ?: #messages.msg('common.newer')}"
|
||||
>← Newer</a>
|
||||
<span
|
||||
class="wi-archives__page-info"
|
||||
th:text="|${archives.page} / ${archives.totalPages}|"
|
||||
@@ -80,8 +80,8 @@ import Layout from "../layouts/Layout.astro";
|
||||
th:if="${archives.hasNext()}"
|
||||
th:href="@{${archives.nextUrl}}"
|
||||
class="wi-archives__page-link wi-archives__page-link--next"
|
||||
th:text="${theme.config?.home?.home_label_older ?: '较旧'}"
|
||||
>较旧 →</a>
|
||||
th:text="${theme.config?.home?.home_label_older ?: #messages.msg('common.older')}"
|
||||
>Older →</a>
|
||||
</nav>
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
@@ -4,14 +4,14 @@ import Layout from "../layouts/Layout.astro";
|
||||
|
||||
<Layout>
|
||||
<Fragment slot="head">
|
||||
<title th:text="|分类 - ${site.title}|"></title>
|
||||
<title th:text="|#{categories.title} - ${site.title}|"></title>
|
||||
</Fragment>
|
||||
|
||||
<div class="wi-categories">
|
||||
<header class="wi-categories__header">
|
||||
<h1 class="wi-categories__title">分类</h1>
|
||||
<h1 class="wi-categories__title" th:text="#{categories.title}">分类</h1>
|
||||
<span class="wi-page-accent"></span>
|
||||
<p class="wi-categories__subtitle" th:text="|共 ${categories.size} 个分类|"></p>
|
||||
<p class="wi-categories__subtitle" th:text="${#messages.msg('common.categoryCount', ${categories.size})}"></p>
|
||||
</header>
|
||||
|
||||
<nav class="wi-categories__list" aria-label="Category list">
|
||||
|
||||
+135
-8
@@ -14,7 +14,7 @@ import Layout from "../layouts/Layout.astro";
|
||||
th:text="${category.spec.displayName}"
|
||||
></h1>
|
||||
<span class="wi-page-accent"></span>
|
||||
<p class="wi-category__subtitle" th:text="|共 ${posts.total} 篇文章|"></p>
|
||||
<p class="wi-category__subtitle" th:text="#{common.postCount(${posts.total})}"></p>
|
||||
<p
|
||||
th:if="${not #strings.isEmpty(category.spec.description)}"
|
||||
class="wi-category__description"
|
||||
@@ -22,13 +22,44 @@ import Layout from "../layouts/Layout.astro";
|
||||
></p>
|
||||
</header>
|
||||
|
||||
<th:block th:replace="~{fragments/post-list}"></th:block>
|
||||
<ul class="wi-category__list" role="list">
|
||||
<li
|
||||
th:each="post : ${posts.items}"
|
||||
class="wi-category__entry"
|
||||
>
|
||||
<a
|
||||
class="wi-category__entry-link"
|
||||
th:href="@{${post.status.permalink}}"
|
||||
>
|
||||
<div class="wi-category__entry-body">
|
||||
<time
|
||||
class="wi-category__entry-date"
|
||||
th:text="${#dates.format(post.spec.publishTime, 'yyyy-MM-dd')}"
|
||||
datetime="${post.spec.publishTime}"
|
||||
></time>
|
||||
<h2 class="wi-category__entry-title" th:text="${post.spec.title}"></h2>
|
||||
<p
|
||||
class="wi-category__entry-excerpt"
|
||||
th:text="${post.status.excerpt}"
|
||||
></p>
|
||||
</div>
|
||||
<img
|
||||
th:unless="${#strings.isEmpty(post.spec.cover)}"
|
||||
class="wi-category__entry-image"
|
||||
th:src="${post.spec.cover}"
|
||||
alt=""
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div
|
||||
th:if="${posts.total == 0}"
|
||||
class="wi-category__empty"
|
||||
th:text="${theme.config?.home?.home_label_no_posts ?: '暂无文章。'}"
|
||||
>暂无文章。</div>
|
||||
th:text="${theme.config?.home?.home_label_no_posts ?: #messages.msg('common.noPosts')}"
|
||||
>No posts yet.</div>
|
||||
|
||||
<nav
|
||||
th:if="${posts.totalPages gt 1}"
|
||||
@@ -39,8 +70,8 @@ import Layout from "../layouts/Layout.astro";
|
||||
th:if="${posts.hasPrevious()}"
|
||||
th:href="@{${posts.prevUrl}}"
|
||||
class="wi-category__page-link wi-category__page-link--prev"
|
||||
th:text="${theme.config?.home?.home_label_newer ?: '较新'}"
|
||||
>← 较新</a>
|
||||
th:text="${theme.config?.home?.home_label_newer ?: #messages.msg('common.newer')}"
|
||||
>← Newer</a>
|
||||
<span
|
||||
class="wi-category__page-info"
|
||||
th:text="|${posts.page} / ${posts.totalPages}|"
|
||||
@@ -49,8 +80,8 @@ import Layout from "../layouts/Layout.astro";
|
||||
th:if="${posts.hasNext()}"
|
||||
th:href="@{${posts.nextUrl}}"
|
||||
class="wi-category__page-link wi-category__page-link--next"
|
||||
th:text="${theme.config?.home?.home_label_older ?: '较旧'}"
|
||||
>较旧 →</a>
|
||||
th:text="${theme.config?.home?.home_label_older ?: #messages.msg('common.older')}"
|
||||
>Older →</a>
|
||||
</nav>
|
||||
</div>
|
||||
</Layout>
|
||||
@@ -97,6 +128,90 @@ import Layout from "../layouts/Layout.astro";
|
||||
line-height: var(--leading-normal);
|
||||
}
|
||||
|
||||
.wi-category__list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: grid;
|
||||
gap: var(--space-lg);
|
||||
}
|
||||
|
||||
.wi-category__entry {
|
||||
border-bottom: 1px dashed var(--rule);
|
||||
transition: background var(--duration-fast) var(--ease-out-quart);
|
||||
}
|
||||
|
||||
.wi-category__entry:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.wi-category__entry:hover {
|
||||
background: var(--bg-raised);
|
||||
margin: 0 calc(-1 * var(--space-md));
|
||||
padding-left: var(--space-md);
|
||||
padding-right: var(--space-md);
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
.wi-category__entry-link {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) 200px;
|
||||
gap: var(--space-lg);
|
||||
padding: var(--space-lg) 0;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.wi-category__entry-body {
|
||||
display: grid;
|
||||
gap: 0.35rem;
|
||||
}
|
||||
|
||||
.wi-category__entry-date {
|
||||
color: var(--ink-3);
|
||||
font-size: var(--text-sm);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.wi-category__entry-title {
|
||||
font-family: var(--font-sans);
|
||||
font-size: var(--text-lg);
|
||||
font-weight: 600;
|
||||
color: var(--ink);
|
||||
line-height: var(--leading-snug);
|
||||
margin: 0.25rem 0;
|
||||
transition: color var(--duration-fast) var(--ease-out-quart);
|
||||
}
|
||||
|
||||
.wi-category__entry-link:hover .wi-category__entry-title {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.wi-category__entry-excerpt {
|
||||
margin: 0;
|
||||
font-size: var(--text-sm);
|
||||
color: var(--ink-2);
|
||||
line-height: var(--leading-normal);
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.wi-category__entry-image {
|
||||
width: 200px;
|
||||
height: 140px;
|
||||
object-fit: cover;
|
||||
border-radius: var(--radius-sm);
|
||||
align-self: center;
|
||||
transition: transform var(--duration-fast) var(--ease-out-quart);
|
||||
}
|
||||
|
||||
.wi-category__entry:hover .wi-category__entry-image {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
.wi-category__empty {
|
||||
color: var(--ink-3);
|
||||
font-size: var(--text-md);
|
||||
@@ -127,4 +242,16 @@ import Layout from "../layouts/Layout.astro";
|
||||
.wi-category__page-info {
|
||||
color: var(--ink-3);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.wi-category__entry-link {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.wi-category__entry-image {
|
||||
width: 100%;
|
||||
height: 180px;
|
||||
order: -1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
+25
-13
@@ -10,7 +10,7 @@ import Layout from "../layouts/Layout.astro";
|
||||
<section class="wi-douban">
|
||||
<div class="wi-container">
|
||||
<div class="wi-douban__header">
|
||||
<h1 class="wi-douban__title" th:text="${title}">豆瓣</h1>
|
||||
<h1 class="wi-douban__title" th:text="${title ?: #messages.msg('douban.title')}">Douban</h1>
|
||||
<span class="wi-page-accent"></span>
|
||||
</div>
|
||||
|
||||
@@ -32,63 +32,63 @@ import Layout from "../layouts/Layout.astro";
|
||||
class="wi-douban__filter-tag wi-douban__filter-tag--sm"
|
||||
th:href="@{/douban(type=${currentType},status='wish')}"
|
||||
th:classappend="${hasStatus and currentStatus == 'wish'} ? 'wi-douban__filter-tag--active' : ''"
|
||||
>想看</a>
|
||||
th:text="#{douban.wish}">Wish</a>
|
||||
<a
|
||||
class="wi-douban__filter-tag wi-douban__filter-tag--sm"
|
||||
th:href="@{/douban(type=${currentType},status='done')}"
|
||||
th:classappend="${(!hasStatus and isDefaultType) or (hasStatus and currentStatus == 'done')} ? 'wi-douban__filter-tag--active' : ''"
|
||||
>看过</a>
|
||||
th:text="#{douban.done}">Done</a>
|
||||
</th:block>
|
||||
<th:block th:if="${currentType == 'book'}">
|
||||
<a
|
||||
class="wi-douban__filter-tag wi-douban__filter-tag--sm"
|
||||
th:href="@{/douban(type='book',status='wish')}"
|
||||
th:classappend="${hasStatus and currentStatus == 'wish'} ? 'wi-douban__filter-tag--active' : ''"
|
||||
>想读</a>
|
||||
th:text="#{douban.wishRead}">Wish</a>
|
||||
<a
|
||||
class="wi-douban__filter-tag wi-douban__filter-tag--sm"
|
||||
th:href="@{/douban(type='book',status='doing')}"
|
||||
th:classappend="${hasStatus and currentStatus == 'doing'} ? 'wi-douban__filter-tag--active' : ''"
|
||||
>在读</a>
|
||||
th:text="#{douban.reading}">Reading</a>
|
||||
<a
|
||||
class="wi-douban__filter-tag wi-douban__filter-tag--sm"
|
||||
th:href="@{/douban(type='book',status='done')}"
|
||||
th:classappend="${(!hasStatus and isDefaultType) or (hasStatus and currentStatus == 'done')} ? 'wi-douban__filter-tag--active' : ''"
|
||||
>读过</a>
|
||||
th:text="#{douban.done}">Done</a>
|
||||
</th:block>
|
||||
<th:block th:if="${currentType == 'music'}">
|
||||
<a
|
||||
class="wi-douban__filter-tag wi-douban__filter-tag--sm"
|
||||
th:href="@{/douban(type='music',status='wish')}"
|
||||
th:classappend="${hasStatus and currentStatus == 'wish'} ? 'wi-douban__filter-tag--active' : ''"
|
||||
>想听</a>
|
||||
th:text="#{douban.wishListen}">Wish</a>
|
||||
<a
|
||||
class="wi-douban__filter-tag wi-douban__filter-tag--sm"
|
||||
th:href="@{/douban(type='music',status='doing')}"
|
||||
th:classappend="${hasStatus and currentStatus == 'doing'} ? 'wi-douban__filter-tag--active' : ''"
|
||||
>在听</a>
|
||||
th:text="#{douban.listening}">Listening</a>
|
||||
<a
|
||||
class="wi-douban__filter-tag wi-douban__filter-tag--sm"
|
||||
th:href="@{/douban(type='music',status='done')}"
|
||||
th:classappend="${(!hasStatus and isDefaultType) or (hasStatus and currentStatus == 'done')} ? 'wi-douban__filter-tag--active' : ''"
|
||||
>听过</a>
|
||||
th:text="#{douban.listened}">Listened</a>
|
||||
</th:block>
|
||||
<th:block th:if="${currentType == 'game'}">
|
||||
<a
|
||||
class="wi-douban__filter-tag wi-douban__filter-tag--sm"
|
||||
th:href="@{/douban(type='game',status='wish')}"
|
||||
th:classappend="${hasStatus and currentStatus == 'wish'} ? 'wi-douban__filter-tag--active' : ''"
|
||||
>想玩</a>
|
||||
th:text="#{douban.wishPlay}">Wish</a>
|
||||
<a
|
||||
class="wi-douban__filter-tag wi-douban__filter-tag--sm"
|
||||
th:href="@{/douban(type='game',status='doing')}"
|
||||
th:classappend="${hasStatus and currentStatus == 'doing'} ? 'wi-douban__filter-tag--active' : ''"
|
||||
>在玩</a>
|
||||
th:text="#{douban.playing}">Playing</a>
|
||||
<a
|
||||
class="wi-douban__filter-tag wi-douban__filter-tag--sm"
|
||||
th:href="@{/douban(type='game',status='done')}"
|
||||
th:classappend="${(!hasStatus and isDefaultType) or (hasStatus and currentStatus == 'done')} ? 'wi-douban__filter-tag--active' : ''"
|
||||
>玩过</a>
|
||||
th:text="#{douban.played}">Played</a>
|
||||
</th:block>
|
||||
</div>
|
||||
|
||||
@@ -120,6 +120,7 @@ import Layout from "../layouts/Layout.astro";
|
||||
class="wi-douban__card"
|
||||
th:each="item : ${doubans.items}"
|
||||
th:if="${!hasGenre or #sets.contains(item.spec?.genres, currentGenre)}"
|
||||
th:attr="data-type=${currentType}"
|
||||
>
|
||||
<a
|
||||
class="wi-douban__card-link"
|
||||
@@ -161,7 +162,7 @@ import Layout from "../layouts/Layout.astro";
|
||||
class="wi-douban__my-score"
|
||||
th:if="${!#strings.isEmpty(item.faves?.score)}"
|
||||
>
|
||||
我的:<th:block th:text="${item.faves?.score}"></th:block>
|
||||
<span th:text="#{douban.myRating}">My:</span><th:block th:text="${item.faves?.score}"></th:block>
|
||||
</span>
|
||||
<span
|
||||
class="wi-douban__year"
|
||||
@@ -299,6 +300,12 @@ import Layout from "../layouts/Layout.astro";
|
||||
background: var(--bg);
|
||||
}
|
||||
|
||||
.wi-douban__card[data-type="music"] .wi-douban__poster {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.wi-douban__poster-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -408,5 +415,10 @@ import Layout from "../layouts/Layout.astro";
|
||||
width: 64px;
|
||||
height: 90px;
|
||||
}
|
||||
|
||||
.wi-douban__card[data-type="music"] .wi-douban__poster {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
---
|
||||
import Navbar from "../components/Navbar.astro";
|
||||
import MobileMenu from "../components/MobileMenu.astro";
|
||||
import "../styles/main.scss";
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="zh" th:lang="${theme.config?.basic?.language ?: #locale.language}" th:classappend="${theme.config?.animation?.animation_enabled == false} ? 'wi-no-animations'">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<script is:inline th:attr="data-scheme=${theme.config?.style?.color_scheme}">
|
||||
(function () {
|
||||
var stored = localStorage.getItem("wi-theme");
|
||||
var prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||
var scheme = null;
|
||||
if (document.currentScript && document.currentScript.getAttribute("data-scheme")) {
|
||||
scheme = document.currentScript.getAttribute("data-scheme");
|
||||
}
|
||||
var isDark = false;
|
||||
if (stored === "dark") { isDark = true; }
|
||||
else if (stored === "light") { isDark = false; }
|
||||
else if (scheme === "dark") { isDark = true; }
|
||||
else if (scheme === "light") { isDark = false; }
|
||||
else if (!stored && prefersDark) { isDark = true; }
|
||||
if (isDark) {
|
||||
document.documentElement.classList.add("dark");
|
||||
document.documentElement.setAttribute("data-color-scheme", "dark");
|
||||
} else {
|
||||
document.documentElement.classList.remove("dark");
|
||||
document.documentElement.setAttribute("data-color-scheme", "light");
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<title th:text="|${settings.title} - ${site.title}|"></title>
|
||||
<link rel="stylesheet" type="text/css" th:href="@{/plugins/footprint/assets/static/css/footprint.css(version=${version})}" />
|
||||
<link rel="stylesheet" type="text/css" th:href="@{/plugins/footprint/assets/static/font/result.css(version=${version})}" />
|
||||
<script type="text/javascript" th:src="@{/plugins/footprint/assets/static/js/jquery-3.6.0.min.js}"></script>
|
||||
<script type="text/javascript">
|
||||
window._AMapSecurityConfig = {
|
||||
securityJsCode: /*[[${settings.gaoDeKey}]]*/''
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript" th:src="|https://webapi.amap.com/maps?v=2.0&key=${settings.gaoDeKey}|"></script>
|
||||
<script type="text/javascript" th:src="@{/plugins/footprint/assets/static/js/footprint.js(version=${version})}"></script>
|
||||
<script th:inline="javascript">
|
||||
window.FOOTPRINT_CONFIG = {
|
||||
amapKey: /*[[${settings.gaoDeKey}]]*/'',
|
||||
footprints: [],
|
||||
title: /*[[${settings.title}]]*/ '足迹',
|
||||
logoName: /*[[${settings.logoName}]]*/ '足迹',
|
||||
describe: /*[[${settings.describe}]]*/ '描述',
|
||||
hsla: /*[[${settings.hsla}]]*/ '200, 100%, 50%',
|
||||
mapStyle: /*[[${settings.mapStyle}]]*/ 'amap://styles/normal'
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body id="footprint-page">
|
||||
<Navbar />
|
||||
<MobileMenu />
|
||||
|
||||
<div class="footprint-container">
|
||||
<div id="footprint-map"></div>
|
||||
|
||||
<div class="logo-container">
|
||||
<h1 class="footprint-logo" th:text="${settings.logoName}">足迹<span class="logo-version">2024</span></h1>
|
||||
<p class="footprint-slogan" th:text="${settings.describe}">每一处足迹都充满了故事,那是对人生的思考和无限的风光。</p>
|
||||
</div>
|
||||
|
||||
<div class="map-controls">
|
||||
<div class="likcc-layer-selector">
|
||||
<button class="likcc-layer-btn active" data-type="normal">
|
||||
<svg class="likcc-layer-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
||||
<path d="M9 9h6v6H9z"></path>
|
||||
</svg>
|
||||
<span>标准图</span>
|
||||
</button>
|
||||
<button class="likcc-layer-btn" data-type="satellite">
|
||||
<svg class="likcc-layer-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path>
|
||||
</svg>
|
||||
<span>卫星图</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="likcc-feature-toggles">
|
||||
<label class="likcc-toggle-item">
|
||||
<input type="checkbox" data-type="road">
|
||||
<div class="likcc-toggle-switch">
|
||||
<div class="likcc-toggle-slider"></div>
|
||||
</div>
|
||||
<div class="likcc-toggle-content">
|
||||
<svg class="likcc-toggle-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M3 7v10a4 4 0 004 4h10a4 4 0 004-4V7a4 4 0 00-4-4H7a4 4 0 00-4 4z"></path>
|
||||
<path d="M9 12h6"></path>
|
||||
</svg>
|
||||
<span class="likcc-toggle-label">路网</span>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="likcc-toggle-item">
|
||||
<input type="checkbox" data-type="traffic">
|
||||
<div class="likcc-toggle-switch">
|
||||
<div class="likcc-toggle-slider"></div>
|
||||
</div>
|
||||
<div class="likcc-toggle-content">
|
||||
<svg class="likcc-toggle-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"></path>
|
||||
</svg>
|
||||
<span class="likcc-toggle-label">路况</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="likcc-zoom-controls">
|
||||
<button class="likcc-zoom-btn" id="zoom-out">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<circle cx="11" cy="11" r="8"></circle>
|
||||
<path d="M21 21l-4.35-4.35"></path>
|
||||
<line x1="8" y1="11" x2="14" y2="11"></line>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="likcc-zoom-btn" id="zoom-in">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<circle cx="11" cy="11" r="8"></circle>
|
||||
<path d="M21 21l-4.35-4.35"></path>
|
||||
<line x1="11" y1="8" x2="11" y2="14"></line>
|
||||
<line x1="8" y1="11" x2="14" y2="11"></line>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="likcc-scale-display">
|
||||
<div class="likcc-scale-bar"></div>
|
||||
<span class="likcc-scale-text" id="scale-text">1000 公里</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<style>
|
||||
#footprint-page {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#footprint-page .footprint-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: calc(100vh - 72px);
|
||||
margin-top: 72px;
|
||||
}
|
||||
|
||||
#footprint-page #footprint-map {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -4,7 +4,7 @@ import Layout from "../layouts/Layout.astro";
|
||||
|
||||
<Layout wide>
|
||||
<Fragment slot="head">
|
||||
<title th:text="|${theme.config?.friends?.friends_page_title ?: '朋友圈'} - ${site.title}|"></title>
|
||||
<title th:text="|${theme.config?.friends?.friends_page_title ?: #messages.msg('friends.title')} - ${site.title}|"></title>
|
||||
</Fragment>
|
||||
|
||||
<section
|
||||
@@ -15,9 +15,9 @@ import Layout from "../layouts/Layout.astro";
|
||||
<div class="wi-friends-page__header">
|
||||
<h1
|
||||
class="wi-friends-page__title"
|
||||
th:text="${theme.config?.friends?.friends_page_title ?: '朋友圈'}"
|
||||
th:text="${theme.config?.friends?.friends_page_title ?: #messages.msg('friends.title')}"
|
||||
>
|
||||
朋友圈
|
||||
Friends Circle
|
||||
</h1>
|
||||
<span class="wi-page-accent"></span>
|
||||
</div>
|
||||
@@ -87,8 +87,9 @@ import Layout from "../layouts/Layout.astro";
|
||||
th:if="${friends.hasPrevious()}"
|
||||
th:href="@{${friends.prevUrl}}"
|
||||
class="wi-friends-page__page-link"
|
||||
th:text="#{common.newer}"
|
||||
>
|
||||
← 上一页
|
||||
← Newer
|
||||
</a>
|
||||
<span
|
||||
class="wi-friends-page__page-info"
|
||||
@@ -98,8 +99,9 @@ import Layout from "../layouts/Layout.astro";
|
||||
th:if="${friends.hasNext()}"
|
||||
th:href="@{${friends.nextUrl}}"
|
||||
class="wi-friends-page__page-link"
|
||||
th:text="#{common.older}"
|
||||
>
|
||||
下一页 →
|
||||
Older →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -111,11 +113,11 @@ import Layout from "../layouts/Layout.astro";
|
||||
>
|
||||
<div class="wi-container">
|
||||
<div class="wi-friends-page__header">
|
||||
<h1 class="wi-friends-page__title">朋友圈</h1>
|
||||
<h1 class="wi-friends-page__title" th:text="#{friends.title}">Friends Circle</h1>
|
||||
<span class="wi-page-accent"></span>
|
||||
</div>
|
||||
<div class="wi-friends-page__empty">
|
||||
<p>朋友圈功能需要安装「朋友圈」插件,<a href="https://www.halo.run/store/apps/app-friends">前往应用市场安装</a></p>
|
||||
<p th:utext="#{common.installPlugin('Friends Circle', 'https://www.halo.run/store/apps/app-friends')}">This feature requires the Friends Circle plugin</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
+76
-9
@@ -13,6 +13,7 @@ import HeroSection from "../components/HeroSection.astro";
|
||||
<div
|
||||
class="wi-home-content"
|
||||
th:classappend="${theme.config?.hero?.hero_enabled != false} ? 'wi-home-content--with-hero'"
|
||||
th:attr="data-i18n-all-loaded=#{common.allLoaded},data-i18n-loading=#{common.loading},data-i18n-words=#{common.words},data-i18n-read-time=#{common.readTime},data-i18n-views=#{common.views}"
|
||||
>
|
||||
<section
|
||||
class="wi-home-pinned"
|
||||
@@ -20,7 +21,7 @@ import HeroSection from "../components/HeroSection.astro";
|
||||
>
|
||||
<div class="wi-container">
|
||||
<div class="wi-section__header">
|
||||
<h2 class="wi-section__title" th:text="${theme.config?.home?.home_pinned_title ?: '置顶'}">置顶</h2>
|
||||
<h2 class="wi-section__title" th:text="${theme.config?.home?.home_pinned_title ?: #messages.msg('hero.pinned')}">置顶</h2>
|
||||
</div>
|
||||
<div class="wi-pinned">
|
||||
<a
|
||||
@@ -65,7 +66,7 @@ import HeroSection from "../components/HeroSection.astro";
|
||||
<section class="wi-home-posts" id="wi-home-posts">
|
||||
<div class="wi-container">
|
||||
<div class="wi-section__header">
|
||||
<h2 class="wi-section__title" th:text="${theme.config?.home?.home_posts_title ?: '文章'}">文章</h2>
|
||||
<h2 class="wi-section__title" th:text="${theme.config?.home?.home_posts_title ?: #messages.msg('hero.posts')}">文章</h2>
|
||||
</div>
|
||||
<div class="wi-flow" id="wi-post-grid">
|
||||
<article
|
||||
@@ -128,7 +129,7 @@ import HeroSection from "../components/HeroSection.astro";
|
||||
class="wi-flow__stat"
|
||||
th:if="${theme.config?.home?.home_card_show_visit ?: true}"
|
||||
>
|
||||
<th:block th:text="${post.stats?.visit ?: 0}"></th:block> 阅读
|
||||
<th:block th:text="${post.stats?.visit ?: 0}"></th:block> <th:block th:text="#{common.views}">阅读</th:block>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -152,7 +153,7 @@ import HeroSection from "../components/HeroSection.astro";
|
||||
th:if="${posts.hasPrevious()}"
|
||||
th:href="@{${posts.prevUrl}}"
|
||||
class="wi-pagination__prev"
|
||||
th:text="${theme.config?.home?.home_label_newer ?: '较新'}"
|
||||
th:text="${theme.config?.home?.home_label_newer ?: #messages.msg('common.newer')}"
|
||||
>← 较新</a>
|
||||
<span
|
||||
class="wi-pagination__info"
|
||||
@@ -162,18 +163,18 @@ import HeroSection from "../components/HeroSection.astro";
|
||||
th:if="${posts.hasNext()}"
|
||||
th:href="@{${posts.nextUrl}}"
|
||||
class="wi-pagination__next"
|
||||
th:text="${theme.config?.home?.home_label_older ?: '较旧'}"
|
||||
th:text="${theme.config?.home?.home_label_older ?: #messages.msg('common.older')}"
|
||||
>较旧 →</a>
|
||||
</nav>
|
||||
|
||||
<div
|
||||
th:if="${posts.hasNext() and theme.config?.home?.home_post_loading == 'infinite_scroll'}"
|
||||
id="wi-infinite-scroll-sentinel"
|
||||
th:attr="data-next-url=${posts.nextUrl}, data-all-loaded-text=${theme.config?.home?.home_label_all_loaded ?: '已加载全部文章'}"
|
||||
th:attr="data-next-url=${posts.nextUrl}, data-all-loaded-text=${theme.config?.home?.home_label_all_loaded ?: #messages.msg('common.allLoaded')}"
|
||||
>
|
||||
<div class="wi-infinite-scroll__loader">
|
||||
<div class="wi-infinite-scroll__spinner"></div>
|
||||
<span th:text="${theme.config?.home?.home_label_loading ?: '加载中...'}">加载中...</span>
|
||||
<span th:text="${theme.config?.home?.home_label_loading ?: #messages.msg('common.loading')}">加载中...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -181,7 +182,7 @@ import HeroSection from "../components/HeroSection.astro";
|
||||
th:if="${!posts.hasNext() and posts.totalPages gt 1 and theme.config?.home?.home_post_loading == 'infinite_scroll'}"
|
||||
class="wi-infinite-scroll__end"
|
||||
>
|
||||
<span th:text="${theme.config?.home?.home_label_all_loaded ?: '已加载全部文章'}">已加载全部文章</span>
|
||||
<span th:text="${theme.config?.home?.home_label_all_loaded ?: #messages.msg('common.allLoaded')}">已加载全部文章</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -194,9 +195,10 @@ import HeroSection from "../components/HeroSection.astro";
|
||||
if (!sentinel) return;
|
||||
|
||||
var grid = document.getElementById("wi-post-grid");
|
||||
var i18nEl = document.querySelector(".wi-home-content");
|
||||
var loading = false;
|
||||
var nextUrl = sentinel.getAttribute("data-next-url");
|
||||
var allLoadedText = sentinel.getAttribute("data-all-loaded-text") || "已加载全部文章";
|
||||
var allLoadedText = sentinel.getAttribute("data-all-loaded-text") || (i18nEl && i18nEl.getAttribute("data-i18n-all-loaded")) || "All posts loaded";
|
||||
|
||||
var observer = new IntersectionObserver(
|
||||
function (entries) {
|
||||
@@ -302,6 +304,71 @@ import HeroSection from "../components/HeroSection.astro";
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script is:inline>
|
||||
(function () {
|
||||
var hero = document.getElementById("wi-hero");
|
||||
var content = document.querySelector(".wi-home-content--with-hero");
|
||||
if (!hero || !content) return;
|
||||
|
||||
var isSnapping = false;
|
||||
var heroHeight = window.innerHeight;
|
||||
|
||||
window.addEventListener("resize", function () {
|
||||
heroHeight = window.innerHeight;
|
||||
}, { passive: true });
|
||||
|
||||
function snapTo(targetY) {
|
||||
if (isSnapping) return;
|
||||
isSnapping = true;
|
||||
window.scrollTo({ top: targetY, behavior: "smooth" });
|
||||
var timer = setTimeout(function () {
|
||||
isSnapping = false;
|
||||
}, 800);
|
||||
if ("onscrollend" in window) {
|
||||
window.addEventListener(
|
||||
"scrollend",
|
||||
function () {
|
||||
clearTimeout(timer);
|
||||
isSnapping = false;
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("wheel", function (e) {
|
||||
if (isSnapping) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
var y = window.scrollY;
|
||||
if (y < heroHeight && e.deltaY > 0) {
|
||||
e.preventDefault();
|
||||
snapTo(heroHeight);
|
||||
} else if (y > 0 && y <= heroHeight && e.deltaY < 0) {
|
||||
e.preventDefault();
|
||||
snapTo(0);
|
||||
}
|
||||
}, { passive: false });
|
||||
|
||||
var touchStartY = 0;
|
||||
window.addEventListener("touchstart", function (e) {
|
||||
touchStartY = e.touches[0].clientY;
|
||||
}, { passive: true });
|
||||
|
||||
window.addEventListener("touchend", function (e) {
|
||||
if (isSnapping) return;
|
||||
var diff = touchStartY - e.changedTouches[0].clientY;
|
||||
var y = window.scrollY;
|
||||
if (y < heroHeight && diff > 30) {
|
||||
snapTo(heroHeight);
|
||||
} else if (y > 0 && y <= heroHeight && diff < -30) {
|
||||
snapTo(0);
|
||||
}
|
||||
}, { passive: true });
|
||||
})();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.wi-home-content {
|
||||
position: relative;
|
||||
|
||||
@@ -4,7 +4,7 @@ import Layout from "../layouts/Layout.astro";
|
||||
|
||||
<Layout wide>
|
||||
<Fragment slot="head">
|
||||
<title th:text="|${theme.config?.links?.links_page_title ?: '友情链接'} - ${site.title}|"></title>
|
||||
<title th:text="|${theme.config?.links?.links_page_title ?: #messages.msg('links.title')} - ${site.title}|"></title>
|
||||
</Fragment>
|
||||
|
||||
<section
|
||||
@@ -16,11 +16,11 @@ import Layout from "../layouts/Layout.astro";
|
||||
<div class="wi-links__header">
|
||||
<h1
|
||||
class="wi-links__title"
|
||||
th:text="${theme.config?.links?.links_page_title ?: '友情链接'}"
|
||||
th:text="${theme.config?.links?.links_page_title ?: #messages.msg('links.title')}"
|
||||
>
|
||||
友情链接
|
||||
</h1>
|
||||
<p class="wi-links__subtitle">山水一程,三生有幸</p>
|
||||
<p class="wi-links__subtitle" th:text="#{links.subtitle}">Mountains and rivers, a journey of a thousand miles</p>
|
||||
<span class="wi-page-accent"></span>
|
||||
</div>
|
||||
|
||||
@@ -154,6 +154,7 @@ import Layout from "../layouts/Layout.astro";
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.wi-links__card-glow {
|
||||
@@ -184,6 +185,7 @@ import Layout from "../layouts/Layout.astro";
|
||||
-webkit-backdrop-filter: blur(16px);
|
||||
border: 1px solid var(--glass-border);
|
||||
border-radius: 16px;
|
||||
flex: 1;
|
||||
transition:
|
||||
transform var(--duration-normal) var(--ease-out-expo),
|
||||
box-shadow var(--duration-normal) var(--ease-out-expo),
|
||||
|
||||
+13
-11
@@ -5,13 +5,13 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
|
||||
<Layout>
|
||||
<Fragment slot="head">
|
||||
<title th:text="|${theme.config?.moments?.moments_page_title ?: '瞬间'} - ${site.title}|"></title>
|
||||
<title th:text="|${theme.config?.moments?.moments_page_title ?: #messages.msg('moments.title')} - ${site.title}|"></title>
|
||||
</Fragment>
|
||||
|
||||
<section class="wi-moments-page">
|
||||
<section class="wi-moments-page" th:attr="data-i18n-all-moments-loaded=#{common.allMomentsLoaded}">
|
||||
<div class="wi-container">
|
||||
<div class="wi-moments-page__header">
|
||||
<h1 class="wi-moments-page__title" th:text="${theme.config?.moments?.moments_page_title ?: '瞬间'}">瞬间</h1>
|
||||
<h1 class="wi-moments-page__title" th:text="${theme.config?.moments?.moments_page_title ?: #messages.msg('moments.title')}">瞬间</h1>
|
||||
<span class="wi-page-accent"></span>
|
||||
</div>
|
||||
|
||||
@@ -77,7 +77,7 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
</th:block>
|
||||
<th:block th:if="${momentsResult == null or #lists.isEmpty(momentsResult.items)}">
|
||||
<div class="wi-moments-page__empty">
|
||||
<p>还没有瞬间,快去记录当下的心情吧 🌙</p>
|
||||
<p th:text="#{moments.noMoments}">No moments yet</p>
|
||||
</div>
|
||||
</th:block>
|
||||
</div>
|
||||
@@ -133,7 +133,7 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
</th:block>
|
||||
<th:block th:if="${momentsResult == null or #lists.isEmpty(momentsResult.items)}">
|
||||
<div class="wi-moments-page__empty">
|
||||
<p>还没有瞬间,快去记录当下的心情吧 🌙</p>
|
||||
<p th:text="#{moments.noMoments}">No moments yet</p>
|
||||
</div>
|
||||
</th:block>
|
||||
</div>
|
||||
@@ -189,7 +189,7 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
</th:block>
|
||||
<th:block th:if="${momentsResult == null or #lists.isEmpty(momentsResult.items)}">
|
||||
<div class="wi-moments-page__empty">
|
||||
<p>还没有瞬间,快去记录当下的心情吧 🌙</p>
|
||||
<p th:text="#{moments.noMoments}">No moments yet</p>
|
||||
</div>
|
||||
</th:block>
|
||||
</div>
|
||||
@@ -204,13 +204,13 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
class="wi-moments-page__page-btn"
|
||||
th:if="${momentsResult.hasPrevious()}"
|
||||
th:href="${momentsResult.prevUrl}"
|
||||
>← 较新</a>
|
||||
th:text="#{common.newer}">Newer</a>
|
||||
<span class="wi-moments-page__page-spacer" th:if="${momentsResult.hasPrevious() and momentsResult.hasNext()}"></span>
|
||||
<a
|
||||
class="wi-moments-page__page-btn"
|
||||
th:if="${momentsResult.hasNext()}"
|
||||
th:href="${momentsResult.nextUrl}"
|
||||
>较旧 →</a>
|
||||
th:text="#{common.older}">Older</a>
|
||||
</nav>
|
||||
|
||||
<div
|
||||
@@ -220,7 +220,7 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
></div>
|
||||
<th:block th:if="${momentFinder == null}">
|
||||
<div class="wi-moments-page__empty">
|
||||
<p>瞬间插件加载异常,请检查插件状态</p>
|
||||
<p th:text="#{common.pluginError}">Plugin error</p>
|
||||
</div>
|
||||
</th:block>
|
||||
</div>
|
||||
@@ -228,7 +228,7 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
|
||||
<th:block th:unless="${pluginFinder.available('PluginMoments')}">
|
||||
<div class="wi-moments-page__empty">
|
||||
<p>瞬间功能需要安装「瞬间」插件,<a href="https://www.halo.run/store/apps/app-hqbe">前往应用市场安装</a></p>
|
||||
<p th:utext="#{common.installPlugin('Moments', 'https://www.halo.run/store/apps/app-hqbe')}">This feature requires the Moments plugin</p>
|
||||
</div>
|
||||
</th:block>
|
||||
</div>
|
||||
@@ -414,7 +414,9 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
sentinel.style.display = "none";
|
||||
var endMsg = document.createElement("div");
|
||||
endMsg.className = "wi-moments-page__empty";
|
||||
endMsg.innerHTML = "<p>已加载全部瞬间</p>";
|
||||
var momentsSection = document.querySelector(".wi-moments-page");
|
||||
var allMomentsText = momentsSection ? momentsSection.getAttribute("data-i18n-all-moments-loaded") : "All moments loaded";
|
||||
endMsg.innerHTML = "<p>" + allMomentsText + "</p>";
|
||||
sentinel.parentNode.appendChild(endMsg);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import Layout from "../layouts/Layout.astro";
|
||||
<Layout>
|
||||
<Fragment slot="head">
|
||||
<title
|
||||
th:text="|${theme.config?.messageboard?.messageboard_title ?: '留言板'} - ${site.title}|"
|
||||
th:text="|${theme.config?.messageboard?.messageboard_title ?: #messages.msg('messageboard.title')} - ${site.title}|"
|
||||
></title>
|
||||
</Fragment>
|
||||
|
||||
@@ -14,12 +14,12 @@ import Layout from "../layouts/Layout.astro";
|
||||
<span class="wi-messageboard__deco">"</span>
|
||||
<h1
|
||||
class="wi-messageboard__title"
|
||||
th:text="${theme.config?.messageboard?.messageboard_title ?: '留言板'}"
|
||||
th:text="${theme.config?.messageboard?.messageboard_title ?: #messages.msg('messageboard.title')}"
|
||||
></h1>
|
||||
<span class="wi-page-accent"></span>
|
||||
<p
|
||||
class="wi-messageboard__subtitle"
|
||||
th:text="${theme.config?.messageboard?.messageboard_subtitle}"
|
||||
th:text="${theme.config?.messageboard?.messageboard_subtitle ?: #messages.msg('messageboard.subtitle')}"
|
||||
></p>
|
||||
</header>
|
||||
|
||||
|
||||
+10
-14
@@ -5,7 +5,7 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
|
||||
<Layout wide>
|
||||
<Fragment slot="head">
|
||||
<title th:text="|${title ?: (theme.config?.photos?.photos_page_title ?: '图库')} - ${site.title}|"></title>
|
||||
<title th:text="|${title ?: (theme.config?.photos?.photos_page_title ?: #messages.msg('photos.title'))} - ${site.title}|"></title>
|
||||
</Fragment>
|
||||
|
||||
<section class="wi-photos-page">
|
||||
@@ -13,9 +13,9 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
<div class="wi-photos-page__header">
|
||||
<h1
|
||||
class="wi-photos-page__title"
|
||||
th:text="${theme.config?.photos?.photos_page_title ?: '图库'}"
|
||||
th:text="${theme.config?.photos?.photos_page_title ?: #messages.msg('photos.title')}"
|
||||
>
|
||||
图库
|
||||
Gallery
|
||||
</h1>
|
||||
<span class="wi-page-accent"></span>
|
||||
</div>
|
||||
@@ -30,8 +30,9 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
th:href="@{${photoUrl.list()}}"
|
||||
class="wi-photos-page__group-link"
|
||||
th:classappend="${#strings.isEmpty(currentGroup)} ? 'wi-photos-page__group-link--active' : ''"
|
||||
th:text="#{common.all}"
|
||||
>
|
||||
全部
|
||||
All
|
||||
</a>
|
||||
<a
|
||||
th:each="group : ${groups}"
|
||||
@@ -48,7 +49,7 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
<div class="wi-photos-page__all-groups">
|
||||
<th:block th:if="${showUngrouped and photos != null and !#lists.isEmpty(photos.items)}">
|
||||
<div class="wi-photos-page__section">
|
||||
<h2 class="wi-photos-page__section-title">全部</h2>
|
||||
<h2 class="wi-photos-page__section-title" th:text="#{common.all}">All</h2>
|
||||
<div
|
||||
class="wi-photos-page__grid"
|
||||
th:attr="data-style=${theme.config?.photos?.photos_style ?: 'masonry'}, data-columns=${theme.config?.photos?.photos_columns ?: 3}"
|
||||
@@ -240,7 +241,7 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
</div>
|
||||
</div>
|
||||
<div class="wi-photos-page__empty" th:if="${#lists.isEmpty(group.photos)}">
|
||||
<p>该分组暂无图片</p>
|
||||
<p th:text="#{common.noPhotosInGroup}">No photos in this group.</p>
|
||||
</div>
|
||||
</th:block>
|
||||
</th:block>
|
||||
@@ -248,25 +249,20 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
</th:block>
|
||||
|
||||
<div class="wi-photos-page__empty" th:if="${#lists.isEmpty(groups) and !(showUngrouped and photos != null and !#lists.isEmpty(photos.items))}">
|
||||
<p>暂无图片</p>
|
||||
<p th:text="#{common.noPhotos}">No photos yet.</p>
|
||||
</div>
|
||||
</th:block>
|
||||
|
||||
<th:block th:if="${groups == null}">
|
||||
<div class="wi-photos-page__empty">
|
||||
<p>图库插件加载异常,请检查插件状态</p>
|
||||
<p th:text="#{common.pluginError}">Plugin error</p>
|
||||
</div>
|
||||
</th:block>
|
||||
</th:block>
|
||||
|
||||
<th:block th:unless="${pluginFinder.available('PluginPhotos')}">
|
||||
<div class="wi-photos-page__empty">
|
||||
<p>
|
||||
图库功能需要安装「图库」插件,<a
|
||||
href="https://www.halo.run/store/apps/app-PgHgw"
|
||||
>前往应用市场安装</a
|
||||
>
|
||||
</p>
|
||||
<p th:utext="#{common.installPlugin('Gallery', 'https://www.halo.run/store/apps/app-PgHgw')}">This feature requires the Gallery plugin</p>
|
||||
</div>
|
||||
</th:block>
|
||||
</div>
|
||||
|
||||
+313
-16
@@ -3,14 +3,42 @@ import Layout from "../layouts/Layout.astro";
|
||||
import LightGallery from "../components/LightGallery.astro";
|
||||
---
|
||||
|
||||
<Layout>
|
||||
<Layout wide={true}>
|
||||
<Fragment slot="head">
|
||||
<title th:text="|${post.spec.title} - ${site.title}|"></title>
|
||||
<meta th:if="${post.spec.cover}" property="og:image" th:content="${post.spec.cover}" />
|
||||
<meta property="og:title" th:content="${post.spec.title}" />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:url" th:content="${post.status.permalink}" />
|
||||
<meta th:if="${post.status.excerpt}" property="og:description" th:content="${post.status.excerpt}" />
|
||||
<meta property="og:site_name" th:content="${site.title}" />
|
||||
<meta name="twitter:card" content="summary_large_image" th:if="${post.spec.cover}" />
|
||||
<meta name="twitter:card" content="summary" th:unless="${post.spec.cover}" />
|
||||
<meta name="twitter:title" th:content="${post.spec.title}" />
|
||||
<meta th:if="${post.spec.cover}" name="twitter:image" th:content="${post.spec.cover}" />
|
||||
<meta th:if="${post.status.excerpt}" name="twitter:description" th:content="${post.status.excerpt}" />
|
||||
<meta property="article:published_time" th:content="${#dates.format(post.spec.publishTime, 'yyyy-MM-dd')}" />
|
||||
<th:block th:if="${post.categories != null and !post.categories.isEmpty()}">
|
||||
<meta property="article:section" th:content="${post.categories[0].spec.displayName}" />
|
||||
</th:block>
|
||||
<th:block th:if="${post.tags != null and !post.tags.isEmpty()}">
|
||||
<meta th:each="tag : ${post.tags}" property="article:tag" th:content="${tag.spec.displayName}" />
|
||||
</th:block>
|
||||
<script type="application/ld+json" th:utext="${'{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Article",
|
||||
"headline": "' + post.spec.title + '",
|
||||
"datePublished": "' + #dates.format(post.spec.publishTime, "yyyy-MM-dd") + '",
|
||||
"author": {
|
||||
"@type": "Person",
|
||||
"name": "' + (post.contributors != null and !post.contributors.isEmpty() ? post.contributors[0].displayName : site.title) + '"
|
||||
}' + (!#strings.isEmpty(post.spec.cover) ? ', "image": "' + post.spec.cover + '"' : '') + (!#strings.isEmpty(post.status.excerpt) ? ', "description": "' + #strings.replace(post.status.excerpt, '"', '\\"') + '"' : '') + '
|
||||
}'}"></script>
|
||||
</Fragment>
|
||||
|
||||
<div class="wi-reading-progress" id="wi-reading-progress"></div>
|
||||
|
||||
<article class="wi-post">
|
||||
<article class="wi-post" th:attr="data-i18n-words=#{common.words},data-i18n-read-time=#{common.readTime}">
|
||||
<header class="wi-post__header">
|
||||
<div
|
||||
th:if="${theme.config?.article?.article_show_cover != false and !#strings.isEmpty(post.spec.cover)}"
|
||||
@@ -82,18 +110,18 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
th:if="${theme.config?.article?.article_show_word_count ?: true}"
|
||||
class="wi-post__stat-item"
|
||||
id="wi-word-count"
|
||||
>-- 字</span>
|
||||
>-- words</span>
|
||||
<span
|
||||
th:if="${theme.config?.article?.article_show_visit_count ?: true}"
|
||||
class="wi-post__stat-item"
|
||||
>
|
||||
<th:block th:text="${post.stats?.visit ?: 0}"></th:block> 阅读
|
||||
<th:block th:text="${post.stats?.visit ?: 0}"></th:block> <th:block th:text="#{common.views}"></th:block>
|
||||
</span>
|
||||
<span
|
||||
th:if="${theme.config?.article?.article_show_read_time ?: false}"
|
||||
class="wi-post__stat-item"
|
||||
id="wi-read-time"
|
||||
>-- 分钟</span>
|
||||
>-- min read</span>
|
||||
</span>
|
||||
</th:block>
|
||||
</div>
|
||||
@@ -109,10 +137,10 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
th:if="${theme.config?.article?.article_show_toc ?: true}"
|
||||
class="wi-toc"
|
||||
id="wi-toc"
|
||||
th:attr="data-position=${theme.config?.article?.article_toc_position ?: 'left'}"
|
||||
th:attr="data-position=${theme.config?.article?.article_toc_position ?: 'left'},data-expand=${theme.config?.article?.article_toc_expand ?: 'active'}"
|
||||
>
|
||||
<div class="wi-toc__header">
|
||||
<span class="wi-toc__title">目录</span>
|
||||
<span class="wi-toc__title" th:text="#{article.toc}">目录</span>
|
||||
</div>
|
||||
<nav class="wi-toc__nav" id="wi-toc-nav"></nav>
|
||||
</aside>
|
||||
@@ -128,6 +156,27 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="wi-post__share" th:if="${theme.config?.article?.article_show_share != false}" th:with="shareUrl=${post.status.permalink}, shareTitle=${post.spec.title}">
|
||||
<span class="wi-post__share-label" th:text="${theme.config?.article?.article_share_title ?: #messages.msg('share.title')}">分享</span>
|
||||
<div class="wi-post__share-buttons">
|
||||
<a class="wi-post__share-btn wi-post__share-btn--weibo" th:href="'https://service.weibo.com/share/share.php?url=' + ${shareUrl} + '&title=' + ${shareTitle}" target="_blank" rel="noopener noreferrer" title="Weibo">
|
||||
<svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor"><path d="M10.098 20.323c-3.977.391-7.414-1.406-7.672-4.02-.259-2.609 2.759-5.047 6.74-5.441 3.979-.394 7.413 1.404 7.671 4.018.259 2.6-2.759 5.049-6.739 5.443zM9.05 17.219c-.384.616-1.208.884-1.829.602-.612-.279-.793-.991-.406-1.593.379-.595 1.176-.861 1.793-.583.631.283.822.997.442 1.574zm1.27-1.627c-.141.237-.449.353-.689.253-.236-.09-.307-.361-.164-.584.14-.227.44-.34.682-.246.24.085.318.352.171.577zm.176-2.719c-1.893-.494-4.033.45-4.857 2.118-.836 1.704-.026 3.591 1.886 4.21 1.983.642 4.318-.341 5.132-2.145.8-1.752-.145-3.681-2.161-4.183zM17.616 3.68c-.998-.27-1.652-.068-1.877.136-.225.207-.094.544.28.726.377.186.856.072 1.122-.258.268-.328.391-.545.475-.604zm2.471 1.947c-1.278-1.399-3.398-1.878-5.217-1.176-1.818.704-2.478 2.523-1.527 4.099.956 1.582 3.168 2.202 5.011 1.395 1.84-.804 2.977-2.899 1.733-4.318zM20.4 4.44c1.462 1.599.936 4.076-.878 5.478-1.816 1.402-4.556 1.402-6.128-.006-1.573-1.404-1.3-3.834.554-5.314 1.854-1.478 4.99-1.759 6.452-.158z"/></svg>
|
||||
</a>
|
||||
<a class="wi-post__share-btn wi-post__share-btn--twitter" th:href="'https://twitter.com/intent/tweet?url=' + ${shareUrl} + '&text=' + ${shareTitle}" target="_blank" rel="noopener noreferrer" title="X">
|
||||
<svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>
|
||||
</a>
|
||||
<a class="wi-post__share-btn wi-post__share-btn--facebook" th:href="'https://www.facebook.com/sharer/sharer.php?u=' + ${shareUrl}" target="_blank" rel="noopener noreferrer" title="Facebook">
|
||||
<svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor"><path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/></svg>
|
||||
</a>
|
||||
<a class="wi-post__share-btn wi-post__share-btn--telegram" th:href="'https://t.me/share/url?url=' + ${shareUrl} + '&text=' + ${shareTitle}" target="_blank" rel="noopener noreferrer" title="Telegram">
|
||||
<svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor"><path d="M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 0 1 .171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.479.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z"/></svg>
|
||||
</a>
|
||||
<button class="wi-post__share-btn wi-post__share-btn--copy" type="button" th:attr="data-url=${shareUrl}" title="Copy Link">
|
||||
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<th:block th:if="${theme.config?.article?.article_show_nav == true}">
|
||||
<nav class="wi-post__nav" aria-label="Post navigation">
|
||||
<th:block
|
||||
@@ -138,7 +187,7 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
th:href="@{${cursor.previous.status.permalink}}"
|
||||
class="wi-post__nav-link wi-post__nav-link--prev"
|
||||
>
|
||||
<span class="wi-post__nav-label">上一篇</span>
|
||||
<span class="wi-post__nav-label" th:text="#{article.previousPost}">上一篇</span>
|
||||
<span
|
||||
class="wi-post__nav-title"
|
||||
th:text="${cursor.previous.spec.title}"
|
||||
@@ -153,7 +202,7 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
th:href="@{${cursor.next.status.permalink}}"
|
||||
class="wi-post__nav-link wi-post__nav-link--next"
|
||||
>
|
||||
<span class="wi-post__nav-label">下一篇</span>
|
||||
<span class="wi-post__nav-label" th:text="#{article.nextPost}">下一篇</span>
|
||||
<span
|
||||
class="wi-post__nav-title"
|
||||
th:text="${cursor.next.spec.title}"
|
||||
@@ -167,6 +216,23 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
</nav>
|
||||
</th:block>
|
||||
|
||||
<th:block th:if="${theme.config?.article?.article_show_related == true}">
|
||||
<section class="wi-post__related" th:with="relatedCat=${post.categories != null and !post.categories.isEmpty()} ? ${post.categories[0].metadata.name} : null, relatedPosts=${relatedCat != null} ? ${postFinder.list({size: 3, categoryName: relatedCat})} : ${postFinder.list({size: 3})}">
|
||||
<h2 class="wi-post__related-title" th:text="${theme.config?.article?.article_related_title ?: #messages.msg('article.relatedPosts')}">相关推荐</h2>
|
||||
<div class="wi-post__related-grid">
|
||||
<a th:each="rp : ${relatedPosts.items}" th:if="${rp.metadata.name != post.metadata.name}" th:href="@{${rp.status.permalink}}" class="wi-post__related-card">
|
||||
<div class="wi-post__related-cover" th:if="${!#strings.isEmpty(rp.spec.cover)}">
|
||||
<img th:src="${rp.spec.cover}" th:alt="${rp.spec.title}" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="wi-post__related-body">
|
||||
<h3 class="wi-post__related-name" th:text="${rp.spec.title}"></h3>
|
||||
<time class="wi-post__related-date" th:text="${#dates.format(rp.spec.publishTime, 'yyyy-MM-dd')}"></time>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</th:block>
|
||||
|
||||
<div class="wi-post__comment" th:attr="data-comment-style=${theme.config?.comment?.comment_style ?: 'warm'},data-show-avatar=${theme.config?.comment?.comment_show_avatar != false}">
|
||||
<halo:comment
|
||||
th:if="${haloCommentEnabled}"
|
||||
@@ -182,7 +248,7 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
class="wi-toc-fab"
|
||||
id="wi-toc-fab"
|
||||
type="button"
|
||||
aria-label="打开目录"
|
||||
th:aria-label="#{common.openToc}"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="8" x2="21" y1="6" y2="6"/><line x1="8" x2="21" y1="12" y2="12"/><line x1="8" x2="21" y1="18" y2="18"/><line x1="3" x2="3.01" y1="6" y2="6"/><line x1="3" x2="3.01" y1="12" y2="12"/><line x1="3" x2="3.01" y1="18" y2="18"/></svg>
|
||||
</button>
|
||||
@@ -195,8 +261,8 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
<div class="wi-toc-drawer__overlay"></div>
|
||||
<div class="wi-toc-drawer__panel">
|
||||
<div class="wi-toc-drawer__header">
|
||||
<span class="wi-toc-drawer__title">目录</span>
|
||||
<button class="wi-toc-drawer__close" type="button" aria-label="关闭目录">
|
||||
<span class="wi-toc-drawer__title" th:text="#{article.toc}">目录</span>
|
||||
<button class="wi-toc-drawer__close" type="button" th:aria-label="#{common.closeToc}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
@@ -263,6 +329,9 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
|
||||
var showWordCount = document.getElementById("wi-word-count");
|
||||
var showReadTime = document.getElementById("wi-read-time");
|
||||
var articleEl = document.querySelector(".wi-post");
|
||||
var wordsLabel = articleEl ? articleEl.getAttribute("data-i18n-words") : "words";
|
||||
var readTimeLabel = articleEl ? articleEl.getAttribute("data-i18n-read-time") : "min read";
|
||||
|
||||
if (showWordCount || showReadTime) {
|
||||
var text = (body.textContent || body.innerText || "").trim();
|
||||
@@ -270,10 +339,10 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
var readMinutes = Math.max(1, Math.ceil(charCount / 500));
|
||||
|
||||
if (showWordCount) {
|
||||
showWordCount.textContent = charCount + " 字";
|
||||
showWordCount.textContent = charCount + " " + wordsLabel;
|
||||
}
|
||||
if (showReadTime) {
|
||||
showReadTime.textContent = readMinutes + " 分钟";
|
||||
showReadTime.textContent = readMinutes + " " + readTimeLabel;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,7 +422,13 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
entries.forEach(function (entry) {
|
||||
if (entry.isIntersecting) {
|
||||
tocLinks.forEach(function (l) { l.classList.remove("wi-toc__link--active"); });
|
||||
tocGroups.forEach(function (g) { g.classList.remove("wi-toc__group--active"); g.classList.remove("wi-toc__group--expanded"); });
|
||||
var tocExpandMode = tocAside ? (tocAside.getAttribute("data-expand") || "active") : "active";
|
||||
tocGroups.forEach(function (g) {
|
||||
g.classList.remove("wi-toc__group--active");
|
||||
if (tocExpandMode !== "all") {
|
||||
g.classList.remove("wi-toc__group--expanded");
|
||||
}
|
||||
});
|
||||
|
||||
var activeLink = tocNav.querySelector('a[href="#' + entry.target.id + '"]');
|
||||
if (activeLink) {
|
||||
@@ -456,6 +531,28 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
});
|
||||
}
|
||||
|
||||
var copyBtn = document.querySelector(".wi-post__share-btn--copy");
|
||||
if (copyBtn) {
|
||||
copyBtn.addEventListener("click", function () {
|
||||
var url = copyBtn.getAttribute("data-url");
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(url).then(function () {
|
||||
copyBtn.classList.add("wi-post__share-btn--copied");
|
||||
setTimeout(function () { copyBtn.classList.remove("wi-post__share-btn--copied"); }, 2000);
|
||||
});
|
||||
} else {
|
||||
var ta = document.createElement("textarea");
|
||||
ta.value = url;
|
||||
document.body.appendChild(ta);
|
||||
ta.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(ta);
|
||||
copyBtn.classList.add("wi-post__share-btn--copied");
|
||||
setTimeout(function () { copyBtn.classList.remove("wi-post__share-btn--copied"); }, 2000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var btn = document.querySelector(".wi-like-btn");
|
||||
if (!btn) return;
|
||||
var postName = btn.getAttribute("data-post-name");
|
||||
@@ -493,6 +590,21 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
console.error("Like error:", err);
|
||||
});
|
||||
});
|
||||
|
||||
var lazyImgs = document.querySelectorAll(".wi-post__content img[loading='lazy']");
|
||||
lazyImgs.forEach(function (img) {
|
||||
if (img.complete && img.naturalWidth > 0) {
|
||||
img.setAttribute("data-blur", "loaded");
|
||||
} else {
|
||||
img.setAttribute("data-blur", "true");
|
||||
img.addEventListener("load", function () {
|
||||
img.setAttribute("data-blur", "loaded");
|
||||
});
|
||||
img.addEventListener("error", function () {
|
||||
img.setAttribute("data-blur", "loaded");
|
||||
});
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</Layout>
|
||||
@@ -680,7 +792,8 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
.wi-post__body .ai-summary,
|
||||
.wi-post__body [class*="ai-summary"],
|
||||
.wi-post__body [class*="ai-abstract"],
|
||||
.wi-post__body .abstract {
|
||||
.wi-post__body .abstract,
|
||||
.wi-post__body [class*="likcc-article-summary"] {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
@@ -693,6 +806,22 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
margin-block: 1.5em;
|
||||
}
|
||||
|
||||
.wi-post__content img {
|
||||
transition: filter 0.4s ease, opacity 0.4s ease;
|
||||
}
|
||||
|
||||
.wi-post__content img[data-blur="true"] {
|
||||
filter: blur(20px);
|
||||
opacity: 0.6;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.wi-post__content img[data-blur="loaded"] {
|
||||
filter: blur(0);
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.wi-post__body a {
|
||||
text-decoration: underline;
|
||||
text-decoration-thickness: 1px;
|
||||
@@ -928,6 +1057,85 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
|
||||
.wi-post__share {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: var(--space-md);
|
||||
padding-top: var(--space-md);
|
||||
}
|
||||
|
||||
.wi-post__share-label {
|
||||
font-size: var(--text-sm);
|
||||
color: var(--ink-3);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.wi-post__share-buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.wi-post__share-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid var(--rule);
|
||||
background: var(--bg-raised);
|
||||
color: var(--ink-3);
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
transition: color 0.2s ease, border-color 0.2s ease, background 0.2s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.wi-post__share-btn:hover {
|
||||
color: var(--accent);
|
||||
border-color: var(--accent);
|
||||
background: color-mix(in srgb, var(--accent) 6%, var(--bg));
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.wi-post__share-btn--weibo:hover {
|
||||
color: #e6162d;
|
||||
border-color: #e6162d;
|
||||
background: color-mix(in srgb, #e6162d 6%, var(--bg));
|
||||
}
|
||||
|
||||
.wi-post__share-btn--facebook:hover {
|
||||
color: #1877f2;
|
||||
border-color: #1877f2;
|
||||
background: color-mix(in srgb, #1877f2 6%, var(--bg));
|
||||
}
|
||||
|
||||
.wi-post__share-btn--telegram:hover {
|
||||
color: #0088cc;
|
||||
border-color: #0088cc;
|
||||
background: color-mix(in srgb, #0088cc 6%, var(--bg));
|
||||
}
|
||||
|
||||
.wi-post__share-btn--copied {
|
||||
color: #22c55e;
|
||||
border-color: #22c55e;
|
||||
}
|
||||
|
||||
.wi-post__share-btn--copied::after {
|
||||
content: '✓';
|
||||
font-size: 14px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.wi-post__share-btn--copied svg {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.wi-post__share-btn--copy {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.wi-post__comment {
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
@@ -985,6 +1193,90 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.wi-post__related {
|
||||
padding-top: var(--space-xl);
|
||||
border-top: 1px solid var(--rule);
|
||||
}
|
||||
|
||||
.wi-post__related-title {
|
||||
font-family: var(--font-sans);
|
||||
font-size: var(--text-lg);
|
||||
font-weight: 700;
|
||||
color: var(--ink);
|
||||
margin-bottom: var(--space-lg);
|
||||
}
|
||||
|
||||
.wi-post__related-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: var(--space-md);
|
||||
}
|
||||
|
||||
.wi-post__related-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
background: var(--bg-raised);
|
||||
border: 1px solid var(--rule);
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
transition: transform var(--duration-fast) var(--ease-out-quart), box-shadow var(--duration-fast) var(--ease-out-quart);
|
||||
}
|
||||
|
||||
.wi-post__related-card:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.wi-post__related-cover {
|
||||
aspect-ratio: 16 / 9;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.wi-post__related-cover img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: transform var(--duration-fast) var(--ease-out-quart);
|
||||
}
|
||||
|
||||
.wi-post__related-card:hover .wi-post__related-cover img {
|
||||
transform: scale(1.03);
|
||||
}
|
||||
|
||||
.wi-post__related-body {
|
||||
padding: var(--space-md);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.wi-post__related-name {
|
||||
font-family: var(--font-sans);
|
||||
font-size: var(--text-sm);
|
||||
font-weight: 600;
|
||||
color: var(--ink);
|
||||
line-height: var(--leading-snug);
|
||||
transition: color var(--duration-fast) var(--ease-out-quart);
|
||||
}
|
||||
|
||||
.wi-post__related-card:hover .wi-post__related-name {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.wi-post__related-date {
|
||||
font-size: var(--text-xs);
|
||||
color: var(--ink-3);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.wi-post__related-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.wi-post__cover-wrap {
|
||||
margin-inline: calc(-1 * var(--space-md));
|
||||
@@ -1049,6 +1341,11 @@ import LightGallery from "../components/LightGallery.astro";
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.wi-toc[data-expand="all"] .wi-toc__sub {
|
||||
max-height: 600px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.wi-toc__link {
|
||||
display: block;
|
||||
padding: 4px 0;
|
||||
|
||||
+15
-15
@@ -55,35 +55,35 @@ import Layout from "../layouts/Layout.astro";
|
||||
th:href="${profile.summary?.profileUrl}"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>Steam 主页 →</a>
|
||||
th:text="#{steam.homepage}">Steam Homepage →</a>
|
||||
</div>
|
||||
<div class="wi-steam__level" th:if="${profile.steamLevel != null}">
|
||||
<span class="wi-steam__level-num" th:text="${profile.steamLevel}"></span>
|
||||
<span class="wi-steam__level-label">等级</span>
|
||||
<span class="wi-steam__level-label" th:text="#{steam.level}">Level</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wi-steam__stats" th:if="${stats != null}">
|
||||
<div class="wi-steam__stat-card">
|
||||
<span class="wi-steam__stat-value" th:text="${stats.totalGames} ?: 0">0</span>
|
||||
<span class="wi-steam__stat-label">拥有游戏</span>
|
||||
<span class="wi-steam__stat-label" th:text="#{steam.ownedGames}">Owned Games</span>
|
||||
</div>
|
||||
<div class="wi-steam__stat-card">
|
||||
<span class="wi-steam__stat-value" th:text="${stats.totalPlaytimeFormatted} ?: '0 小时'">0 小时</span>
|
||||
<span class="wi-steam__stat-label">总游玩时长</span>
|
||||
<span class="wi-steam__stat-value" th:text="${stats.totalPlaytimeFormatted} ?: '0 hours'">0 hours</span>
|
||||
<span class="wi-steam__stat-label" th:text="#{steam.totalPlaytime}">Total Playtime</span>
|
||||
</div>
|
||||
<div class="wi-steam__stat-card">
|
||||
<span class="wi-steam__stat-value" th:text="${stats.recentPlaytimeFormatted} ?: '0 小时'">0 小时</span>
|
||||
<span class="wi-steam__stat-label">近两周</span>
|
||||
<span class="wi-steam__stat-value" th:text="${stats.recentPlaytimeFormatted} ?: '0 hours'">0 hours</span>
|
||||
<span class="wi-steam__stat-label" th:text="#{steam.recentPlaytime}">Recent 2 Weeks</span>
|
||||
</div>
|
||||
<div class="wi-steam__stat-card">
|
||||
<span class="wi-steam__stat-value" th:text="${badges != null and badges.totalBadges != null ? badges.totalBadges : 0}">0</span>
|
||||
<span class="wi-steam__stat-label">徽章</span>
|
||||
<span class="wi-steam__stat-label" th:text="#{steam.badges}">Badges</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wi-steam__section" th:if="${recentGames != null and !recentGames.isEmpty()}">
|
||||
<h3 class="wi-steam__section-title">最近游玩</h3>
|
||||
<h3 class="wi-steam__section-title" th:text="#{steam.recentlyPlayed}">Recently Played</h3>
|
||||
<div class="wi-steam__recent-scroll">
|
||||
<article class="wi-steam__recent-card" th:each="game : ${recentGames}">
|
||||
<a
|
||||
@@ -107,7 +107,7 @@ import Layout from "../layouts/Layout.astro";
|
||||
<div class="wi-steam__recent-body">
|
||||
<h4 class="wi-steam__recent-name" th:text="${game.name}"></h4>
|
||||
<div class="wi-steam__recent-meta">
|
||||
<span class="wi-steam__recent-time" th:text="${game.playtime2WeeksFormatted} ?: '0 小时'"></span>
|
||||
<span class="wi-steam__recent-time" th:text="${game.playtime2WeeksFormatted} ?: #{steam.hours}"></span>
|
||||
<span
|
||||
class="wi-steam__recent-achievements"
|
||||
th:if="${game.achievementProgressText != null}"
|
||||
@@ -122,7 +122,7 @@ import Layout from "../layouts/Layout.astro";
|
||||
</th:block>
|
||||
|
||||
<div class="wi-steam__section">
|
||||
<h3 class="wi-steam__section-title">游戏库</h3>
|
||||
<h3 class="wi-steam__section-title" th:text="#{steam.gameLibrary}">Game Library</h3>
|
||||
<div class="wi-steam__games-grid">
|
||||
<article class="wi-steam__game-card" th:each="game : ${games.items}">
|
||||
<a
|
||||
@@ -146,11 +146,11 @@ import Layout from "../layouts/Layout.astro";
|
||||
<div class="wi-steam__game-body">
|
||||
<h4 class="wi-steam__game-name" th:text="${game.name}"></h4>
|
||||
<div class="wi-steam__game-meta">
|
||||
<span class="wi-steam__game-time" th:text="${game.playtimeFormatted} ?: '0 小时'"></span>
|
||||
<span class="wi-steam__game-time" th:text="${game.playtimeFormatted} ?: #{steam.hours}"></span>
|
||||
<span
|
||||
class="wi-steam__game-last"
|
||||
th:if="${!#strings.isEmpty(game.lastPlayedFormatted)}"
|
||||
th:text="|最后游玩 ${game.lastPlayedFormatted}|"
|
||||
th:text="#{steam.lastPlayed(${game.lastPlayedFormatted})}"
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -166,13 +166,13 @@ import Layout from "../layouts/Layout.astro";
|
||||
class="wi-steam__page-btn"
|
||||
th:if="${games.hasPrevious()}"
|
||||
th:href="${games.prevUrl}"
|
||||
>上一页</a>
|
||||
th:text="#{common.newer}">Previous</a>
|
||||
<span class="wi-steam__page-spacer" th:if="${games.hasPrevious() and games.hasNext()}"></span>
|
||||
<a
|
||||
class="wi-steam__page-btn"
|
||||
th:if="${games.hasNext()}"
|
||||
th:href="${games.nextUrl}"
|
||||
>下一页</a>
|
||||
th:text="#{common.older}">Next</a>
|
||||
</nav>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
+7
-7
@@ -11,7 +11,7 @@ import Layout from "../layouts/Layout.astro";
|
||||
<header class="wi-tag__header">
|
||||
<h1 class="wi-tag__title" th:text="${tag.spec.displayName}"></h1>
|
||||
<span class="wi-page-accent"></span>
|
||||
<p class="wi-tag__subtitle" th:text="|共 ${posts.total} 篇文章|"></p>
|
||||
<p class="wi-tag__subtitle" th:text="#{common.postCount(${posts.total})}"></p>
|
||||
<p
|
||||
th:if="${not #strings.isEmpty(tag.spec.description)}"
|
||||
class="wi-tag__description"
|
||||
@@ -55,8 +55,8 @@ import Layout from "../layouts/Layout.astro";
|
||||
<div
|
||||
th:if="${posts.total == 0}"
|
||||
class="wi-tag__empty"
|
||||
th:text="${theme.config?.home?.home_label_no_posts ?: '暂无文章。'}"
|
||||
>暂无文章。</div>
|
||||
th:text="${theme.config?.home?.home_label_no_posts ?: #messages.msg('common.noPosts')}"
|
||||
>No posts yet.</div>
|
||||
|
||||
<nav
|
||||
th:if="${posts.totalPages gt 1}"
|
||||
@@ -67,8 +67,8 @@ import Layout from "../layouts/Layout.astro";
|
||||
th:if="${posts.hasPrevious()}"
|
||||
th:href="@{${posts.prevUrl}}"
|
||||
class="wi-tag__page-link wi-tag__page-link--prev"
|
||||
th:text="${theme.config?.home?.home_label_newer ?: '较新'}"
|
||||
>← 较新</a>
|
||||
th:text="${theme.config?.home?.home_label_newer ?: #messages.msg('common.newer')}"
|
||||
>← Newer</a>
|
||||
<span
|
||||
class="wi-tag__page-info"
|
||||
th:text="|${posts.page} / ${posts.totalPages}|"
|
||||
@@ -77,8 +77,8 @@ import Layout from "../layouts/Layout.astro";
|
||||
th:if="${posts.hasNext()}"
|
||||
th:href="@{${posts.nextUrl}}"
|
||||
class="wi-tag__page-link wi-tag__page-link--next"
|
||||
th:text="${theme.config?.home?.home_label_older ?: '较旧'}"
|
||||
>较旧 →</a>
|
||||
th:text="${theme.config?.home?.home_label_older ?: #messages.msg('common.older')}"
|
||||
>Older →</a>
|
||||
</nav>
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
@@ -4,14 +4,14 @@ import Layout from "../layouts/Layout.astro";
|
||||
|
||||
<Layout>
|
||||
<Fragment slot="head">
|
||||
<title th:text="|标签 - ${site.title}|"></title>
|
||||
<title th:text="|#{tags.title} - ${site.title}|"></title>
|
||||
</Fragment>
|
||||
|
||||
<div class="wi-tags">
|
||||
<header class="wi-tags__header">
|
||||
<h1 class="wi-tags__title">标签</h1>
|
||||
<h1 class="wi-tags__title" th:text="#{tags.title}">标签</h1>
|
||||
<span class="wi-page-accent"></span>
|
||||
<p class="wi-tags__subtitle" th:text="|共 ${tags.size} 个标签|"></p>
|
||||
<p class="wi-tags__subtitle" th:text="${#messages.msg('common.tagCount', ${tags.size})}"></p>
|
||||
</header>
|
||||
|
||||
<div class="wi-tags__cloud" role="list" aria-label="Tag list">
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ spec:
|
||||
author:
|
||||
name: 暖心向阳335
|
||||
website: https://nxxy335.top/
|
||||
description: 具有独特气质的生活博客主题
|
||||
description: 暖如灯火,静如留白。暖屿以柔和的色调和舒缓的节奏回归内容本身,为记录与阅读留出一方安静从容的角落。
|
||||
logo: /themes/warm-island/assets/logo.png
|
||||
homepage: https://nxxy335.top/WarmIsland/
|
||||
repo: https://github.com/sunny-335/halo-theme-WarmIsland
|
||||
|
||||
Reference in New Issue
Block a user