fix(opensource): 修视觉终审的四个 P1 与灰阶/对齐细节
视觉终审对开源页改版判「需修」,逐条修完并量化复验。
P1-1 数据板空档与三段右缘不齐:streak 只占半栏、snake 通栏 → 右侧空 306px。
- 网格改 `repeat(auto-fit, minmax(320px, 1fr))`,仅一张非通栏卡时加 `.pf-card-solo`
(`grid-column: 1/-1`),语言条去掉 max-width
- 实测:统计行/语言条/数据板右缘统一 959px,streak 卡宽 298→638
P1-2 卡内 SVG 文字不可读:streak 固有 495px 被压到 298px(0.6×),14px 标签变 8.4px。
- 卡改全宽后 1:1 渲染(实测 rendered=495=natural);抓取参数把次级灰换成站点 ink:
亮色 #3f424a(10.05:1)、暗色 #b9bec8(9.07:1),旧值 #9aa0aa 仅 2.63:1
P1-3 移动端打字机折行推挤:390 下第 4 句 260px > 可用 230px 必折两行,
min-height:1.6em 挡不住 → 每轮下推 21px 再弹回。
- `@media(max-width:560px){.typing{min-height:calc(1.6em*2)}}`(实测 42px 恒定零推挤)
- 光标收成 2px 竖条 + baseline 对齐(原来是 0.5em 实心块,两行时被拉到行间)
- typing 第 4 句裁短(中文 ≤16 字、英文 ≤36 字符)
P1-4 streak 卡入场动画空壳帧:SVG 内 fadein 序列(环 0.4s/数字 0.6s/…/1.2s)+ lazy
加载 → 用户先看到 0.5–1.5s 半成品,截图也会随机拍到空卡。
- 抓取脚本新增 freezeAnimations():剥掉全部 animation 声明、opacity:0 改 1、
删除 @keyframes;重抓后 grep animation:/opacity: 0 均为 0(streak 各 6KB、
snake 35KB→20KB)
P2 一并:
- streak 亮色容器 grayscale(1) 回到灰阶基调;暗色蛇卡改 grayscale+invert+contrast+
brightness 组合,空网格不再与底色同色
- 项目墙描述 text-wrap: pretty(长描述末行孤词)
- 统计口径注释改为「三格」,不硬塞第 4 格(贡献数已由热力图承载)
- 社交图标行负 margin 做光学对齐
附:content-lint 增加 SKIP_ALL 白名单(一次性预览路由 /books-preview/ 无 en 对应页,
语言切换链接会误报断链+配对缺)
验证: 构建 51 页 exit 0;content-lint 54 页 0/0/0;E2E 46/46;
Playwright 实测三段右缘 959 一致、streak 1:1、1280/390 零横向溢出、
移动打字机高度 42px 恒定、光标 2px、项目墙 text-wrap=pretty
Spec: 2026-11-02_blog-5i-fonts-polish (T8 修复)
Co-authored-by: GLM-5.3
This commit is contained in:
1 parent
907f64472a
commit
cfe508ff14
10 files changed
+96
-62
No files matched your search
@@ -6,8 +6,8 @@ typing:
|
|||||||
en: Self-hosting whatever can be self-hosted
|
en: Self-hosting whatever can be self-hosted
|
||||||
- zh: 拥抱开源,热爱开源
|
- zh: 拥抱开源,热爱开源
|
||||||
en: Embrace open source, love open source
|
en: Embrace open source, love open source
|
||||||
- zh: 把读过的书、按下的快门都放进同一个工作台
|
- zh: 书与快门都在一个工作台
|
||||||
en: Books read and shutters pressed, gathered in one workbench
|
en: Books and shutters, one workbench
|
||||||
|
|
||||||
blurb:
|
blurb:
|
||||||
zh: 本站本身即开源:
|
zh: 本站本身即开源:
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
{
|
{
|
||||||
"assets": {
|
"assets": {
|
||||||
"streak-light.svg": {
|
"streak-light.svg": {
|
||||||
"source": "https://streak-stats.demolab.com/?user=wait4xx&hide_border=true&background=00000000&ring=3454d1&fire=3454d1&currStreakLabel=3454d1&currStreakNum=33343a&sideNums=33343a&sideLabels=8b8f98&dates=8b8f98",
|
"source": "https://streak-stats.demolab.com/?user=wait4xx&hide_border=true&background=00000000&ring=3454d1&fire=3454d1&currStreakLabel=3454d1&currStreakNum=33343a&sideNums=33343a&sideLabels=3f424a&dates=3f424a",
|
||||||
"fetchedAt": "2026-11-03T03:07:28.521Z",
|
"fetchedAt": "2026-11-03T03:39:51.755Z",
|
||||||
"label": "连续贡献",
|
"label": "连续贡献",
|
||||||
"theme": "light"
|
"theme": "light"
|
||||||
},
|
},
|
||||||
"streak-dark.svg": {
|
"streak-dark.svg": {
|
||||||
"source": "https://streak-stats.demolab.com/?user=wait4xx&hide_border=true&background=00000000&ring=3454d1&fire=3454d1&currStreakLabel=3454d1&currStreakNum=c9ccd4&sideNums=c9ccd4&sideLabels=9aa0aa&dates=9aa0aa",
|
"source": "https://streak-stats.demolab.com/?user=wait4xx&hide_border=true&background=00000000&ring=3454d1&fire=3454d1&currStreakLabel=3454d1&currStreakNum=c9ccd4&sideNums=c9ccd4&sideLabels=b9bec8&dates=b9bec8",
|
||||||
"fetchedAt": "2026-11-03T03:07:28.521Z",
|
"fetchedAt": "2026-11-03T03:39:51.755Z",
|
||||||
"label": "连续贡献",
|
"label": "连续贡献",
|
||||||
"theme": "dark"
|
"theme": "dark"
|
||||||
},
|
},
|
||||||
"snake.svg": {
|
"snake.svg": {
|
||||||
"source": "https://raw.githubusercontent.com/wait4xx/wait4xx/output/github-contribution-grid-snake.svg",
|
"source": "https://raw.githubusercontent.com/wait4xx/wait4xx/output/github-contribution-grid-snake.svg",
|
||||||
"fetchedAt": "2026-11-03T03:07:28.521Z",
|
"fetchedAt": "2026-11-03T03:39:51.755Z",
|
||||||
"label": "贡献蛇",
|
"label": "贡献蛇",
|
||||||
"theme": "any"
|
"theme": "any"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<svg viewBox="-16 -32 880 192" width="880" height="192" xmlns="http://www.w3.org/2000/svg"><desc>Generated with https://github.com/Platane/snk</desc><style>:root{--cb:#1b1f230a;--cs:purple;--ce:#ebedf0;--c0:#ebedf0;--c1:#9be9a8;--c2:#40c463;--c3:#30a14e;--c4:#216e39}.c{shape-rendering:geometricPrecision;fill:var(--ce);stroke-width:1px;stroke:var(--cb);animation:none 35300ms linear infinite;width:12px;height:12px}@keyframes c0{4.52%{fill:var(--c1)}4.54%,100%{fill:var(--ce)}}.c.c0{fill:var(--c1);animation-name:c0}@keyframes c1{66.85%{fill:var(--c2)}66.87%,100%{fill:var(--ce)}}.c.c1{fill:var(--c2);animation-name:c1}@keyframes c2{3.67%{fill:var(--c1)}3.69%,100%{fill:var(--ce)}}.c.c2{fill:var(--c1);animation-name:c2}@keyframes c3{1.97%{fill:var(--c1)}1.99%,100%{fill:var(--ce)}}.c.c3{fill:var(--c1);animation-name:c3}@keyframes c4{2.82%{fill:var(--c1)}2.84%,100%{fill:var(--ce)}}.c.c4{fill:var(--c1);animation-name:c4}@keyframes c5{3.39%{fill:var(--c1)}3.41%,100%{fill:var(--ce)}}.c.c5{fill:var(--c1);animation-name:c5}@keyframes c6{2.26%{fill:var(--c1)}2.28%,100%{fill:var(--ce)}}.c.c6{fill:var(--c1);animation-name:c6}@keyframes c7{10.19%{fill:var(--c1)}10.21%,100%{fill:var(--ce)}}.c.c7{fill:var(--c1);animation-name:c7}@keyframes c8{9.06%{fill:var(--c1)}9.08%,100%{fill:var(--ce)}}.c.c8{fill:var(--c1);animation-name:c8}@keyframes c9{41.63%{fill:var(--c1)}41.65%,100%{fill:var(--ce)}}.c.c9{fill:var(--c1);animation-name:c9}@keyframes ca{12.74%{fill:var(--c1)}12.76%,100%{fill:var(--ce)}}.c.ca{fill:var(--c1);animation-name:ca}@keyframes cb{13.59%{fill:var(--c1)}13.61%,100%{fill:var(--ce)}}.c.cb{fill:var(--c1);animation-name:cb}@keyframes cc{14.15%{fill:var(--c1)}14.17%,100%{fill:var(--ce)}}.c.cc{fill:var(--c1);animation-name:cc}@keyframes cd{14.44%{fill:var(--c1)}14.46%,100%{fill:var(--ce)}}.c.cd{fill:var(--c1);animation-name:cd}@keyframes ce{21.8%{fill:var(--c1)}21.82%,100%{fill:var(--ce)}}.c.ce{fill:var(--c1);animation-name:ce}@keyframes cf{19.82%{fill:var(--c1)}19.84%,100%{fill:var(--ce)}}.c.cf{fill:var(--c1);animation-name:cf}@keyframes cg{20.67%{fill:var(--c1)}20.69%,100%{fill:var(--ce)}}.c.cg{fill:var(--c1);animation-name:cg}@keyframes ch{14.72%{fill:var(--c1)}14.74%,100%{fill:var(--ce)}}.c.ch{fill:var(--c1);animation-name:ch}@keyframes ci{21.52%{fill:var(--c1)}21.54%,100%{fill:var(--ce)}}.c.ci{fill:var(--c1);animation-name:ci}@keyframes cj{19.25%{fill:var(--c1)}19.27%,100%{fill:var(--ce)}}.c.cj{fill:var(--c1);animation-name:cj}@keyframes ck{15%{fill:var(--c1)}15.02%,100%{fill:var(--ce)}}.c.ck{fill:var(--c1);animation-name:ck}@keyframes cl{15.29%{fill:var(--c1)}15.31%,100%{fill:var(--ce)}}.c.cl{fill:var(--c1);animation-name:cl}@keyframes cm{44.18%{fill:var(--c2)}44.2%,100%{fill:var(--ce)}}.c.cm{fill:var(--c2);animation-name:cm}@keyframes cn{18.4%{fill:var(--c1)}18.42%,100%{fill:var(--ce)}}.c.cn{fill:var(--c1);animation-name:cn}@keyframes co{18.69%{fill:var(--c1)}18.71%,100%{fill:var(--ce)}}.c.co{fill:var(--c1);animation-name:co}@keyframes cp{16.14%{fill:var(--c1)}16.16%,100%{fill:var(--ce)}}.c.cp{fill:var(--c1);animation-name:cp}@keyframes cq{15.85%{fill:var(--c1)}15.87%,100%{fill:var(--ce)}}.c.cq{fill:var(--c1);animation-name:cq}@keyframes cr{23.5%{fill:var(--c1)}23.52%,100%{fill:var(--ce)}}.c.cr{fill:var(--c1);animation-name:cr}@keyframes cs{18.12%{fill:var(--c1)}18.14%,100%{fill:var(--ce)}}.c.cs{fill:var(--c1);animation-name:cs}@keyframes ct{89.79%{fill:var(--c4)}89.81%,100%{fill:var(--ce)}}.c.ct{fill:var(--c4);animation-name:ct}@keyframes cu{16.99%{fill:var(--c1)}17.01%,100%{fill:var(--ce)}}.c.cu{fill:var(--c1);animation-name:cu}@keyframes cv{76.19%{fill:var(--c4)}76.21%,100%{fill:var(--ce)}}.c.cv{fill:var(--c4);animation-name:cv}@keyframes cw{47.02%{fill:var(--c2)}47.04%,100%{fill:var(--ce)}}.c.cw{fill:var(--c2);animation-name:cw}@keyframes cx{35.4%{fill:var(--c1)}35.42%,100%{fill:var(--ce)}}.c.cx{fill:var(--c1);animation-name:cx}@keyframes cy{35.12%{fill:var(--c1)}35.14%,100%{fill:var(--ce)}}.c.cy{fill:var(--c1);animation-name:cy}@keyframes cz{26.34%{fill:var(--c1)}26.36%,100%{fill:var(--ce)}}.c.cz{fill:var(--c1);animation-name:cz}@keyframes c10{33.7%{fill:var(--c1)}33.72%,100%{fill:var(--ce)}}.c.c10{fill:var(--c1);animation-name:c10}@keyframes c11{33.98%{fill:var(--c1)}34%,100%{fill:var(--ce)}}.c.c11{fill:var(--c1);animation-name:c11}@keyframes c12{50.41%{fill:var(--c2)}50.43%,100%{fill:var(--ce)}}.c.c12{fill:var(--c2);animation-name:c12}@keyframes c13{78.46%{fill:var(--c4)}78.48%,100%{fill:var(--ce)}}.c.c13{fill:var(--c4);animation-name:c13}@keyframes c14{49.28%{fill:var(--c2)}49.3%,100%{fill:var(--ce)}}.c.c14{fill:var(--c2);animation-name:c14}@keyframes c15{27.47%{fill:var(--c1)}27.49%,100%{fill:var(--ce)}}.c.c15{fill:var(--c1);animation-name:c15}@keyframes c16{80.44%{fill:var(--c4)}80.46%,100%{fill:var(--ce)}}.c.c16{fill:var(--c4);animation-name:c16}@keyframes c17{27.75%{fill:var(--c1)}27.77%,100%{fill:var(--ce)}}.c.c17{fill:var(--c1);animation-name:c17}@keyframes c18{32.28%{fill:var(--c1)}32.3%,100%{fill:vLine truncated
|
<svg viewBox="-16 -32 880 192" width="880" height="192" xmlns="http://www.w3.org/2000/svg"><desc>Generated with https://github.com/Platane/snk</desc><style>:root{--cb:#1b1f230a;--cs:purple;--ce:#ebedf0;--c0:#ebedf0;--c1:#9be9a8;--c2:#40c463;--c3:#30a14e;--c4:#216e39}.c{shape-rendering:geometricPrecision;fill:var(--ce);stroke-width:1px;stroke:var(--cb);width:12px;height:12px}.c.c0{fill:var(--c1);animation-name:c0}.c.c1{fill:var(--c2);animation-name:c1}.c.c2{fill:var(--c1);animation-name:c2}.c.c3{fill:var(--c1);animation-name:c3}.c.c4{fill:var(--c1);animation-name:c4}.c.c5{fill:var(--c1);animation-name:c5}.c.c6{fill:var(--c1);animation-name:c6}.c.c7{fill:var(--c1);animation-name:c7}.c.c8{fill:var(--c1);animation-name:c8}.c.c9{fill:var(--c1);animation-name:c9}.c.ca{fill:var(--c1);animation-name:ca}.c.cb{fill:var(--c1);animation-name:cb}.c.cc{fill:var(--c1);animation-name:cc}.c.cd{fill:var(--c1);animation-name:cd}.c.ce{fill:var(--c1);animation-name:ce}.c.cf{fill:var(--c1);animation-name:cf}.c.cg{fill:var(--c1);animation-name:cg}.c.ch{fill:var(--c1);animation-name:ch}.c.ci{fill:var(--c1);animation-name:ci}.c.cj{fill:var(--c1);animation-name:cj}.c.ck{fill:var(--c1);animation-name:ck}.c.cl{fill:var(--c1);animation-name:cl}.c.cm{fill:var(--c2);animation-name:cm}.c.cn{fill:var(--c1);animation-name:cn}.c.co{fill:var(--c1);animation-name:co}.c.cp{fill:var(--c1);animation-name:cp}.c.cq{fill:var(--c1);animation-name:cq}.c.cr{fill:var(--c1);animation-name:cr}.c.cs{fill:var(--c1);animation-name:cs}.c.ct{fill:var(--c4);animation-name:ct}.c.cu{fill:var(--c1);animation-name:cu}.c.cv{fill:var(--c4);animation-name:cv}.c.cw{fill:var(--c2);animation-name:cw}.c.cx{fill:var(--c1);animation-name:cx}.c.cy{fill:var(--c1);animation-name:cy}.c.cz{fill:var(--c1);animation-name:cz}.c.c10{fill:var(--c1);animation-name:c10}.c.c11{fill:var(--c1);animation-name:c11}.c.c12{fill:var(--c2);animation-name:c12}.c.c13{fill:var(--c4);animation-name:c13}.c.c14{fill:var(--c2);animation-name:c14}.c.c15{fill:var(--c1);animation-name:c15}.c.c16{fill:var(--c4);animation-name:c16}.c.c17{fill:var(--c1);animation-name:c17}.c.c18{fill:var(--c1);animation-name:c18}.c.c19{fill:var(--c1);animation-name:c19}.c.c1a{fill:var(--c2);animation-name:c1a}.c.c1b{fill:var(--c1);animation-name:c1b}.c.c1c{fill:var(--c1);animation-name:c1c}.c.c1d{fill:var(--c4);animation-name:c1d}.c.c1e{fill:var(--c4);animation-name:c1e}.u{transform-origin:0 0;transform:scale(0,1);animation-name:u0;transform-origin:0.0px 0}.u.u1{fill:var(--c2);animation-name:u1;transform-origin:648.5px 0}.u.u2{fill:var(--c4);animation-name:u2;transform-origin:748.2px 0}.s{shape-rendering:geometricPrecision;fill:var(--cs);animation-name:s0}.s.s1{transform:translate(16px,-16px);animation-name:s1}.s.s2{transform:translate(32px,-16px);animation-name:s2}.s.s3{transform:translate(48px,-16px);animation-name:s3}</style><rect class="c" x="2" y="2" rx="2" ry="2"/><rect class="c" x="2" y="18" rx="2" ry="2"/><rect class="c" x="2" y="34" rx="2" ry="2"/><rect class="c" x="2" y="50" rx="2" ry="2"/><rect class="c" x="2" y="66" rx="2" ry="2"/><rect class="c" x="2" y="82" rx="2" ry="2"/><rect class="c" x="2" y="98" rx="2" ry="2"/><rect class="c" x="18" y="2" rx="2" ry="2"/><rect class="c" x="18" y="18" rx="2" ry="2"/><rect class="c" x="18" y="34" rx="2" ry="2"/><rect class="c" x="18" y="50" rx="2" ry="2"/><rect class="c" x="18" y="66" rx="2" ry="2"/><rect class="c" x="18" y="82" rx="2" ry="2"/><rect class="c c0" x="18" y="98" rx="2" ry="2"/><rect class="c" x="34" y="2" rx="2" ry="2"/><rect class="c" x="34" y="18" rx="2" ry="2"/><rect class="c" x="34" y="34" rx="2" ry="2"/><rect class="c" x="34" y="50" rx="2" ry="2"/><rect class="c" x="34" y="66" rx="2" ry="2"/><rect class="c" x="34" y="82" rx="2" ry="2"/><rect class="c" x="34" y="98" rx="2" ry="2"/><rect class="c" x="50" y="2" rx="2" ry="2"/><rect class="c" x="50" y="18" rx="2" ry="2"/><rect class="c" x="50" y="34" rx="2" ry="2"/><rect class="c" x="50" y="50" rx="2" ry="2"/><rect class="c c1" x="50" y="66" rx="2" ry="2"/><rect class="c c2" x="50" y="82" rx="2" ry="2"/><rect class="c" x="50" y="98" rx="2" ry="2"/><rect class="c" x="66" y="2" rx="2" ry="2"/><rect class="c" x="66" y="18" rx="2" ry="2"/><rect class="c c3" x="66" y="34" rx="2" ry="2"/><rect class="c c4" x="66" y="50" rx="2" ry="2"/><rect class="c" x="66" y="66" rx="2" ry="2"/><rect class="c c5" x="66" y="82" rx="2" ry="2"/><rect class="c" x="66" y="98" rx="2" ry="2"/><rect class="c" x="82" y="2" rx="2" ry="2"/><rect class="c" x="82" y="18" rx="2" ry="2"/><rect class="c c6" x="82" y="34" rx="2" ry="2"/><rect class="c" x="82" y="50" rx="2" ry="2"/><rect class="c" x="82" y="66" rx="2" ry="2"/><rect class="c" x="82" y="82" rx="2" ry="2"/><rect class="c" x="82" y="98" rx="2" ry="2"/><rect class="c" x="98" y="2" rx="2" ry="2"/><rect class="c" x="98" y="18" rx="2" ry="2"/><rect class="c" x="98" y="34" rx="2" ry="2"/><rect class="c" x="98" y="50" rx="2" ry="2"/><rect class="c" x="98" y="66" rx="2" ry="2"/><rect class="cLine truncated
|
||||||
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 20 KiB |
@@ -1,15 +1,8 @@
|
|||||||
<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'
|
<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'
|
||||||
style='isolation: isolate' viewBox='0 0 495 195' width='495px' height='195px' direction='ltr'>
|
style='isolation: isolate' viewBox='0 0 495 195' width='495px' height='195px' direction='ltr'>
|
||||||
<style>
|
<style>
|
||||||
@keyframes currstreak {
|
|
||||||
0% { font-size: 3px; opacity: 0.2; }
|
|
||||||
80% { font-size: 34px; opacity: 1; }
|
|
||||||
100% { font-size: 28px; opacity: 1; }
|
|
||||||
}
|
|
||||||
@keyframes fadein {
|
|
||||||
0% { opacity: 0; }
|
|
||||||
100% { opacity: 1; }
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
<defs>
|
<defs>
|
||||||
<clipPath id='outer_rectangle'>
|
<clipPath id='outer_rectangle'>
|
||||||
@@ -32,21 +25,21 @@
|
|||||||
<g style='isolation: isolate'>
|
<g style='isolation: isolate'>
|
||||||
<!-- Total Contributions big number -->
|
<!-- Total Contributions big number -->
|
||||||
<g transform='translate(82.5, 48)'>
|
<g transform='translate(82.5, 48)'>
|
||||||
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#c9ccd4' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='700' font-size='28px' font-style='normal' style='opacity: 0; animation: fadein 0.5s linear forwards 0.6s'>
|
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#c9ccd4' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='700' font-size='28px' font-style='normal' style='opacity: 1'>
|
||||||
344
|
344
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<!-- Total Contributions label -->
|
<!-- Total Contributions label -->
|
||||||
<g transform='translate(82.5, 84)'>
|
<g transform='translate(82.5, 84)'>
|
||||||
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#9aa0aa' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='400' font-size='14px' font-style='normal' style='opacity: 0; animation: fadein 0.5s linear forwards 0.7s'>
|
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#b9bec8' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='400' font-size='14px' font-style='normal' style='opacity: 1'>
|
||||||
Total Contributions
|
Total Contributions
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<!-- Total Contributions range -->
|
<!-- Total Contributions range -->
|
||||||
<g transform='translate(82.5, 114)'>
|
<g transform='translate(82.5, 114)'>
|
||||||
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#9aa0aa' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='400' font-size='12px' font-style='normal' style='opacity: 0; animation: fadein 0.5s linear forwards 0.8s'>
|
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#b9bec8' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='400' font-size='12px' font-style='normal' style='opacity: 1'>
|
||||||
May 24, 2019 - Present
|
May 24, 2019 - Present
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
@@ -54,31 +47,31 @@
|
|||||||
<g style='isolation: isolate'>
|
<g style='isolation: isolate'>
|
||||||
<!-- Current Streak label -->
|
<!-- Current Streak label -->
|
||||||
<g transform='translate(247.5, 108)'>
|
<g transform='translate(247.5, 108)'>
|
||||||
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#3454d1' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='700' font-size='14px' font-style='normal' style='opacity: 0; animation: fadein 0.5s linear forwards 0.9s'>
|
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#3454d1' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='700' font-size='14px' font-style='normal' style='opacity: 1'>
|
||||||
Current Streak
|
Current Streak
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<!-- Current Streak range -->
|
<!-- Current Streak range -->
|
||||||
<g transform='translate(247.5, 145)'>
|
<g transform='translate(247.5, 145)'>
|
||||||
<text x='0' y='21' stroke-width='0' text-anchor='middle' fill='#9aa0aa' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='400' font-size='12px' font-style='normal' style='opacity: 0; animation: fadein 0.5s linear forwards 0.9s'>
|
<text x='0' y='21' stroke-width='0' text-anchor='middle' fill='#b9bec8' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='400' font-size='12px' font-style='normal' style='opacity: 1'>
|
||||||
Nov 3
|
Nov 3
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<!-- Ring around number -->
|
<!-- Ring around number -->
|
||||||
<g mask='url(#mask_out_ring_behind_fire)'>
|
<g mask='url(#mask_out_ring_behind_fire)'>
|
||||||
<circle cx='247.5' cy='71' r='40' fill='none' stroke='#3454d1' stroke-width='5' style='opacity: 0; animation: fadein 0.5s linear forwards 0.4s'></circle>
|
<circle cx='247.5' cy='71' r='40' fill='none' stroke='#3454d1' stroke-width='5' style='opacity: 1'></circle>
|
||||||
</g>
|
</g>
|
||||||
<!-- Fire icon -->
|
<!-- Fire icon -->
|
||||||
<g transform='translate(247.5, 19.5)' stroke-opacity='0' style='opacity: 0; animation: fadein 0.5s linear forwards 0.6s'>
|
<g transform='translate(247.5, 19.5)' stroke-opacity='0' style='opacity: 1'>
|
||||||
<path d='M -12 -0.5 L 15 -0.5 L 15 23.5 L -12 23.5 L -12 -0.5 Z' fill='none'/>
|
<path d='M -12 -0.5 L 15 -0.5 L 15 23.5 L -12 23.5 L -12 -0.5 Z' fill='none'/>
|
||||||
<path d='M 1.5 0.67 C 1.5 0.67 2.24 3.32 2.24 5.47 C 2.24 7.53 0.89 9.2 -1.17 9.2 C -3.23 9.2 -4.79 7.53 -4.79 5.47 L -4.76 5.11 C -6.78 7.51 -8 10.62 -8 13.99 C -8 18.41 -4.42 22 0 22 C 4.42 22 8 18.41 8 13.99 C 8 8.6 5.41 3.79 1.5 0.67 Z M -0.29 19 C -2.07 19 -3.51 17.6 -3.51 15.86 C -3.51 14.24 -2.46 13.1 -0.7 12.74 C 1.07 12.38 2.9 11.53 3.92 10.16 C 4.31 11.45 4.51 12.81 4.51 14.2 C 4.51 16.85 2.36 19 -0.29 19 Z' fill='#3454d1' stroke-opacity='0'/>
|
<path d='M 1.5 0.67 C 1.5 0.67 2.24 3.32 2.24 5.47 C 2.24 7.53 0.89 9.2 -1.17 9.2 C -3.23 9.2 -4.79 7.53 -4.79 5.47 L -4.76 5.11 C -6.78 7.51 -8 10.62 -8 13.99 C -8 18.41 -4.42 22 0 22 C 4.42 22 8 18.41 8 13.99 C 8 8.6 5.41 3.79 1.5 0.67 Z M -0.29 19 C -2.07 19 -3.51 17.6 -3.51 15.86 C -3.51 14.24 -2.46 13.1 -0.7 12.74 C 1.07 12.38 2.9 11.53 3.92 10.16 C 4.31 11.45 4.51 12.81 4.51 14.2 C 4.51 16.85 2.36 19 -0.29 19 Z' fill='#3454d1' stroke-opacity='0'/>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<!-- Current Streak big number -->
|
<!-- Current Streak big number -->
|
||||||
<g transform='translate(247.5, 48)'>
|
<g transform='translate(247.5, 48)'>
|
||||||
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#c9ccd4' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='700' font-size='28px' font-style='normal' style='animation: currstreak 0.6s linear forwards'>
|
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#c9ccd4' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='700' font-size='28px' font-style='normal' >
|
||||||
0
|
0
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
@@ -87,21 +80,21 @@
|
|||||||
<g style='isolation: isolate'>
|
<g style='isolation: isolate'>
|
||||||
<!-- Longest Streak big number -->
|
<!-- Longest Streak big number -->
|
||||||
<g transform='translate(412.5, 48)'>
|
<g transform='translate(412.5, 48)'>
|
||||||
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#c9ccd4' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='700' font-size='28px' font-style='normal' style='opacity: 0; animation: fadein 0.5s linear forwards 1.2s'>
|
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#c9ccd4' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='700' font-size='28px' font-style='normal' style='opacity: 1'>
|
||||||
6
|
6
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<!-- Longest Streak label -->
|
<!-- Longest Streak label -->
|
||||||
<g transform='translate(412.5, 84)'>
|
<g transform='translate(412.5, 84)'>
|
||||||
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#9aa0aa' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='400' font-size='14px' font-style='normal' style='opacity: 0; animation: fadein 0.5s linear forwards 1.3s'>
|
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#b9bec8' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='400' font-size='14px' font-style='normal' style='opacity: 1'>
|
||||||
Longest Streak
|
Longest Streak
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<!-- Longest Streak range -->
|
<!-- Longest Streak range -->
|
||||||
<g transform='translate(412.5, 114)'>
|
<g transform='translate(412.5, 114)'>
|
||||||
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#9aa0aa' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='400' font-size='12px' font-style='normal' style='opacity: 0; animation: fadein 0.5s linear forwards 1.4s'>
|
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#b9bec8' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='400' font-size='12px' font-style='normal' style='opacity: 1'>
|
||||||
Oct 19 - Oct 24
|
Oct 19 - Oct 24
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.1 KiB |
@@ -1,15 +1,8 @@
|
|||||||
<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'
|
<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'
|
||||||
style='isolation: isolate' viewBox='0 0 495 195' width='495px' height='195px' direction='ltr'>
|
style='isolation: isolate' viewBox='0 0 495 195' width='495px' height='195px' direction='ltr'>
|
||||||
<style>
|
<style>
|
||||||
@keyframes currstreak {
|
|
||||||
0% { font-size: 3px; opacity: 0.2; }
|
|
||||||
80% { font-size: 34px; opacity: 1; }
|
|
||||||
100% { font-size: 28px; opacity: 1; }
|
|
||||||
}
|
|
||||||
@keyframes fadein {
|
|
||||||
0% { opacity: 0; }
|
|
||||||
100% { opacity: 1; }
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
<defs>
|
<defs>
|
||||||
<clipPath id='outer_rectangle'>
|
<clipPath id='outer_rectangle'>
|
||||||
@@ -32,21 +25,21 @@
|
|||||||
<g style='isolation: isolate'>
|
<g style='isolation: isolate'>
|
||||||
<!-- Total Contributions big number -->
|
<!-- Total Contributions big number -->
|
||||||
<g transform='translate(82.5, 48)'>
|
<g transform='translate(82.5, 48)'>
|
||||||
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#33343a' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='700' font-size='28px' font-style='normal' style='opacity: 0; animation: fadein 0.5s linear forwards 0.6s'>
|
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#33343a' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='700' font-size='28px' font-style='normal' style='opacity: 1'>
|
||||||
344
|
344
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<!-- Total Contributions label -->
|
<!-- Total Contributions label -->
|
||||||
<g transform='translate(82.5, 84)'>
|
<g transform='translate(82.5, 84)'>
|
||||||
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#8b8f98' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='400' font-size='14px' font-style='normal' style='opacity: 0; animation: fadein 0.5s linear forwards 0.7s'>
|
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#3f424a' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='400' font-size='14px' font-style='normal' style='opacity: 1'>
|
||||||
Total Contributions
|
Total Contributions
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<!-- Total Contributions range -->
|
<!-- Total Contributions range -->
|
||||||
<g transform='translate(82.5, 114)'>
|
<g transform='translate(82.5, 114)'>
|
||||||
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#8b8f98' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='400' font-size='12px' font-style='normal' style='opacity: 0; animation: fadein 0.5s linear forwards 0.8s'>
|
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#3f424a' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='400' font-size='12px' font-style='normal' style='opacity: 1'>
|
||||||
May 24, 2019 - Present
|
May 24, 2019 - Present
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
@@ -54,31 +47,31 @@
|
|||||||
<g style='isolation: isolate'>
|
<g style='isolation: isolate'>
|
||||||
<!-- Current Streak label -->
|
<!-- Current Streak label -->
|
||||||
<g transform='translate(247.5, 108)'>
|
<g transform='translate(247.5, 108)'>
|
||||||
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#3454d1' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='700' font-size='14px' font-style='normal' style='opacity: 0; animation: fadein 0.5s linear forwards 0.9s'>
|
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#3454d1' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='700' font-size='14px' font-style='normal' style='opacity: 1'>
|
||||||
Current Streak
|
Current Streak
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<!-- Current Streak range -->
|
<!-- Current Streak range -->
|
||||||
<g transform='translate(247.5, 145)'>
|
<g transform='translate(247.5, 145)'>
|
||||||
<text x='0' y='21' stroke-width='0' text-anchor='middle' fill='#8b8f98' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='400' font-size='12px' font-style='normal' style='opacity: 0; animation: fadein 0.5s linear forwards 0.9s'>
|
<text x='0' y='21' stroke-width='0' text-anchor='middle' fill='#3f424a' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='400' font-size='12px' font-style='normal' style='opacity: 1'>
|
||||||
Nov 3
|
Nov 3
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<!-- Ring around number -->
|
<!-- Ring around number -->
|
||||||
<g mask='url(#mask_out_ring_behind_fire)'>
|
<g mask='url(#mask_out_ring_behind_fire)'>
|
||||||
<circle cx='247.5' cy='71' r='40' fill='none' stroke='#3454d1' stroke-width='5' style='opacity: 0; animation: fadein 0.5s linear forwards 0.4s'></circle>
|
<circle cx='247.5' cy='71' r='40' fill='none' stroke='#3454d1' stroke-width='5' style='opacity: 1'></circle>
|
||||||
</g>
|
</g>
|
||||||
<!-- Fire icon -->
|
<!-- Fire icon -->
|
||||||
<g transform='translate(247.5, 19.5)' stroke-opacity='0' style='opacity: 0; animation: fadein 0.5s linear forwards 0.6s'>
|
<g transform='translate(247.5, 19.5)' stroke-opacity='0' style='opacity: 1'>
|
||||||
<path d='M -12 -0.5 L 15 -0.5 L 15 23.5 L -12 23.5 L -12 -0.5 Z' fill='none'/>
|
<path d='M -12 -0.5 L 15 -0.5 L 15 23.5 L -12 23.5 L -12 -0.5 Z' fill='none'/>
|
||||||
<path d='M 1.5 0.67 C 1.5 0.67 2.24 3.32 2.24 5.47 C 2.24 7.53 0.89 9.2 -1.17 9.2 C -3.23 9.2 -4.79 7.53 -4.79 5.47 L -4.76 5.11 C -6.78 7.51 -8 10.62 -8 13.99 C -8 18.41 -4.42 22 0 22 C 4.42 22 8 18.41 8 13.99 C 8 8.6 5.41 3.79 1.5 0.67 Z M -0.29 19 C -2.07 19 -3.51 17.6 -3.51 15.86 C -3.51 14.24 -2.46 13.1 -0.7 12.74 C 1.07 12.38 2.9 11.53 3.92 10.16 C 4.31 11.45 4.51 12.81 4.51 14.2 C 4.51 16.85 2.36 19 -0.29 19 Z' fill='#3454d1' stroke-opacity='0'/>
|
<path d='M 1.5 0.67 C 1.5 0.67 2.24 3.32 2.24 5.47 C 2.24 7.53 0.89 9.2 -1.17 9.2 C -3.23 9.2 -4.79 7.53 -4.79 5.47 L -4.76 5.11 C -6.78 7.51 -8 10.62 -8 13.99 C -8 18.41 -4.42 22 0 22 C 4.42 22 8 18.41 8 13.99 C 8 8.6 5.41 3.79 1.5 0.67 Z M -0.29 19 C -2.07 19 -3.51 17.6 -3.51 15.86 C -3.51 14.24 -2.46 13.1 -0.7 12.74 C 1.07 12.38 2.9 11.53 3.92 10.16 C 4.31 11.45 4.51 12.81 4.51 14.2 C 4.51 16.85 2.36 19 -0.29 19 Z' fill='#3454d1' stroke-opacity='0'/>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<!-- Current Streak big number -->
|
<!-- Current Streak big number -->
|
||||||
<g transform='translate(247.5, 48)'>
|
<g transform='translate(247.5, 48)'>
|
||||||
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#33343a' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='700' font-size='28px' font-style='normal' style='animation: currstreak 0.6s linear forwards'>
|
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#33343a' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='700' font-size='28px' font-style='normal' >
|
||||||
0
|
0
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
@@ -87,21 +80,21 @@
|
|||||||
<g style='isolation: isolate'>
|
<g style='isolation: isolate'>
|
||||||
<!-- Longest Streak big number -->
|
<!-- Longest Streak big number -->
|
||||||
<g transform='translate(412.5, 48)'>
|
<g transform='translate(412.5, 48)'>
|
||||||
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#33343a' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='700' font-size='28px' font-style='normal' style='opacity: 0; animation: fadein 0.5s linear forwards 1.2s'>
|
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#33343a' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='700' font-size='28px' font-style='normal' style='opacity: 1'>
|
||||||
6
|
6
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<!-- Longest Streak label -->
|
<!-- Longest Streak label -->
|
||||||
<g transform='translate(412.5, 84)'>
|
<g transform='translate(412.5, 84)'>
|
||||||
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#8b8f98' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='400' font-size='14px' font-style='normal' style='opacity: 0; animation: fadein 0.5s linear forwards 1.3s'>
|
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#3f424a' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='400' font-size='14px' font-style='normal' style='opacity: 1'>
|
||||||
Longest Streak
|
Longest Streak
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<!-- Longest Streak range -->
|
<!-- Longest Streak range -->
|
||||||
<g transform='translate(412.5, 114)'>
|
<g transform='translate(412.5, 114)'>
|
||||||
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#8b8f98' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='400' font-size='12px' font-style='normal' style='opacity: 0; animation: fadein 0.5s linear forwards 1.4s'>
|
<text x='0' y='32' stroke-width='0' text-anchor='middle' fill='#3f424a' stroke='none' font-family='"Segoe UI", Ubuntu, sans-serif' font-weight='400' font-size='12px' font-style='normal' style='opacity: 1'>
|
||||||
Oct 19 - Oct 24
|
Oct 19 - Oct 24
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.1 KiB |
@@ -16,6 +16,11 @@ if (MODE === 'skip') {
|
|||||||
const SKIP_PREFIX = ['/admin/', '/photos-originals/']; // admin=CMS 路由;photos-originals=部署期 rsync 叠加层(不在 dist,另有部署链保障)
|
const SKIP_PREFIX = ['/admin/', '/photos-originals/']; // admin=CMS 路由;photos-originals=部署期 rsync 叠加层(不在 dist,另有部署链保障)
|
||||||
const SKIP_FILE = new Set(['/404.html']); // Astro 404 页不参与配对
|
const SKIP_FILE = new Set(['/404.html']); // Astro 404 页不参与配对
|
||||||
|
|
||||||
|
// 完全不参与检查的产物(连站内链接也不查):仅用于一次性预览路由。
|
||||||
|
// 书架方案预览页没有 en 对应页,而 Header 的语言切换会自动生成 /en/… 链接,
|
||||||
|
// 会误报「断链 + 配对缺」;该路由在用户选定方案后即删除。
|
||||||
|
const SKIP_ALL = new Set(['/books-preview/index.html']);
|
||||||
|
|
||||||
function walk(dir, out = []) {
|
function walk(dir, out = []) {
|
||||||
for (const e of readdirSync(dir)) {
|
for (const e of readdirSync(dir)) {
|
||||||
const p = join(dir, e);
|
const p = join(dir, e);
|
||||||
@@ -48,8 +53,9 @@ const fails = [];
|
|||||||
const warns = [];
|
const warns = [];
|
||||||
|
|
||||||
for (const f of files) {
|
for (const f of files) {
|
||||||
const html = readFileSync(f, 'utf8');
|
|
||||||
const rel = f.slice(DIST.length) || '/';
|
const rel = f.slice(DIST.length) || '/';
|
||||||
|
if (SKIP_ALL.has(rel)) continue;
|
||||||
|
const html = readFileSync(f, 'utf8');
|
||||||
|
|
||||||
// 站内 <a href>:仅根相对路径;#锚点/mailto/tel/外部/data: 全跳过
|
// 站内 <a href>:仅根相对路径;#锚点/mailto/tel/外部/data: 全跳过
|
||||||
for (const m of html.matchAll(/<a\s[^>]*href="([^"]*)"/g)) {
|
for (const m of html.matchAll(/<a\s[^>]*href="([^"]*)"/g)) {
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ const UA = 'wait4x-blog-assets/1.0 (+https://wait4x.online)';
|
|||||||
const ACCENT = '3454d1';
|
const ACCENT = '3454d1';
|
||||||
const INK_LIGHT = '33343a';
|
const INK_LIGHT = '33343a';
|
||||||
const INK_DARK = 'c9ccd4';
|
const INK_DARK = 'c9ccd4';
|
||||||
const MUTED_LIGHT = '8b8f98';
|
// 次级文字(Total Contributions / dates)也用 ink 档:旧的 #8b8f98/#9aa0aa 缩小后对比不足 4.5:1
|
||||||
const MUTED_DARK = '9aa0aa';
|
const MUTED_LIGHT = '3f424a';
|
||||||
|
const MUTED_DARK = 'b9bec8';
|
||||||
|
|
||||||
/** 同一张卡按明暗两套参数各存一份(组件内用 CSS 切换,零运行时请求) */
|
/** 同一张卡按明暗两套参数各存一份(组件内用 CSS 切换,零运行时请求) */
|
||||||
const ASSETS = [
|
const ASSETS = [
|
||||||
@@ -62,6 +63,26 @@ const ASSETS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 冻结进场动画:streak-stats 的 SVG 里元素带 `style='opacity: 0; animation: fadein … forwards'`,
|
||||||
|
* loading=lazy 时用户会先看到 0.5–1.5s 的半成品。这里把动画声明剥掉、opacity 归 1,
|
||||||
|
* 静态呈现最终态(同时删掉 @keyframes 块,减小体积)。
|
||||||
|
*/
|
||||||
|
function freezeAnimations(svg) {
|
||||||
|
let out = svg.replace(/style='([^']*)'/g, (_, css) => {
|
||||||
|
const cleaned = css
|
||||||
|
.split(';')
|
||||||
|
.map((decl) => decl.trim())
|
||||||
|
.filter((decl) => decl && !decl.startsWith('animation'))
|
||||||
|
.map((decl) => (/^opacity\s*:\s*0\b/.test(decl) ? 'opacity: 1' : decl))
|
||||||
|
.join('; ');
|
||||||
|
return cleaned ? `style='${cleaned}'` : '';
|
||||||
|
});
|
||||||
|
out = out.replace(/animation\s*:\s*[^;'"]*;?/g, '');
|
||||||
|
out = out.replace(/@keyframes[^{]*\{(?:[^{}]*\{[^{}]*\})*[^{}]*\}/g, '');
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
/** 10s 超时抓取;返回 SVG 文本或 null */
|
/** 10s 超时抓取;返回 SVG 文本或 null */
|
||||||
async function grab(url) {
|
async function grab(url) {
|
||||||
try {
|
try {
|
||||||
@@ -78,7 +99,7 @@ async function grab(url) {
|
|||||||
console.warn(`[assets] 非 SVG 响应,已跳过: ${url.slice(0, 90)}…`);
|
console.warn(`[assets] 非 SVG 响应,已跳过: ${url.slice(0, 90)}…`);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return text;
|
return freezeAnimations(text);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn(`[assets] 抓取失败(${err.name === 'TimeoutError' ? '超时' : err.message}): ${url.slice(0, 90)}…`);
|
console.warn(`[assets] 抓取失败(${err.name === 'TimeoutError' ? '超时' : err.message}): ${url.slice(0, 90)}…`);
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -82,6 +82,8 @@ for (const [key, label] of [
|
|||||||
dark: hasAsset(`${key}-dark.svg`) ? assetPath(`${key}-dark.svg`) : undefined,
|
dark: hasAsset(`${key}-dark.svg`) ? assetPath(`${key}-dark.svg`) : undefined,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// 只有一张非通栏卡时让它占满整行(否则右半空档;stats/top-langs 上游 503 时就是这种情形)
|
||||||
|
const soloCard = boardCards.length === 1;
|
||||||
const snakeCard = hasAsset('snake.svg')
|
const snakeCard = hasAsset('snake.svg')
|
||||||
? { label: locale === 'zh' ? '贡献蛇' : 'Contribution snake', src: assetPath('snake.svg') }
|
? { label: locale === 'zh' ? '贡献蛇' : 'Contribution snake', src: assetPath('snake.svg') }
|
||||||
: null;
|
: null;
|
||||||
@@ -130,6 +132,7 @@ const L = {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* 统计三格:关注者 / 公开仓库 / 总星标(贡献数走热力图,不在此重复) */}
|
||||||
{(stats || totalStars !== null) && (
|
{(stats || totalStars !== null) && (
|
||||||
<dl class="pf-stats mono">
|
<dl class="pf-stats mono">
|
||||||
{stats && (
|
{stats && (
|
||||||
@@ -165,7 +168,12 @@ const L = {
|
|||||||
<p class="pf-board-title mono">{locale === 'zh' ? '数据板' : 'Data board'}</p>
|
<p class="pf-board-title mono">{locale === 'zh' ? '数据板' : 'Data board'}</p>
|
||||||
<div class="pf-board-grid">
|
<div class="pf-board-grid">
|
||||||
{boardCards.map((card) => (
|
{boardCards.map((card) => (
|
||||||
<figure class="pf-card">
|
<figure
|
||||||
|
class:list={[
|
||||||
|
'pf-card',
|
||||||
|
{ 'pf-card-streak': card.light.includes('streak'), 'pf-card-solo': soloCard },
|
||||||
|
]}
|
||||||
|
>
|
||||||
<img class="pf-card-img only-light" src={card.light} alt={card.label} loading="lazy" decoding="async" />
|
<img class="pf-card-img only-light" src={card.light} alt={card.label} loading="lazy" decoding="async" />
|
||||||
{card.dark && (
|
{card.dark && (
|
||||||
<img class="pf-card-img only-dark" src={card.dark} alt={card.label} loading="lazy" decoding="async" />
|
<img class="pf-card-img only-dark" src={card.dark} alt={card.label} loading="lazy" decoding="async" />
|
||||||
@@ -240,7 +248,8 @@ const L = {
|
|||||||
display: flex;
|
display: flex;
|
||||||
gap: var(--space-2);
|
gap: var(--space-2);
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: var(--space-2) 0 0;
|
/* 光学对齐:.tap 的 44px 热区带左右 padding,整体左移使图标视觉左缘对齐正文列 */
|
||||||
|
margin: var(--space-2) 0 0 -0.55rem;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
.pf-socials a { color: var(--ink-3); display: inline-flex; }
|
.pf-socials a { color: var(--ink-3); display: inline-flex; }
|
||||||
@@ -281,7 +290,6 @@ const L = {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.35rem;
|
gap: 0.35rem;
|
||||||
max-width: 32rem;
|
|
||||||
}
|
}
|
||||||
.pf-lang {
|
.pf-lang {
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -323,9 +331,11 @@ const L = {
|
|||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.04em;
|
||||||
margin-bottom: var(--space-2);
|
margin-bottom: var(--space-2);
|
||||||
}
|
}
|
||||||
|
/* 自适应列:只有 1 张卡时自动占满整行(避免右半空档),≥2 张时并排;
|
||||||
|
320px 下限保证车卡内 SVG 不被压到字号过小 */
|
||||||
.pf-board-grid {
|
.pf-board-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
||||||
gap: var(--space-2);
|
gap: var(--space-2);
|
||||||
}
|
}
|
||||||
.pf-card {
|
.pf-card {
|
||||||
@@ -339,7 +349,7 @@ const L = {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
}
|
}
|
||||||
.pf-card-wide { grid-column: 1 / -1; }
|
.pf-card-wide, .pf-card-solo { grid-column: 1 / -1; }
|
||||||
.pf-card-img { max-width: 100%; height: auto; display: block; }
|
.pf-card-img { max-width: 100%; height: auto; display: block; }
|
||||||
.pf-card figcaption {
|
.pf-card figcaption {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
@@ -349,9 +359,12 @@ const L = {
|
|||||||
/* 明暗两版自托管 SVG:默认只显示亮色,暗色主题切到暗色版 */
|
/* 明暗两版自托管 SVG:默认只显示亮色,暗色主题切到暗色版 */
|
||||||
/* 贡献蛇:SVG 内部用自带 CSS 变量(绿阶 + #ebedf0 空格),<img> 无法改写内部配色 →
|
/* 贡献蛇:SVG 内部用自带 CSS 变量(绿阶 + #ebedf0 空格),<img> 无法改写内部配色 →
|
||||||
滤镜归一到站点灰阶;暗色下反相,避免浅灰格子贴在深底上刺眼(想去掉绿→灰只改这一行) */
|
滤镜归一到站点灰阶;暗色下反相,避免浅灰格子贴在深底上刺眼(想去掉绿→灰只改这一行) */
|
||||||
|
/* streak 卡的环/火苗是写死的品牌蓝:亮色下去色以贴合灰阶数据卡;暗色保留原卡 */
|
||||||
|
.pf-card-streak .pf-card-img { filter: grayscale(1); }
|
||||||
.pf-card-snake .pf-card-img { filter: grayscale(1) contrast(1.03); }
|
.pf-card-snake .pf-card-img { filter: grayscale(1) contrast(1.03); }
|
||||||
|
/* 暗色蛇:只 invert 会把空格色压得与页面底色接近、矩阵骨架消失 → 叠加 contrast/brightness 找回网格 */
|
||||||
:global([data-theme='dark']) .pf-card-snake .pf-card-img {
|
:global([data-theme='dark']) .pf-card-snake .pf-card-img {
|
||||||
filter: grayscale(1) invert(1) contrast(0.92);
|
filter: grayscale(1) invert(1) contrast(1.18) brightness(1.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
.only-dark { display: none; }
|
.only-dark { display: none; }
|
||||||
|
|||||||
@@ -88,8 +88,9 @@ try {
|
|||||||
.repo-desc {
|
.repo-desc {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: var(--ink-3);
|
color: var(--ink-3);
|
||||||
/* 居中后长描述限行宽,避免整行摊平散架 */
|
/* 居中后长描述限行宽,避免整行摊平散架;pretty 减少末行孤词 */
|
||||||
max-width: 34em;
|
max-width: 34em;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
.repo-meta { display: flex; gap: var(--space-3); font-size: 12px; color: var(--ink-3); margin-top: 4px; }
|
.repo-meta { display: flex; gap: var(--space-3); font-size: 12px; color: var(--ink-3); margin-top: 4px; }
|
||||||
.lang { display: inline-flex; align-items: center; gap: 4px; }
|
.lang { display: inline-flex; align-items: center; gap: 4px; }
|
||||||
|
|||||||
@@ -85,14 +85,17 @@ const first = safe[0] ?? '';
|
|||||||
margin: 0 0 var(--space-2);
|
margin: 0 0 var(--space-2);
|
||||||
min-height: 1.6em; /* 固定行高,打字期间不推挤下方内容 */
|
min-height: 1.6em; /* 固定行高,打字期间不推挤下方内容 */
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
/* baseline:光标与末行基线对齐(center 会在两行时把光标拉到中间) */
|
||||||
gap: 1px;
|
align-items: baseline;
|
||||||
|
gap: 2px;
|
||||||
}
|
}
|
||||||
.typing-text { white-space: pre-wrap; }
|
.typing-text { white-space: pre-wrap; }
|
||||||
.typing-caret {
|
.typing-caret {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 0.5em;
|
width: 2px; /* 细竖条:不参与折行计算 */
|
||||||
height: 1em;
|
height: 1em;
|
||||||
|
align-self: baseline;
|
||||||
|
transform: translateY(0.12em);
|
||||||
background: var(--accent);
|
background: var(--accent);
|
||||||
animation: caret-blink 1.05s steps(1) infinite;
|
animation: caret-blink 1.05s steps(1) infinite;
|
||||||
}
|
}
|
||||||
@@ -100,6 +103,10 @@ const first = safe[0] ?? '';
|
|||||||
0%, 49% { opacity: 1; }
|
0%, 49% { opacity: 1; }
|
||||||
50%, 100% { opacity: 0; }
|
50%, 100% { opacity: 0; }
|
||||||
}
|
}
|
||||||
|
/* 窄屏预留两行高度:长句折行时不再每轮下推再弹回(实测 390 视口曾推挤 ~21px) */
|
||||||
|
@media (max-width: 560px) {
|
||||||
|
.typing { min-height: calc(1.6em * 2); }
|
||||||
|
}
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
.typing-caret { animation: none; opacity: 0.6; }
|
.typing-caret { animation: none; opacity: 0.6; }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user