feat: 完善主题功能并适配插件 (v1.1.5)
功能新增 - 新增页面布局契约 templates/layout.html,插件前台页面可复用主题外观,避免回退到 Halo fallback 布局 - 新增微信读书页面模板 (weread.html),集成 halo-weread-plugin 书架 - 新增订阅页面模板 (page_subscriptions.html) - 新增欢迎弹窗组件(IP 地理定位,多 API 容错) - 新增点击特效组件(9 种效果) - 页脚新增全站统计,支持开关与统计项配置,默认开启 插件适配 - 适配 extra-api:文章字数改服务端统计、正文可选中英混排与服务端代码高亮 - 修正各页面插件应用市场链接与插件名 修复 - 修复文章正文图片/视频无法居中(正文样式移至全局,scoped 样式对 Thymeleaf 注入内容无效) - 修复正文 H1-H6 字号过大,重排层级与移动端断点 - 修复 th: 属性中文字符串缺少引号导致的 Thymeleaf 解析异常(/links、/moments 500) - 修复 JS 内联表达式与 Thymeleaf 内联语法冲突,全部内联脚本加 th:inline="none" - 修复移除 i18n 后 steam 页 Elvis 表达式回归问题 - 修正订阅页 th:attr 引号嵌套错误 优化 - Hero 移除灰色遮罩,下滑箭头改为可点击平滑滚动 - 优化目录样式:移除圆点与下拉箭头,支持两行显示,修复长目录截断 - 移除 i18n 多语言支持 清理 - 移除未使用的 Vue/图标依赖与废弃脚本、重复资源
This commit is contained in:
1 parent
9d0bfcfb4f
commit
430d107d44
78 files changed
+2959
-36075
No files matched your search
@@ -0,0 +1,331 @@
|
||||
@use 'variables' as *;
|
||||
|
||||
/* ==========================================================================
|
||||
正文排版(文章页 .wi-post__body / 单页 .wi-page__body 共用)
|
||||
--------------------------------------------------------------------------
|
||||
目标:
|
||||
1. 标题层级清晰、字号克制,移动端逐级收敛(而不是反向放大)
|
||||
2. 图片 / 视频 / 嵌入 iframe / figure 一律水平居中且不破坏响应式
|
||||
========================================================================== */
|
||||
|
||||
/* 正文容器:运行时由 Thymeleaf 注入内容,因此这里的规则必须是全局的,
|
||||
不能写进组件的 scoped <style>(那样不会命中注入的内容)。 */
|
||||
.wi-post__body,
|
||||
.wi-page__body,
|
||||
.wi-messageboard__body {
|
||||
/* ---------- 标题层级 ---------- */
|
||||
:is(h1, h2, h3, h4, h5, h6) {
|
||||
font-family: var(--font-sans);
|
||||
font-weight: 700;
|
||||
line-height: 1.35;
|
||||
letter-spacing: -0.01em;
|
||||
color: var(--ink);
|
||||
scroll-margin-top: 88px;
|
||||
text-wrap: balance;
|
||||
/* 覆盖全局标题装饰(左侧竖线 / 圆点),正文内保持干净 */
|
||||
padding-left: 0;
|
||||
border-left: 0;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: none;
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: clamp(1.45rem, 1.3rem + 0.7vw, 1.75rem);
|
||||
margin-top: 2em;
|
||||
margin-bottom: 0.7em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: clamp(1.3rem, 1.2rem + 0.5vw, 1.5rem);
|
||||
margin-top: 1.9em;
|
||||
margin-bottom: 0.65em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: clamp(1.15rem, 1.08rem + 0.35vw, 1.28rem);
|
||||
margin-top: 1.7em;
|
||||
margin-bottom: 0.6em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: clamp(1.05rem, 1rem + 0.25vw, 1.13rem);
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1rem;
|
||||
margin-top: 1.4em;
|
||||
margin-bottom: 0.45em;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
color: var(--ink-3);
|
||||
margin-top: 1.4em;
|
||||
margin-bottom: 0.45em;
|
||||
}
|
||||
|
||||
/* 标题紧跟在另一个标题后时去掉多余上间距 */
|
||||
:is(h1, h2, h3, h4, h5, h6) + :is(h1, h2, h3, h4, h5, h6) {
|
||||
margin-top: 0.6em;
|
||||
}
|
||||
|
||||
/* 段落内首个元素不需要上间距 */
|
||||
> :is(h1, h2, h3, h4, h5, h6):first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-block-end: 1.2em;
|
||||
}
|
||||
|
||||
/* ---------- 代码块 / 引用 / 列表 ---------- */
|
||||
|
||||
* {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
:is(pre, code, table) {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin-block: 1.5em;
|
||||
padding: 1.25em;
|
||||
border-radius: $border-radius-md;
|
||||
border: 1px solid var(--rule);
|
||||
background: var(--bg-raised);
|
||||
font-size: 0.875em;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
pre code {
|
||||
background: none;
|
||||
padding: 0;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
code {
|
||||
background: var(--bg-raised);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: $border-radius-sm;
|
||||
font-size: 0.875em;
|
||||
border: 1px solid var(--rule);
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin-block: 2em;
|
||||
}
|
||||
|
||||
:is(ul, ol) {
|
||||
padding-inline-start: 1.5em;
|
||||
margin-block-end: 1.2em;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-block-end: 0.6em;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: underline;
|
||||
text-decoration-thickness: 1px;
|
||||
text-underline-offset: 0.2em;
|
||||
}
|
||||
|
||||
/* 第三方摘要插件容器 */
|
||||
:is(.ai-summary, .abstract),
|
||||
[class*='ai-summary'],
|
||||
[class*='ai-abstract'],
|
||||
[class*='likcc-article-summary'] {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
/* ---------- 媒体居中 ---------- */
|
||||
|
||||
/* 图片 / 视频:块级 + 自动外边距实现居中,max-width 保证不溢出容器 */
|
||||
img,
|
||||
video {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
img,
|
||||
video {
|
||||
border-radius: $border-radius-md;
|
||||
margin-block: 1.5em;
|
||||
}
|
||||
|
||||
/* 行内小图标 / 表情不受居中规则影响 */
|
||||
img[role='presentation'],
|
||||
img[aria-hidden='true'],
|
||||
:is(.emoji, .icon, .avatar, .badge) {
|
||||
display: inline;
|
||||
margin-inline: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
/* 编辑器可能输出 align="center|left|right" 或 text-align 样式,保持一致居中 */
|
||||
[align='center'],
|
||||
[style*='text-align:center'],
|
||||
[style*='text-align: center'] {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
iframe {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
margin-inline: auto;
|
||||
border: none;
|
||||
}
|
||||
|
||||
figure {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
margin-inline: auto;
|
||||
margin-block: 1.5em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
figure :is(img, video) {
|
||||
margin-block: 0;
|
||||
}
|
||||
|
||||
figcaption {
|
||||
color: var(--ink-3);
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.6;
|
||||
text-align: center;
|
||||
margin-top: 0.6em;
|
||||
}
|
||||
|
||||
/* lightgallery 注入的 <a> 包裹层:收缩到图片宽度并居中 */
|
||||
.wi-lightgallery-item {
|
||||
display: block;
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
margin-inline: auto;
|
||||
border-radius: $border-radius-md;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
.wi-lightgallery-item > img {
|
||||
margin-block: 0;
|
||||
}
|
||||
|
||||
/* 响应式嵌入容器(由脚本按 width/height 生成 aspect-ratio) */
|
||||
.wi-embed {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
margin-inline: auto;
|
||||
margin-block: 1.5em;
|
||||
overflow: hidden;
|
||||
border-radius: $border-radius-md;
|
||||
background: var(--bg-raised);
|
||||
}
|
||||
|
||||
.wi-embed > :is(iframe, video, embed, object) {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* 图片懒加载占位模糊 */
|
||||
.wi-media-loading {
|
||||
filter: blur(20px);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.wi-media-loaded {
|
||||
filter: blur(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 移动端:标题逐级收敛,正文行高放宽 */
|
||||
@media (max-width: 768px) {
|
||||
.wi-post__body,
|
||||
.wi-page__body,
|
||||
.wi-messageboard__body {
|
||||
h1 {
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.28rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.16rem;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-block-end: 1.35em;
|
||||
}
|
||||
|
||||
pre {
|
||||
font-size: 0.9em;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
img,
|
||||
video {
|
||||
margin-block: 1.2em;
|
||||
}
|
||||
|
||||
/* 窄屏图片允许撑满内容宽度,避免留白过大 */
|
||||
img,
|
||||
video,
|
||||
.wi-lightgallery-item,
|
||||
figure {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.wi-post__body,
|
||||
.wi-page__body,
|
||||
.wi-messageboard__body {
|
||||
h1 {
|
||||
font-size: 1.32rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.22rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.12rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user