Compare commits

..

No commits in common. "master" and "v1.2.5" have entirely different histories.

13 changed files with 69 additions and 456 deletions

View file

@ -1,10 +1,5 @@
# SanYeCao-Blog
<p align="right">[<a href="./README.md">中文</a> | <a href="./README-en.md">English</a>]</p>
> [!CAUTION]
>
> This project is no longer maintained, for further updates, see:<b>[ClovertaTheTrilobita/astro-blog-template](https://github.com/ClovertaTheTrilobita/astro-blog-template)</b>
<p align="center"><br>
✨SanYeCao Blog✨<br>
🌊Lightweight / Fast / Beautiful🌊<br><br>

View file

@ -2,10 +2,6 @@
<p align="right">[<a href="./README.md">中文</a> | <a href="./README-en.md">English</a>]</p>
> [!CAUTION]
>
> 此项目已不再维护,后续更新请移步:<b>[ClovertaTheTrilobita/astro-blog-template](https://github.com/ClovertaTheTrilobita/astro-blog-template)</b>
<p align="center"><br>
✨三叶草Blog✨<br>
🌊轻度/快速/美观🌊<br><br>
@ -22,7 +18,9 @@
<br>
<p align="center">
<img width="873" height="504" alt="image" src="https://github.com/user-attachments/assets/a39626f9-5ad6-450c-a535-2791878b5ebf" alt="preview-zh" />
<img width="868" height="503" alt="image" src="https://github.com/user-attachments/assets/f9551692-1720-42c2-a75d-576e2b8dc571"
alt="preview-zh"
/>
</p>
<br>

View file

@ -1,22 +1,20 @@
<img width="1582" height="1035" alt="image" src="https://github.com/user-attachments/assets/8e159ac2-5636-429c-ad09-b77798f5140d" />
<img width="2879" height="1848" alt="image" src="https://github.com/user-attachments/assets/48813e56-af63-4e34-9f6c-5d48a098d4e0" style="zoom:25%;" />
<br>
<img width="1582" height="1035" alt="image" src="https://github.com/user-attachments/assets/30f683a6-229c-4357-8079-3e374a6d5187" />
<img width="2879" height="1848" alt="image" src="https://github.com/user-attachments/assets/8d5dda1f-6577-4fce-9d29-e2ac9d7fe665" style="zoom:25%;" />
<br>
<img width="1582" height="1035" alt="image" src="https://github.com/user-attachments/assets/566712e3-ff8f-4a7b-867b-b3eaa7881f9d" />
<img width="2879" height="1848" alt="image" src="https://github.com/user-attachments/assets/fb6b4715-a86e-4a19-ab13-c648afad3e8c" style="zoom:25%;" />
<br>
<img width="1582" height="1035" alt="image" src="https://github.com/user-attachments/assets/58de77f0-f7e1-45c8-a2c3-b5063382bf0e" />
<img width="2879" height="1848" alt="image" src="https://github.com/user-attachments/assets/340b4d91-4f6e-4f37-b3ec-e33113cdc2a2" style="zoom:25%;" />
<br>
<img width="1582" height="1035" alt="image" src="https://github.com/user-attachments/assets/d0941aba-ce9e-4b9c-bad1-ae11c266bde2" />
<img width="2879" height="1848" alt="image" src="https://github.com/user-attachments/assets/36267696-91f7-4c88-9565-4713547d0453" style="zoom:25%;" />
<br>

View file

@ -96,7 +96,19 @@ const tags = data.tags;
.post-title {
margin: 0;
font-family: var(--font-serif);
font-family:
"Noto Sans SC",
system-ui,
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
Roboto,
Oxygen,
Ubuntu,
Cantarell,
"Open Sans",
"Helvetica Neue",
sans-serif;
font-weight: 500;
font-size: 1.34rem;
line-height: 1.5;
@ -172,30 +184,6 @@ const tags = data.tags;
color: #aab7c4;
}
:global(html:lang(zh)) .post-title {
font-size: 1.5rem;
line-height: 1.45;
}
:global(html:lang(zh)) .post-description {
font-size: 1.0625rem;
line-height: 1.8;
}
:global(html:lang(zh)) .tags {
margin-top: 0.6rem;
font-size: 0.9375rem;
}
:global(html:lang(zh)) .post-meta-row {
margin-top: 0.6rem;
font-size: 0.875rem;
}
:global(html:lang(zh)) .post-card + .post-card {
margin-top: 1.75rem;
}
@media (max-width: 600px) {
.post-link {
display: grid;
@ -252,21 +240,5 @@ const tags = data.tags;
padding-bottom: 0.2rem;
padding-top: 0.2rem;
}
:global(html:lang(zh)) .post-title {
font-size: 1.4375rem;
}
:global(html:lang(zh)) .post-link {
grid-template-columns: minmax(0, 1fr) clamp(6rem, 30vw, 8rem);
}
:global(html:lang(zh)) .post-image-link {
width: 100%;
}
:global(html:lang(zh)) .post-image {
height: auto;
}
}
</style>

View file

@ -1,16 +1,11 @@
---
import Remark42Status from "./Remark42Status.astro";
const { slug } = Astro.props;
const pagePath = `/posts/${slug}/`;
const host = import.meta.env.PUBLIC_REMARK42_HOST;
const siteId = import.meta.env.PUBLIC_REMARK42_SITE_ID;
---
<div class="remark42-embed">
<Remark42Status />
<div id="remark42"></div>
</div>
<script define:vars={{ pagePath, host, siteId }} is:inline data-astro-rerun>
function getTheme() {
return document.documentElement.classList.contains("dark")
@ -60,99 +55,28 @@ const siteId = import.meta.env.PUBLIC_REMARK42_SITE_ID;
}
script.onload = () => resolve(true);
script.onerror = (error) => {
script.remove();
reject(error);
};
script.onerror = reject;
document.head.appendChild(script);
});
}
async function mountRemark42() {
const node = document.getElementById("remark42");
const status = document.getElementById("remark42-status");
const loadingStatus = status?.querySelector("[data-remark42-loading]");
const failedStatus = status?.querySelector("[data-remark42-failed]");
if (!node || !loadingStatus || !failedStatus) return;
if (!node) return;
window.__remark42LoadCleanup?.();
let active = true;
let iframe = null;
let timer;
const onIframeLoad = () => {
if (!active || !iframe || !node.contains(iframe)) return;
loadingStatus.hidden = true;
failedStatus.hidden = true;
status.hidden = true;
clearTimeout(timer);
observer.disconnect();
};
const watchIframe = () => {
const nextIframe = node.querySelector("iframe");
if (nextIframe === iframe) return;
iframe?.removeEventListener("load", onIframeLoad);
iframe = nextIframe;
iframe?.addEventListener("load", onIframeLoad, { once: true });
};
const observer = new MutationObserver(watchIframe);
observer.observe(node, { childList: true, subtree: true });
watchIframe();
const showFailure = () => {
if (!active || loadingStatus.hidden) return;
loadingStatus.hidden = true;
failedStatus.hidden = false;
};
window.__remark42LoadCleanup = () => {
active = false;
clearTimeout(timer);
observer.disconnect();
iframe?.removeEventListener("load", onIframeLoad);
};
loadingStatus.hidden = false;
failedStatus.hidden = true;
status.hidden = false;
timer = setTimeout(showFailure, 15000);
if (!host || !siteId) {
showFailure();
return;
}
try {
const alreadyLoaded = Boolean(window.REMARK42);
setRemarkConfig();
await ensureScript();
if (!active) return;
if (!window.REMARK42) {
showFailure();
return;
}
if (!window.REMARK42) return;
if (alreadyLoaded && typeof window.REMARK42.destroy === "function") {
if (typeof window.REMARK42.destroy === "function") {
window.REMARK42.destroy();
}
// The script creates the first iframe itself. Only remount when
// reusing it on a new page/theme, or if it did not create one.
if (
(alreadyLoaded || !node.querySelector("iframe")) &&
typeof window.REMARK42.createInstance === "function"
) {
if (typeof window.REMARK42.createInstance === "function") {
node.innerHTML = "";
window.REMARK42.createInstance(window.remark_config);
}
} catch {
showFailure();
}
}
function setupRemark42ThemeObserver() {
@ -182,18 +106,3 @@ const siteId = import.meta.env.PUBLIC_REMARK42_SITE_ID;
mountRemark42();
setupRemark42ThemeObserver();
</script>
<style>
.remark42-embed {
position: relative;
min-width: 0;
}
/* Let the iframe load in the same space occupied by the centered status. */
:global(#remark42-status:not([hidden])) + #remark42 {
position: absolute;
inset: 0;
visibility: hidden;
pointer-events: none;
}
</style>

View file

@ -1,230 +0,0 @@
---
import { getLangFromUrl } from "@/i18n";
const lang = getLangFromUrl(Astro.url);
const loadingText = lang === "zh" ? "评论区加载中…" : "Loading comments…";
const failedText = lang === "zh" ? "评论区加载失败" : "Failed to load comments";
---
<div id="remark42-status" role="status" aria-atomic="true">
<p class="remark42-loading" data-remark42-loading>
<span class="coffee-animation" aria-hidden="true">
<span class="coffee">
<span></span>
<span></span>
<span></span>
</span>
</span>
<span>{loadingText}</span>
</p>
<p class="remark42-failed" data-remark42-failed hidden>
<span class="broken-coffee" aria-hidden="true">
<span class="coffee-spill"></span>
<span class="coffee-fallen">
<span class="coffee-half coffee-half-left"></span>
<span class="coffee-half coffee-half-right">
<span class="coffee-handle"></span>
</span>
</span>
</span>
<span>{failedText}</span>
</p>
</div>
<style>
#remark42-status {
--status-color: #6b7680;
--status-accent: var(--deep-blue);
display: grid;
place-items: center;
min-block-size: 10rem;
padding: 1.5rem 1rem;
text-align: center;
}
.remark42-loading,
.remark42-failed {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 0.85rem;
margin: 0;
color: var(--status-color);
font-size: 0.85rem;
font-weight: 400;
line-height: 1.6;
}
/* Coffee animation adapted from jh3y — jheytompkins.com. */
.coffee-animation {
position: relative;
flex: 0 0 auto;
width: 2.5rem;
height: 4rem;
color: var(--status-accent);
}
.coffee {
position: absolute;
bottom: 0;
left: 0;
display: grid;
grid-template-columns: repeat(3, 1fr);
justify-items: center;
box-sizing: border-box;
width: 2rem;
height: 2rem;
padding: 0.1rem;
border-radius: 0.2rem;
background: currentColor;
}
.coffee::before,
.coffee-handle {
content: "";
position: absolute;
top: 50%;
left: 100%;
box-sizing: border-box;
width: 1rem;
height: 1.3rem;
margin-left: -0.5rem;
border: 0.2rem solid currentColor;
border-radius: 0.2rem;
transform: translateY(-50%);
}
.coffee > span {
width: 0.4rem;
height: 1rem;
background: currentColor;
opacity: 0.3;
animation: coffee-steam 2s infinite;
}
.coffee > span:nth-child(1) {
animation-delay: 0.4s;
}
.coffee > span:nth-child(2) {
animation-delay: 1s;
}
.coffee > span:nth-child(3) {
animation-delay: 0.2s;
}
/* Two lengthwise halves resting in a spill; reuse the loading cup's silhouette. */
.broken-coffee {
position: relative;
flex: 0 0 auto;
width: 4.5rem;
height: 4rem;
color: var(--status-accent);
}
.coffee-fallen {
position: absolute;
top: 0.8rem;
left: 1.05rem;
width: 2rem;
height: 2.3rem;
transform: rotate(23deg);
}
.coffee-half {
position: absolute;
inset: 0;
}
.coffee-half::before {
content: "";
position: absolute;
inset: 0;
border-radius: 0.2rem;
background: currentColor;
}
.coffee-half-left {
transform: translate(-0.16rem, -0.07rem) rotate(-3deg);
}
.coffee-half-left::before {
clip-path: polygon(
0 0, 54% 0, 42% 23%, 58% 40%,
43% 58%, 56% 76%, 46% 100%, 0 100%
);
}
.coffee-half-right {
transform: translate(0.17rem, 0.08rem) rotate(3deg);
}
.coffee-half-right::before {
clip-path: polygon(
54% 0, 100% 0, 100% 100%, 46% 100%,
56% 76%, 43% 58%, 58% 40%, 42% 23%
);
}
.coffee-spill {
position: absolute;
top: 0.75rem;
left: 0.5rem;
width: 3.55rem;
height: 2.8rem;
border-radius: 43% 57% 30% 70% / 56% 37% 63% 44%;
background: currentColor;
/* Same ink as the cup, softened like the loading animation's steam. */
opacity: 0.2;
transform: rotate(-8deg);
}
.coffee-spill::before {
content: "";
position: absolute;
top: -0.5rem;
left: 0.9rem;
width: 1.8rem;
height: 1.4rem;
border-radius: 45% 55% 38% 62%;
background: inherit;
}
.coffee-spill::after {
content: "";
position: absolute;
left: 0.45rem;
bottom: -0.3rem;
width: 2.4rem;
height: 1.1rem;
border-radius: 40% 60% 54% 46%;
background: inherit;
}
#remark42-status[hidden],
[hidden] {
display: none;
}
:global(html.dark) #remark42-status {
--status-color: #aab7c4;
--status-accent: #9ecbff;
}
@keyframes coffee-steam {
to {
opacity: 0;
transform: translateY(-200%);
}
}
@media (prefers-reduced-motion: reduce) {
.coffee > span {
animation: none;
opacity: 0.2;
transform: translateY(-65%);
}
}
</style>

View file

@ -14,7 +14,7 @@ const { tag, lang } = Astro.props;
display: inline-block;
max-width: 100%;
padding-block: 0.2rem;
font-family: var(--font-serif);
font-family: "Noto Sans SC", system-ui, sans-serif;
font-size: inherit;
font-weight: 400;
line-height: 1.6;

View file

@ -17,7 +17,7 @@ export default {
publishedOn: "Published on",
commentsDesc: [
"Feel free to leave your thoughts here. 💭💡",
"After signing in, you can click “Subscribe by Email” at the bottom right of the text box to receive notifications via E-mail."
"After signing in, you can click the “Subscribe by Email” button at the bottom right of the text box to receive notifications of new interactions via email."
]
},
theme: {

View file

@ -35,6 +35,10 @@ const {
href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;700&display=swap"
rel="stylesheet"
/>
<meta name="generator" content={Astro.generator} />
<title>{pageTitle}</title>
</head>

View file

@ -103,9 +103,7 @@ const publishedDate = new Intl.DateTimeFormat(
aria-labelledby="comments-heading"
>
<h2 id="comments-heading">{comments}</h2>
{t.post.commentsDesc.map((line: string) => (
<p class="comments-description" set:html={line} />
))}
{t.post.commentsDesc.map((line: string) => <p set:html={line} />)}
<Remark42Embed slug={slug} />
</section>
</article>
@ -309,7 +307,17 @@ const publishedDate = new Intl.DateTimeFormat(
--article-muted: #596672;
--article-rule: rgba(83, 100, 147, 0.25);
--article-tint: rgba(83, 100, 147, 0.045);
font-family: var(--font-serif);
font-family:
system-ui,
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
"PingFang SC",
"Hiragino Sans GB",
"Microsoft YaHei",
"Noto Sans CJK SC",
"Source Han Sans SC",
sans-serif;
font-size: 1.07rem;
font-weight: 400;
line-height: 1.85;
@ -320,18 +328,13 @@ const publishedDate = new Intl.DateTimeFormat(
margin-top: 0;
}
:global(html:lang(zh)) .post-content {
font-size: 1.125rem;
line-height: 1.9;
}
.post-content :global(p) {
margin-block: 1.05em;
}
.post-content :global(h2) {
margin: 3.2rem 0 1rem;
font-family: var(--font-serif);
font-family: "Noto Sans SC", system-ui, sans-serif;
font-size: clamp(1.35rem, 2vw, 1.55rem);
line-height: 1.4;
text-wrap: balance;
@ -339,7 +342,7 @@ const publishedDate = new Intl.DateTimeFormat(
.post-content :global(h3) {
margin: 2.25rem 0 0.8rem;
font-family: var(--font-serif);
font-family: "Noto Sans SC", system-ui, sans-serif;
font-size: clamp(1.12rem, 1.6vw, 1.28rem);
line-height: 1.45;
text-wrap: balance;
@ -347,7 +350,7 @@ const publishedDate = new Intl.DateTimeFormat(
.post-content :global(h4) {
margin: 1.8rem 0 0.65rem;
font-family: var(--font-serif);
font-family: "Noto Sans SC", system-ui, sans-serif;
line-height: 1.5;
font-size: 1.05em;
}
@ -393,7 +396,7 @@ const publishedDate = new Intl.DateTimeFormat(
.post-content :global(figcaption) {
margin-top: 0.55rem;
color: var(--article-muted);
font-family: var(--font-serif);
font-family: "Noto Sans SC", system-ui, sans-serif;
font-size: 0.78rem;
line-height: 1.5;
text-align: center;
@ -490,7 +493,7 @@ const publishedDate = new Intl.DateTimeFormat(
gap: 0.3rem 0.55rem;
margin: 0.3rem 0;
color: #66717c;
font-family: var(--font-serif);
font-family: "Noto Sans SC", system-ui, sans-serif;
font-size: 0.8rem;
font-weight: 400;
line-height: 1.5;
@ -502,15 +505,6 @@ const publishedDate = new Intl.DateTimeFormat(
opacity: 0.65;
}
:global(html:lang(zh)) .description {
font-size: 1.0625rem;
line-height: 1.8;
}
:global(html:lang(zh)) .post-byline {
font-size: 0.875rem;
}
:global(html.dark) .post-byline {
color: #aab7c4;
}
@ -659,16 +653,6 @@ const publishedDate = new Intl.DateTimeFormat(
scroll-margin-top: 5rem;
}
.comments-description {
color: #6b7680;
font-size: 0.85rem;
line-height: 1.6;
}
:global(html.dark) .comments-description {
color: #aab7c4;
}
:global(html.dark) .post-content {
--article-muted: #aab7c4;
--article-rule: rgba(170, 183, 196, 0.28);

View file

@ -83,19 +83,13 @@ const rssLink = lang === "zh" ? "/rss.xml" : "/en/rss.xml";
.section-title,
.index :global(.latest-comments > h2) {
margin: 0 0 1.25rem;
font-family: var(--font-serif);
font-family: "Noto Sans SC", system-ui, sans-serif;
font-size: 0.95rem;
font-weight: 500;
line-height: 1.5;
color: #66717c;
}
:global(html:lang(zh)) .section-title,
:global(html:lang(zh)) .index :global(.latest-comments > h2) {
font-size: 1.0625rem;
margin-bottom: 1rem;
}
:global(html.dark) .section-title,
:global(html.dark) .index :global(.latest-comments > h2) {
color: #aab7c4;

View file

@ -16,9 +16,14 @@ article svg[id^="mermaid-"] {
}
html {
--font-serif: "Noto Serif SC", "Source Han Serif SC", "Songti SC",
"STSong", "SimSun", serif;
font-family: var(--font-serif);
/* font-family: "Maple Mono", "Maple Mono CN", monospace; */
font-family:
"Noto Serif SC",
"Source Han Serif SC",
"Songti SC",
"STSong",
"SimSun",
serif;
font-weight: 500;
/* background-color: #ffffff; */
background-color: var(--background-color);
@ -31,18 +36,6 @@ html {
scrollbar-color: #828282 transparent;
}
/* 中文保留适合阅读的常规字重。 */
html:lang(zh) {
font-weight: 400;
}
button,
input,
select,
textarea {
font-family: var(--font-serif);
}
body {
margin: 0 auto;
width: 100%;
@ -106,10 +99,6 @@ html.dark body::after {
body {
font-size: 1rem;
}
html:lang(zh) body {
font-size: 1.0625rem;
}
}

View file

@ -84,7 +84,7 @@
justify-content: center;
background: rgba(160, 175, 190, 0.14);
color: #5e6b77;
font-family: var(--font-serif);
font-family: system-ui, sans-serif;
font-size: 0.85rem;
font-weight: 600;
user-select: none;
@ -101,7 +101,7 @@
align-items: baseline;
gap: 0.25rem 0.55rem;
min-width: 0;
font-family: var(--font-serif);
font-family: system-ui, sans-serif;
line-height: 1.35;
}
@ -126,7 +126,7 @@
max-height: 4.65em;
overflow: hidden;
color: #3f4a54;
font-family: var(--font-serif);
font-family: system-ui, sans-serif;
font-size: 0.93rem;
font-weight: 400;
line-height: 1.55;
@ -143,7 +143,7 @@
gap: 0.55rem 1rem;
min-width: 0;
color: #89939c;
font-family: var(--font-serif);
font-family: system-ui, sans-serif;
font-size: 0.75rem;
line-height: 1.45;
}