@xingwangzhe/stalux 1.55.7 → 1.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/components/stalux/archives/archivesList.astro +1 -2
- package/src/components/stalux/archives/toArchive.astro +1 -1
- package/src/components/stalux/categories/categoriesCard.astro +1 -5
- package/src/components/stalux/common/author.astro +1 -1
- package/src/components/stalux/layout/navs.astro +1 -6
- package/src/components/stalux/posts/ArticleSummary.astro +0 -1
- package/src/components/stalux/posts/PostTaxonomy.astro +1 -5
- package/src/components/stalux/posts/postCard.astro +5 -16
- package/src/components/stalux/posts/postContent.astro +3 -7
- package/src/components/stalux/posts/postNavigation.astro +0 -2
- package/src/components/stalux/tags/tagHeader.astro +3 -3
- package/src/components/stalux/tags/tagsCloud.astro +2 -3
- package/src/index.ts +13 -0
- package/src/internal/html-output.ts +18 -0
- package/src/internal/route-hrefs.ts +47 -0
- package/src/internal/social-card-data.ts +1 -1
- package/src/internal/style-names.generated.ts +4 -19
- package/src/layouts/PostLayout.astro +0 -4
- package/src/pages/404.astro +1 -2
- package/src/pages/about.astro +0 -1
- package/src/pages/api/posts.json.ts +1 -1
- package/src/pages/atom.xml.ts +2 -0
- package/src/pages/posts/[post].md.ts +2 -2
- package/src/pages/rss.xml.ts +2 -0
- package/src/scripts/swup-router.ts +7 -1
- package/src/styles/generated.css +1 -1
- package/src/styles/motion.css +0 -123
- package/src/utils/ai-discovery.ts +1 -1
- package/src/utils/feed.ts +1 -1
- package/src/utils/public-routes.ts +14 -4
- package/src/utils/seo-document.ts +3 -2
- package/src/utils/view-transitions.ts +4 -109
package/package.json
CHANGED
|
@@ -98,10 +98,9 @@ const archiveYears = [...archivesByYearMonth.entries()]
|
|
|
98
98
|
)}
|
|
99
99
|
</time>
|
|
100
100
|
<a
|
|
101
|
-
href={`/posts/${post.data.abbrlink}
|
|
101
|
+
href={`/posts/${post.data.abbrlink}`}
|
|
102
102
|
class="stalux-archive-post-link"
|
|
103
103
|
data-archive-description={post.data.desc || ""}
|
|
104
|
-
data-astro-prefetch="viewport"
|
|
105
104
|
>
|
|
106
105
|
{post.data.title}
|
|
107
106
|
</a>
|
|
@@ -11,5 +11,5 @@ const { t } = createTranslator(siteConfig.lang || "zh-CN");
|
|
|
11
11
|
|
|
12
12
|
<!-- Modern Web Guidance (html): 一行“查看全部归档”文字 + 链接 => <p>。 -->
|
|
13
13
|
<p id={"stalux-to-archive-archs"}>
|
|
14
|
-
<a data-stalux-control="button" href="/archives"
|
|
14
|
+
<a data-stalux-control="button" href="/archives">{t("archives.viewAll")}</a>
|
|
15
15
|
</p>
|
|
@@ -23,11 +23,7 @@ const { t } = createTranslator((siteConfig.lang as string) || "zh-CN");
|
|
|
23
23
|
<!-- Modern Web Guidance (html): 分类卡本身即 <article>;外层曾经的 <div class="stalux-category-shell">
|
|
24
24
|
已上移到列表的 <li>(见 categoriesList.astro),避免多一层无语义容器。 -->
|
|
25
25
|
<article class="stalux-category-card" data-stalux-control="category-card">
|
|
26
|
-
<a
|
|
27
|
-
href={`/categories/${props.category.name}/`}
|
|
28
|
-
class="stalux-categoryheader a-none"
|
|
29
|
-
data-astro-prefetch
|
|
30
|
-
>
|
|
26
|
+
<a href={`/categories/${props.category.name}`} class="stalux-categoryheader a-none">
|
|
31
27
|
<span class="stalux-category-icon">
|
|
32
28
|
<svg
|
|
33
29
|
aria-hidden="true"
|
|
@@ -22,7 +22,7 @@ const navigationHref = isHomePage ? "/about" : "/";
|
|
|
22
22
|
<figure
|
|
23
23
|
class={`stalux-author-figure ${props.iscolum ? "stalux-author-figure-column stalux-u-flex-col" : ""}`}
|
|
24
24
|
>
|
|
25
|
-
<a data-stalux-control="avatar" href={navigationHref} class="a-none"
|
|
25
|
+
<a data-stalux-control="avatar" href={navigationHref} class="a-none">
|
|
26
26
|
<Image src={authorConfig.avatar} alt={authorConfig.name} width={100} height={100} />
|
|
27
27
|
</a>
|
|
28
28
|
<figcaption>{authorConfig.name}</figcaption>
|
|
@@ -54,12 +54,7 @@ const navs = navsConfig?.items ?? [];
|
|
|
54
54
|
const NavIcon = item.icon ? getLucideIcon(item.icon, Astro.logger) : null;
|
|
55
55
|
return (
|
|
56
56
|
<li class="stalux-nav-item stalux-u-flex stalux-u-items-center">
|
|
57
|
-
<a
|
|
58
|
-
href={item.link}
|
|
59
|
-
class="stalux-nav-link"
|
|
60
|
-
data-ref="stalux-nav-link"
|
|
61
|
-
data-astro-prefetch
|
|
62
|
-
>
|
|
57
|
+
<a href={item.link} class="stalux-nav-link" data-ref="stalux-nav-link">
|
|
63
58
|
{NavIcon && <NavIcon size={20} stroke-width={2} class="nav-icon" />}
|
|
64
59
|
<span class="stalux-nav-text">{item.title}</span>
|
|
65
60
|
</a>
|
|
@@ -51,11 +51,7 @@ const cfg = {
|
|
|
51
51
|
<ul class={cfg.listClass} data-stalux-reveal>
|
|
52
52
|
{items.map((item) => (
|
|
53
53
|
<li data-stalux-reveal-item>
|
|
54
|
-
<a
|
|
55
|
-
href={`${cfg.prefix}${item}/`}
|
|
56
|
-
class={`${cfg.itemClass} a-none`}
|
|
57
|
-
data-astro-prefetch
|
|
58
|
-
>
|
|
54
|
+
<a href={`${cfg.prefix}${item}`} class={`${cfg.itemClass} a-none`}>
|
|
59
55
|
{item}
|
|
60
56
|
</a>
|
|
61
57
|
</li>
|
|
@@ -27,12 +27,7 @@ const description = post.data.desc || "";
|
|
|
27
27
|
class="stalux-post-card-shell stalux-post-card h-full text-inherit no-underline stalux-u-flex stalux-u-flex-col stalux-u-w-full stalux-u-min-w-0"
|
|
28
28
|
>
|
|
29
29
|
{post.data.cover && (
|
|
30
|
-
<a
|
|
31
|
-
href={`/posts/${post.data.abbrlink}/`}
|
|
32
|
-
class="a-none"
|
|
33
|
-
data-astro-prefetch="viewport"
|
|
34
|
-
aria-label={post.data.title}
|
|
35
|
-
>
|
|
30
|
+
<a href={`/posts/${post.data.abbrlink}`} class="a-none" aria-label={post.data.title}>
|
|
36
31
|
<span class="stalux-card-post-cover stalux-u-w-full stalux-u-min-w-0">
|
|
37
32
|
<img
|
|
38
33
|
src={post.data.cover}
|
|
@@ -48,7 +43,7 @@ const description = post.data.desc || "";
|
|
|
48
43
|
</a>
|
|
49
44
|
)}
|
|
50
45
|
<h2 class="stalux-card-post-title">
|
|
51
|
-
<a href={`/posts/${post.data.abbrlink}
|
|
46
|
+
<a href={`/posts/${post.data.abbrlink}`} class="a-none">
|
|
52
47
|
{post.data.title}
|
|
53
48
|
</a>
|
|
54
49
|
</h2>
|
|
@@ -77,7 +72,7 @@ const description = post.data.desc || "";
|
|
|
77
72
|
<ul class="stalux-card-post-tags stalux-u-flex stalux-u-items-center stalux-u-flex-wrap">
|
|
78
73
|
{post.data.tags?.map((tag) => (
|
|
79
74
|
<li>
|
|
80
|
-
<a class="a-none" href={`/tags/${tag}`}
|
|
75
|
+
<a class="a-none" href={`/tags/${tag}`}>
|
|
81
76
|
<span class="stalux-card-post-tag">{tag}</span>
|
|
82
77
|
</a>
|
|
83
78
|
</li>
|
|
@@ -88,18 +83,12 @@ const description = post.data.desc || "";
|
|
|
88
83
|
>
|
|
89
84
|
{post.data.categories?.map((category) => (
|
|
90
85
|
<li>
|
|
91
|
-
<a class="a-none" href={`/categories/${category}`}
|
|
86
|
+
<a class="a-none" href={`/categories/${category}`}>
|
|
92
87
|
<span class="stalux-card-post-category">{category}</span>
|
|
93
88
|
</a>
|
|
94
89
|
</li>
|
|
95
90
|
))}
|
|
96
91
|
</ul>
|
|
97
92
|
</footer>
|
|
98
|
-
<a
|
|
99
|
-
href={`/posts/${post.data.abbrlink}/`}
|
|
100
|
-
class="stalux-card-read-more a-none"
|
|
101
|
-
data-astro-prefetch
|
|
102
|
-
>
|
|
103
|
-
Read More
|
|
104
|
-
</a>
|
|
93
|
+
<a href={`/posts/${post.data.abbrlink}`} class="stalux-card-read-more a-none"> Read More </a>
|
|
105
94
|
</article>
|
|
@@ -14,8 +14,9 @@ interface Props {
|
|
|
14
14
|
title: string;
|
|
15
15
|
description?: string;
|
|
16
16
|
searchKeywords?: string[];
|
|
17
|
+
// Kept for downstream overrides of this component; the theme's own render
|
|
18
|
+
// path no longer turns them into any view-transition CSS (Swup owns cues).
|
|
17
19
|
transitionName?: string;
|
|
18
|
-
titleTransitionName?: string;
|
|
19
20
|
transitionScope?: "article" | "about";
|
|
20
21
|
date?: string;
|
|
21
22
|
updated?: string;
|
|
@@ -25,7 +26,6 @@ interface Props {
|
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
const props = Astro.props as Props;
|
|
28
|
-
const transitionPrefix = props.transitionScope === "about" ? "stalux-about" : "stalux-article";
|
|
29
29
|
const configEntries = await getCollection("config");
|
|
30
30
|
const siteConfig = getSiteData(configEntries);
|
|
31
31
|
const promoteConfig = getPromoteData(configEntries);
|
|
@@ -113,11 +113,7 @@ const mdSourceUrl = exportMd ? `${Astro.url.pathname.replace(/\/$/u, "")}.md` :
|
|
|
113
113
|
)}
|
|
114
114
|
</header>
|
|
115
115
|
|
|
116
|
-
<ArticleSummary
|
|
117
|
-
description={props.description}
|
|
118
|
-
label={t("post.summary")}
|
|
119
|
-
transitionName={`${transitionPrefix}-summary`}
|
|
120
|
-
/>
|
|
116
|
+
<ArticleSummary description={props.description} label={t("post.summary")} />
|
|
121
117
|
|
|
122
118
|
<span
|
|
123
119
|
hidden
|
|
@@ -34,7 +34,6 @@ const { t } = createTranslator((siteConfig.lang as string) || "zh-CN");
|
|
|
34
34
|
data-stalux-motion="previous"
|
|
35
35
|
class="stalux-pagination-link stalux-pagination-prev-post"
|
|
36
36
|
rel="prev"
|
|
37
|
-
data-astro-prefetch
|
|
38
37
|
>
|
|
39
38
|
<span class="stalux-pagination-arrow">
|
|
40
39
|
<svg
|
|
@@ -90,7 +89,6 @@ const { t } = createTranslator((siteConfig.lang as string) || "zh-CN");
|
|
|
90
89
|
data-stalux-motion="next"
|
|
91
90
|
class="stalux-pagination-link stalux-pagination-next-post"
|
|
92
91
|
rel="next"
|
|
93
|
-
data-astro-prefetch
|
|
94
92
|
>
|
|
95
93
|
<p class="stalux-pagination-content">
|
|
96
94
|
<span class="stalux-pagination-label">{t("post.nextPost")}</span>
|
|
@@ -21,9 +21,9 @@ const { t } = createTranslator(siteConfig.lang || "zh-CN");
|
|
|
21
21
|
const typeKey = props.typeKey || props.type;
|
|
22
22
|
let typeUrl = "";
|
|
23
23
|
if (typeKey === "category" || typeKey === "categories" || typeKey === "分类") {
|
|
24
|
-
typeUrl = "/categories
|
|
24
|
+
typeUrl = "/categories";
|
|
25
25
|
} else if (typeKey === "tag" || typeKey === "tags" || typeKey === "标签") {
|
|
26
|
-
typeUrl = "/tags
|
|
26
|
+
typeUrl = "/tags";
|
|
27
27
|
}
|
|
28
28
|
---
|
|
29
29
|
|
|
@@ -52,7 +52,7 @@ if (typeKey === "category" || typeKey === "categories" || typeKey === "分类")
|
|
|
52
52
|
<p class="stalux-tag-page-description">
|
|
53
53
|
{t("taxonomy.foundPosts", { count: props.count })}
|
|
54
54
|
</p>
|
|
55
|
-
<a href={typeUrl} class="stalux-tag-back-link"
|
|
55
|
+
<a href={typeUrl} class="stalux-tag-back-link"
|
|
56
56
|
>{t("taxonomy.backToList", { type: props.type })}</a
|
|
57
57
|
>
|
|
58
58
|
</header>
|
|
@@ -17,7 +17,7 @@ const cloudDensity = Math.sqrt(Math.max(tagList.length, 100) / 100);
|
|
|
17
17
|
const tagLinks = tagList.map((t) => ({
|
|
18
18
|
type: "link" as const,
|
|
19
19
|
text: t.name,
|
|
20
|
-
url: `/tags/${t.name}
|
|
20
|
+
url: `/tags/${t.name}`,
|
|
21
21
|
}));
|
|
22
22
|
---
|
|
23
23
|
|
|
@@ -36,13 +36,12 @@ const tagLinks = tagList.map((t) => ({
|
|
|
36
36
|
{group.map(({ name, count }) => (
|
|
37
37
|
<li data-stalux-reveal-item>
|
|
38
38
|
<a
|
|
39
|
-
href={`/tags/${name}
|
|
39
|
+
href={`/tags/${name}`}
|
|
40
40
|
class="stalux-cloud-tag-card"
|
|
41
41
|
data-stalux-card
|
|
42
42
|
data-stalux-tag-card
|
|
43
43
|
data-stalux-control="tag-card"
|
|
44
44
|
data-count={count}
|
|
45
|
-
data-astro-prefetch
|
|
46
45
|
>
|
|
47
46
|
<span class="stalux-cloud-tag-name">{name}</span>
|
|
48
47
|
<span class="stalux-cloud-tag-count">{count}</span>
|
package/src/index.ts
CHANGED
|
@@ -53,6 +53,7 @@ import { createPageOutputCache } from "./internal/page-output-cache";
|
|
|
53
53
|
import { loadCoverEncoder, restoreCoverFiles, upgradeCoverImages } from "./internal/post-cover";
|
|
54
54
|
import { isPluginProject } from "./internal/project-mode";
|
|
55
55
|
import { syncBackgroundSvgs, syncFontAssets } from "./internal/public-assets";
|
|
56
|
+
import { normalizeRouteHrefs } from "./internal/route-hrefs";
|
|
56
57
|
import { createRuntimeCacheKey } from "./internal/runtime-cache-key";
|
|
57
58
|
import {
|
|
58
59
|
appendUniquePlugin,
|
|
@@ -529,6 +530,8 @@ export function stalux(options: StaluxOptions = {}): AstroIntegration[] {
|
|
|
529
530
|
promoteCodeStyles(document);
|
|
530
531
|
containMermaidSvgs(document);
|
|
531
532
|
removePageFontStyles(document);
|
|
533
|
+
// 正文里手写的 /posts/x/ 也统一成路由器实际提供的形态
|
|
534
|
+
normalizeRouteHrefs(document);
|
|
532
535
|
const images = findHtmlImages(before, document);
|
|
533
536
|
await updateLocalImageDimensions(images, outDir, {
|
|
534
537
|
cache: dimensionsCache,
|
|
@@ -740,6 +743,16 @@ export function stalux(options: StaluxOptions = {}): AstroIntegration[] {
|
|
|
740
743
|
...userSitemap,
|
|
741
744
|
customPages,
|
|
742
745
|
filter,
|
|
746
|
+
// Page routes are served without a trailing slash; keep the root
|
|
747
|
+
// and real files (`.md`, `.json`, `.xml`, images) exactly as built.
|
|
748
|
+
async serialize(item) {
|
|
749
|
+
const next = userSitemap?.serialize ? await userSitemap.serialize(item) : item;
|
|
750
|
+
if (!next) return next;
|
|
751
|
+
const url = new URL(next.url);
|
|
752
|
+
if (url.pathname !== "/") url.pathname = url.pathname.replace(/\/+$/u, "");
|
|
753
|
+
next.url = url.href;
|
|
754
|
+
return next;
|
|
755
|
+
},
|
|
743
756
|
}),
|
|
744
757
|
{
|
|
745
758
|
name: "stalux/sitemap-alias",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type DefaultTreeAdapterMap, serialize, serializeOuter } from "parse5";
|
|
2
|
+
import { normalizeRouteHref } from "./route-hrefs";
|
|
2
3
|
|
|
3
4
|
type Element = DefaultTreeAdapterMap["element"];
|
|
4
5
|
|
|
@@ -17,6 +18,9 @@ export function createHtmlMutationEmitter(
|
|
|
17
18
|
attrs: Element["attrs"];
|
|
18
19
|
text: string[];
|
|
19
20
|
}> = [];
|
|
21
|
+
// Anchor hrefs are rewritten by value range only: reserializing the whole
|
|
22
|
+
// element would re-escape attribute text the emitter never touched.
|
|
23
|
+
const hrefSnapshots: Array<{ node: Element; start: number; end: number }> = [];
|
|
20
24
|
let head: Element | undefined;
|
|
21
25
|
function visit(node: DefaultTreeAdapterMap["node"]) {
|
|
22
26
|
if ("tagName" in node) {
|
|
@@ -37,6 +41,10 @@ export function createHtmlMutationEmitter(
|
|
|
37
41
|
attrs: node.attrs.map((attribute) => ({ ...attribute })),
|
|
38
42
|
text: node.childNodes.map((child) => ("value" in child ? child.value : "")),
|
|
39
43
|
});
|
|
44
|
+
} else if (node.tagName === "a") {
|
|
45
|
+
const href = location?.attrs?.href;
|
|
46
|
+
if (href)
|
|
47
|
+
hrefSnapshots.push({ node, start: href.startOffset, end: href.endOffset });
|
|
40
48
|
}
|
|
41
49
|
}
|
|
42
50
|
if ("childNodes" in node) for (const child of node.childNodes) visit(child);
|
|
@@ -45,6 +53,16 @@ export function createHtmlMutationEmitter(
|
|
|
45
53
|
|
|
46
54
|
return () => {
|
|
47
55
|
const edits: Array<{ start: number; end: number; value: string }> = [];
|
|
56
|
+
for (const { node, start, end } of hrefSnapshots) {
|
|
57
|
+
const current = node.attrs.find((attribute) => attribute.name === "href")?.value;
|
|
58
|
+
if (current === undefined) continue;
|
|
59
|
+
const raw = source.slice(start, end);
|
|
60
|
+
const parsed = /^(href\s*=\s*["'])([^"']*)(["'])$/u.exec(raw);
|
|
61
|
+
if (!parsed) continue;
|
|
62
|
+
const next = normalizeRouteHref(parsed[2] ?? "");
|
|
63
|
+
if (next === parsed[2]) continue;
|
|
64
|
+
edits.push({ start, end, value: `${parsed[1]}${next}${parsed[3]}` });
|
|
65
|
+
}
|
|
48
66
|
for (const snapshot of snapshots) {
|
|
49
67
|
const { node, start, end, attrs, text } = snapshot;
|
|
50
68
|
if (!node.parentNode) {
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { DefaultTreeAdapterMap } from "parse5";
|
|
2
|
+
|
|
3
|
+
type Document = DefaultTreeAdapterMap["document"];
|
|
4
|
+
|
|
5
|
+
/** Endpoints that are real files: the extension identifies them, never a slash. */
|
|
6
|
+
const REAL_FILE =
|
|
7
|
+
/\.(?:md|json|xml|txt|html?|pdf|png|webp|avif|svg|jpe?g|gif|ico|css|js|mjs|map|zip|mp4|webm|woff2?|ttf|otf)$/iu;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Rewrite a site-absolute href to the form the router actually serves.
|
|
11
|
+
*
|
|
12
|
+
* Page routes carry no trailing slash (`/posts/x`, `/archives`), while real
|
|
13
|
+
* files keep theirs (`/posts/x.md`, `/api/posts.json`). Only rooted paths are
|
|
14
|
+
* touched: relative links, protocol-relative URLs and anchors pass through.
|
|
15
|
+
*/
|
|
16
|
+
export function normalizeRouteHref(href: string): string {
|
|
17
|
+
if (!href.startsWith("/") || href.startsWith("//")) return href;
|
|
18
|
+
const match = /^([^?#]*)([?#].*)?$/u.exec(href);
|
|
19
|
+
const path = match?.[1] ?? href;
|
|
20
|
+
const suffix = match?.[2] ?? "";
|
|
21
|
+
if (path === "/" || !path.endsWith("/") || REAL_FILE.test(path)) return href;
|
|
22
|
+
return `${path.replace(/\/+$/u, "")}${suffix}`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Content-authored links still use the old trailing-slash form. Normalising the
|
|
27
|
+
* parsed document here keeps hand-written Markdown from reintroducing a URL
|
|
28
|
+
* shape the router no longer serves, without touching the author's source.
|
|
29
|
+
*/
|
|
30
|
+
export function normalizeRouteHrefs(document: Document): number {
|
|
31
|
+
let changed = 0;
|
|
32
|
+
const visit = (node: DefaultTreeAdapterMap["node"]): void => {
|
|
33
|
+
if ("tagName" in node && node.tagName === "a") {
|
|
34
|
+
for (const attribute of node.attrs) {
|
|
35
|
+
if (attribute.name !== "href") continue;
|
|
36
|
+
const next = normalizeRouteHref(attribute.value);
|
|
37
|
+
if (next !== attribute.value) {
|
|
38
|
+
attribute.value = next;
|
|
39
|
+
changed++;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if ("childNodes" in node) for (const child of node.childNodes) visit(child);
|
|
44
|
+
};
|
|
45
|
+
visit(document);
|
|
46
|
+
return changed;
|
|
47
|
+
}
|
|
@@ -22,7 +22,7 @@ export function createSocialCardData(
|
|
|
22
22
|
siteTitle: site.title,
|
|
23
23
|
author: author.name,
|
|
24
24
|
host: siteUrl.host,
|
|
25
|
-
postUrl: new URL(`/posts/${encodeURIComponent(post.abbrlink)}
|
|
25
|
+
postUrl: new URL(`/posts/${encodeURIComponent(post.abbrlink)}`, siteUrl).href,
|
|
26
26
|
tags: post.tags ?? [],
|
|
27
27
|
date: formatInTimeZone(
|
|
28
28
|
parseDate(post.date, site.timezone || "Asia/Shanghai"),
|
|
@@ -339,24 +339,9 @@ export const styleNames: { classes: Record<string, string>; variables: Record<st
|
|
|
339
339
|
},
|
|
340
340
|
"animations": {
|
|
341
341
|
"spin": "k0",
|
|
342
|
-
"stalux-
|
|
343
|
-
"stalux-
|
|
344
|
-
"stalux-
|
|
345
|
-
"stalux-
|
|
346
|
-
"stalux-page-enter": "k5",
|
|
347
|
-
"stalux-page-enter-back": "k6",
|
|
348
|
-
"stalux-page-exit": "k7",
|
|
349
|
-
"stalux-random-spin": "k8",
|
|
350
|
-
"stalux-sidebar-left-back-in": "k9",
|
|
351
|
-
"stalux-sidebar-left-back-out": "ka",
|
|
352
|
-
"stalux-sidebar-left-in": "kb",
|
|
353
|
-
"stalux-sidebar-left-out": "kc",
|
|
354
|
-
"stalux-sidebar-right-back-in": "kd",
|
|
355
|
-
"stalux-sidebar-right-back-out": "ke",
|
|
356
|
-
"stalux-sidebar-right-in": "kf",
|
|
357
|
-
"stalux-sidebar-right-out": "kg",
|
|
358
|
-
"stalux-social-stalux-social-arrive": "kh",
|
|
359
|
-
"stalux-taxonomy-enter": "ki",
|
|
360
|
-
"stalux-taxonomy-enter-back": "kj"
|
|
342
|
+
"stalux-cursor-blink": "k1",
|
|
343
|
+
"stalux-link-avatar-spin": "k2",
|
|
344
|
+
"stalux-random-spin": "k3",
|
|
345
|
+
"stalux-social-stalux-social-arrive": "k4"
|
|
361
346
|
}
|
|
362
347
|
};
|
|
@@ -8,7 +8,6 @@ import PostNavigation from "@components/stalux/posts/postNavigation.astro";
|
|
|
8
8
|
import PostRight from "@components/stalux/posts/postRight.astro";
|
|
9
9
|
import WalineComment from "@components/stalux/posts/WalineComment.astro";
|
|
10
10
|
import { getCommentData } from "@utils/config-utils";
|
|
11
|
-
import { getPostTitleTransitionName } from "@utils/view-transitions";
|
|
12
11
|
import { buildWalineProps } from "@utils/waline";
|
|
13
12
|
|
|
14
13
|
interface Props {
|
|
@@ -63,9 +62,6 @@ const walineConfig = walineSection?.serverURL
|
|
|
63
62
|
title={props.title}
|
|
64
63
|
description={props.description}
|
|
65
64
|
searchKeywords={[...tags, ...categories, ...(props.searchKeywords ?? [])]}
|
|
66
|
-
titleTransitionName={props.postId === undefined
|
|
67
|
-
? undefined
|
|
68
|
-
: getPostTitleTransitionName(props.postId)}
|
|
69
65
|
date={props.date}
|
|
70
66
|
updated={props.updated}
|
|
71
67
|
readingMinutes={props.readingMinutes}
|
package/src/pages/404.astro
CHANGED
|
@@ -25,7 +25,7 @@ const { t } = createTranslator(siteConfig.lang || "zh-CN");
|
|
|
25
25
|
<p data-stalux-motion-content>{t("page404.pageNotFound")}</p>
|
|
26
26
|
<p class="agent-recovery" data-stalux-motion-content>
|
|
27
27
|
This URL does not exist. Continue at the <a href="/">home page</a>, browse the
|
|
28
|
-
<a href="/archives
|
|
28
|
+
<a href="/archives">archive</a>, read <a href="/llms.txt">llms.txt</a>, or inspect
|
|
29
29
|
the
|
|
30
30
|
<a href="/sitemap-index.xml">sitemap</a>
|
|
31
31
|
to find published content.
|
|
@@ -42,7 +42,6 @@ const { t } = createTranslator(siteConfig.lang || "zh-CN");
|
|
|
42
42
|
href="/"
|
|
43
43
|
class="stalux-404-home-btn home-btn"
|
|
44
44
|
data-stalux-control="button"
|
|
45
|
-
data-astro-prefetch
|
|
46
45
|
data-stalux-motion-content
|
|
47
46
|
>{t("page404.backHome")}</a
|
|
48
47
|
>
|
package/src/pages/about.astro
CHANGED
|
@@ -29,7 +29,7 @@ export const GET: APIRoute = async ({ logger }) => {
|
|
|
29
29
|
categories: post.data.categories ?? [],
|
|
30
30
|
desc: post.data.desc ?? "",
|
|
31
31
|
wordCount: descriptions.get(String(post.data.abbrlink))?.wordCount ?? 0,
|
|
32
|
-
url: sitePath(`posts/${encodeURIComponent(String(post.data.abbrlink))}
|
|
32
|
+
url: sitePath(`posts/${encodeURIComponent(String(post.data.abbrlink))}`),
|
|
33
33
|
}));
|
|
34
34
|
|
|
35
35
|
return new Response(JSON.stringify(payload), {
|
package/src/pages/atom.xml.ts
CHANGED
|
@@ -19,6 +19,8 @@ export const GET: APIRoute = async ({ logger }) => {
|
|
|
19
19
|
title: stalux?.title || "Stalux Blog",
|
|
20
20
|
description: stalux?.description || "A blog powered by Stalux theme",
|
|
21
21
|
site: stalux.url,
|
|
22
|
+
// 页面路由不带尾斜杠,feed 里的条目链接要与之保持一致
|
|
23
|
+
trailingSlash: false,
|
|
22
24
|
items,
|
|
23
25
|
customData: `<language>${langToFeedLanguage(lang)}</language>\n<copyright>${t("rss.copyright")}</copyright>`,
|
|
24
26
|
xmlns: {
|
|
@@ -17,8 +17,8 @@ function generateCCFooter(post: CollectionEntry<"posts">, config: ConfigMap): st
|
|
|
17
17
|
const baseUrl = (siteConfig.url as string) || "";
|
|
18
18
|
const author = (config.get("author")?.name as string) || "";
|
|
19
19
|
const postUrl = baseUrl
|
|
20
|
-
? `${baseUrl}/posts/${post.data.abbrlink}
|
|
21
|
-
: `/posts/${post.data.abbrlink}
|
|
20
|
+
? `${baseUrl}/posts/${post.data.abbrlink}`
|
|
21
|
+
: `/posts/${post.data.abbrlink}`;
|
|
22
22
|
|
|
23
23
|
const lines: string[] = [];
|
|
24
24
|
lines.push(`**${t("post.author")}**${author}`);
|
package/src/pages/rss.xml.ts
CHANGED
|
@@ -19,6 +19,8 @@ export const GET: APIRoute = async ({ logger }) => {
|
|
|
19
19
|
title: stalux?.title || "Stalux Blog",
|
|
20
20
|
description: stalux?.description || "A blog powered by Stalux theme",
|
|
21
21
|
site: stalux.url,
|
|
22
|
+
// 页面路由不带尾斜杠,feed 里的条目链接要与之保持一致
|
|
23
|
+
trailingSlash: false,
|
|
22
24
|
items,
|
|
23
25
|
customData: `<language>${langToFeedLanguage(lang)}</language>\n<copyright>${t("rss.copyright")}</copyright>`,
|
|
24
26
|
xmlns: {
|
|
@@ -91,7 +91,13 @@ export function installSwupRouter(): Swup {
|
|
|
91
91
|
let activeContext: NavigationContext | undefined;
|
|
92
92
|
let visibleHistoryIndex = Number(window.history.state?.index ?? 1);
|
|
93
93
|
let browserMotion = false;
|
|
94
|
-
|
|
94
|
+
// Swup waits for the target document before it starts any animation, so a
|
|
95
|
+
// slow fetch is a window with no visual response at all. The official
|
|
96
|
+
// plugin waits 300ms before showing its bar, which leaves most of that
|
|
97
|
+
// window empty; 80ms keeps a cached/preloaded visit invisible (it finishes
|
|
98
|
+
// first) while a real network round trip gets an immediate, theme-coloured
|
|
99
|
+
// cue. The bar itself is compositor-only: a 3px transform on one element.
|
|
100
|
+
const progress = new SwupProgressPlugin({ delay: 80, transition: 200 });
|
|
95
101
|
const scroll = new SwupScrollPlugin({
|
|
96
102
|
doScrollingRightAway: false,
|
|
97
103
|
animateScroll: { betweenPages: false, samePageWithHash: true, samePage: true },
|
package/src/styles/generated.css
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
@layer theme, base, components, utilities;
|
|
2
|
-
@layer components{.stalux-ai-prompt{clip-path:inset(50%);white-space:pre-wrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.stalux-badge-group{border:none}.stalux-badge-group-arrow{font-size:.65rem;transition:transform .2s;display:inline-block}.stalux-badge-group-summary{user-select:none;cursor:pointer;color:var(--white-70p);gap:.4rem;padding:.2rem 0;font-size:.85rem;list-style-type:none;transition:color .2s}.stalux-beian-public-security-beian{color:#ffffffb3;gap:5px;font-size:.9rem;text-decoration:none;transition:color .3s;display:inline-flex}.stalux-card-time{gap:.45rem;margin:0;display:inline-flex}.stalux-copyright{color:var(--white-70p);gap:.3em;font-weight:500}.stalux-footer{backdrop-filter:blur(10px);color:var(--white-full);background-color:#0000001a;margin-top:auto;padding:1.5rem 0;font-size:.9rem}.stalux-footer-content{gap:.8rem;max-width:1200px;margin:0 auto;padding:0 1rem}.stalux-nav-list{transform:scale(var(--nav-scale,1));transform-origin:50%;box-sizing:border-box;gap:2rem;max-width:100%;transition:transform .22s cubic-bezier(.22,.72,.22,1);overflow:visible}.stalux-nav-overlay{pointer-events:none;z-index:999;opacity:0;background:#0009;height:100%;transition:opacity .3s;display:none;position:fixed;top:0;left:0}.stalux-nav-scroll-btn{background:var(--black-30p);backdrop-filter:blur(8px);box-shadow:var(--shadow-md);pointer-events:none;z-index:10;cursor:pointer;width:36px;height:36px;color:var(--white-full);opacity:0;border:none;border-radius:9999px;padding:0;transition:opacity .25s;display:none;position:absolute;top:50%;transform:translateY(-50%)}.stalux-nav-toggle{z-index:998;cursor:pointer;min-width:48px;min-height:48px;color:inherit;background:0 0;border:none;padding:.75rem;display:none}.stalux-stats-site-build-time{color:#fffc;margin:.5rem 0 0;font-size:.9rem}.stalux-stats-stats-separator{color:#ffffff80}.stalux-theme-info{color:var(--white-70p);gap:.3em;margin:0;font-size:.85rem}.stalux-nav-container{box-sizing:border-box;max-width:100%;position:relative;overflow:hidden}.stalux-beian-beian-info{gap:1rem;margin:0}.stalux-nav-item{text-shadow:var(--stalux-text-shadow);flex-shrink:0;margin-left:1em;margin-right:1em;font-size:1.3em}.stalux-page-description{color:var(--white-60p);margin-top:0;margin-bottom:1.5em;font-size:1.2em}.stalux-page-title{text-shadow:var(--stalux-text-shadow);margin-top:1.5em;font-size:2.5em}.stalux-badge,.stalux-badges-wrapper .stalux-badge{width:auto}.stalux-u-min-w-0{min-width:0}.stalux-u-w-full{width:100%}.stalux-u-flex{display:flex}.stalux-u-flex-col{flex-direction:column}.stalux-u-flex-wrap{flex-wrap:wrap}.stalux-u-items-center{align-items:center}.stalux-u-justify-center{justify-content:center}.stalux-badges,.stalux-badges-wrapper{gap:.5rem}.stalux-stats-site-stats{gap:.5rem;font-size:.9rem}.stalux-nav-text{white-space:nowrap;color:var(--white-full)}.stalux-badge-group-items{padding-top:.35rem}.stalux-u-text-center{text-align:center}.stalux-badge-group-hint{color:var(--white-70p);font-size:.7rem}.stalux-badge-group-title{color:var(--white-80p)}.stalux-weather-heading{font-size:inherit;font-weight:inherit;margin:0}nav{width:100%;min-width:0;max-width:100%}html{scroll-padding-top:var(--stalux-nav-offset,var(--stalux-site-header-height))}.stalux-site-header{z-index:990;width:100%;min-height:var(--stalux-site-header-min-height);isolation:isolate;justify-content:center;align-items:center;display:flex;position:sticky;top:0}.stalux-nav-scroll-btn[data-visible]{pointer-events:auto;opacity:1}.stalux-nav-scroll-btn[data-side=left]{left:4px}.stalux-nav-scroll-btn[data-side=right]{right:4px}.stalux-nav-scroll-btn svg{stroke:currentColor;stroke-width:2px;fill:none;width:20px;height:20px}.stalux-nav-link,.stalux-nav-link:visited{cursor:pointer;width:100%;color:inherit;min-height:44px;font:inherit;background:0 0;border:none;align-items:center;gap:.5rem;padding:.5rem .75rem;text-decoration:none;display:flex}.stalux-nav-link .nav-icon{stroke:var(--white-full)}.stalux-nav-toggle svg{width:32px;height:32px}.stalux-nav-overlay[data-state=show]{pointer-events:auto;opacity:1;display:block}#stalux-to-archive-archs{margin:2em 0 0}#stalux-date-date-time{text-shadow:var(--stalux-text-shadow);color:var(--white-full);flex-direction:column;align-items:center;margin:2em 0 0;display:flex}#stalux-date-date-time #stalux-date-date{min-height:1.25em;margin-bottom:.5em;font-size:2em;line-height:1.25}#stalux-date-date-time #stalux-date-time{font-variant-numeric:tabular-nums;min-height:1.25em;font-size:3em;line-height:1.25}.stalux-theme-info span,.stalux-copyright span{margin:0}.stalux-theme-info a{color:#fffc;margin:0 .2em;text-decoration:none;transition:color .3s}.stalux-beian-beian-info a{color:#ffffffb3;font-size:.9rem;text-decoration:none;transition:color .3s}.stalux-beian-public-security-beian img{width:15px;height:15px;display:inline-block}.stalux-badge-group-summary::-webkit-details-marker,.stalux-badge-group[open] .stalux-badge-group-hint[data-hint=collapsed],.stalux-badge-group:not([open]) .stalux-badge-group-hint[data-hint=expanded]{display:none}.stalux-badge-group[open] .stalux-badge-group-arrow{transform:rotate(90deg)}@media (hover:hover) and (pointer:fine){.stalux-nav-scroll-btn:hover{background:0 0}.stalux-nav-container:hover .stalux-nav-scroll-btn[data-visible]{opacity:1}.stalux-nav-link:hover .nav-icon,.stalux-nav-link:hover .stalux-nav-text{stroke:var(--stalux-accent-color);color:var(--stalux-accent-color)}.stalux-theme-info a:hover{color:#fff;text-decoration:none}.stalux-beian-beian-info a:hover,.stalux-beian-public-security-beian:hover{color:#ffffffe6;text-decoration:none}.stalux-badge-group-summary:hover{color:var(--white-70p)}}@media (width>=601px){.stalux-site-nav{isolation:isolate;border-radius:0 0 16px 16px;transition:background-color .18s}.stalux-site-nav[data-scrolled]{backdrop-filter:blur(20px)saturate(140%);box-shadow:0 1px 0 var(--white-10p), 0 8px 24px #0000001f;background:#181818c7}}@media (width<=1100px){.stalux-nav-list{gap:1rem}.stalux-nav-item{margin-left:.6em;margin-right:.6em;font-size:1em}}@media (width<=900px){.stalux-nav-item{margin-left:.25em;margin-right:.25em;font-size:.95em}.stalux-nav-list{gap:.5rem}}@media (width<=768px){.stalux-footer{padding:1.2rem 0;font-size:.8rem}.stalux-footer-content{gap:.6rem;padding:0 .8rem}.stalux-badges{gap:.3rem}.stalux-badge{width:auto}}@media (width<=600px){html{--stalux-site-header-min-height:4rem}.stalux-nav-toggle[data-state=open]{visibility:hidden;pointer-events:none}.stalux-nav-toggle[data-scrolled]{backdrop-filter:blur(20px)saturate(140%);box-shadow:0 1px 0 var(--white-10p), 0 8px 24px #0000001f;background:#181818c7;border-radius:12px}.stalux-nav-toggle{display:block;position:fixed;top:.75rem;left:.75rem}.stalux-nav-container{overflow:visible}nav{width:auto}.stalux-nav-list{pointer-events:none;z-index:1000;background:var(--black-20p);backdrop-filter:blur(20px);flex-direction:column;justify-content:flex-start;align-items:flex-start;gap:0;width:min(220px,100vw - 1rem);height:100vh;padding:.5rem 1rem 2rem;position:fixed;top:0;left:0;right:auto;overflow-y:auto;transform:translate(-100%)}.stalux-nav-list[data-state=open]{pointer-events:auto;transform:translate(0)}.stalux-nav-item{border-bottom:1px solid var(--white-10p);flex-shrink:0;width:100%;margin:0;font-size:.9em}.stalux-nav-text{display:inline}.stalux-nav-link{width:100%;min-height:44px;font-size:inherit;padding:.45rem .75rem}.stalux-nav-link .nav-icon{width:18px;height:18px}}@media (width<=480px){.stalux-footer{padding:1rem 0;font-size:.8rem}.stalux-footer-content{gap:.6rem;padding:0 .8rem}}.stalux-main,.stalux-post-page,.stalux-post-layout>*,.stalux-link-card-content,.stalux-word-list-item,.stalux-word-card{box-sizing:border-box;min-width:0;max-width:100%}.stalux-main{overflow-wrap:anywhere}.stalux-link-shell{min-width:0;max-width:100%;display:block}.stalux-link-card{box-sizing:border-box;width:100%;max-width:100%}.stalux-category-shell{width:100%;min-width:0}.stalux-author-figure>a{flex-shrink:0;display:inline-block}.stalux-author-figure img{display:block}.stalux-post-card-shell,.stalux-category-shell,.stalux-link-shell{position:relative}.stalux-post-card,.stalux-category-card,.stalux-link-card,.stalux-word-card{transition:transform .2s,background-color .2s,border-color .2s,box-shadow .2s}:is(.stalux-post-card-shell,.stalux-category-shell):focus-within>*,.stalux-link-shell:focus-visible>*{box-shadow:var(--card-box-shadow-hover)}:is(button,summary,[role=button]):focus-visible{outline:2px solid var(--stalux-accent-color);outline-offset:3px}@media (prefers-reduced-motion:reduce){.stalux-main *,.stalux-main :before,.stalux-main :after{transition-duration:0s!important;animation:none!important}.stalux-post-card,.stalux-category-card,.stalux-link-card,.stalux-link-card-content,.stalux-card-post-cover img,.stalux-category-icon,.stalux-author-figure img,.stalux-link-card-avatar img{transform:none!important}}@keyframes stalux-social-stalux-social-arrive{0%{opacity:0;transform:translateY(.75rem)rotate(-12deg)}to{opacity:1;transform:translateY(0)rotate(0)}}@keyframes stalux-random-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes stalux-link-avatar-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}}@layer utilities{.sr-only{clip:rect(0,0,0,0);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.visible{visibility:visible}.absolute{position:absolute}.static{position:static}.grid{display:grid}.block{display:block}.inline-block{display:inline-block}.hidden{display:none}.h-full{height:100%}.flex{display:flex}.flex-shrink{flex-shrink:1}.flex-wrap{flex-wrap:wrap}.transform{transform:translateX(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotateZ(var(--un-rotate-z)) skewX(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.b,.border{border-width:1px}.text-inherit{color:inherit}.no-underline{text-decoration:none}.outline{outline-style:solid}}@layer theme;@layer base{html,body{color:#fff;width:100%;height:100%;margin:0;& main{flex:1}scrollbar-color:var(--stalux-scrollbar-thumb) var(--stalux-scrollbar-track);scrollbar-width:auto;font-family:var(--font-body), "Noto Sans SC", "Noto Sans CJK SC", system-ui, -apple-system, sans-serif;text-rendering:optimizelegibility;line-height:1.25;display:block}body{height:auto;min-height:100%}html{scrollbar-gutter:stable;background-color:var(--stalux-bg-color,#202020)}html[data-clarity-id]{opacity:1!important}a{color:inherit;cursor:pointer;text-decoration-skip-ink:auto;background-color:#0000;text-decoration:none;transition:color .2s,text-shadow .2s;position:relative}.a-none{cursor:pointer;text-decoration-skip-ink:auto;background-color:#0000;color:inherit!important;text-decoration:none!important}.a-none:after{display:none!important}a:not(.a-none):not([data-stalux-card]):not(.stalux-nav-link):after{content:"";background:linear-gradient(90deg, var(--stalux-accent-color), var(--accent-50p));transform-origin:0;pointer-events:none;width:100%;height:1px;transition:transform .25s cubic-bezier(.25,.9,.2,1);position:absolute;bottom:-2px;left:0;transform:scaleX(0)}a:not(.a-none):not([data-stalux-card]):not(.stalux-nav-link):focus-visible:after,a:not(.a-none):not([data-stalux-card]):not(.stalux-nav-link):active:after{transform:scaleX(1)}@media (hover:hover) and (pointer:fine){a:not(.a-none):not([data-stalux-card]):not(.stalux-nav-link):hover:after{transform:scaleX(1)}}a:active,a:focus-visible{text-decoration:none}@media (hover:hover) and (pointer:fine){a:hover{text-decoration:none}}a:focus{outline:none}a:focus-visible{outline:2px solid var(--stalux-accent-color);outline-offset:2px}ul{margin:0;padding:0;list-style:none}.none{display:none}.stalux-root{color:#fff;min-height:100vh}.stalux-main{min-height:calc(100vh - var(--stalux-site-header-height,3rem))}:root{--stalux-bg-color:#202020;--stalux-bg-filter:none;--stalux-scrollbar-thumb:#7d7d7d;--stalux-scrollbar-thumb-hover:#9a9a9a;--stalux-scrollbar-track:#2a2a2a;--stalux-site-header-min-height:3.75rem;--stalux-site-header-height:var(--stalux-site-header-min-height);--stalux-text-shadow:var(--stalux-accent-color) .08rem .08rem .18rem;--stalux-accent-color:#eab308;--stalux-accent-rgb:234 179 8;--surface-glass:var(--black-05p);--surface-glass-shadow:var(--shadow-sidebar);--card-bg:var(--surface-glass);--card-border:#ffffff1a;--card-box-shadow:0 10px 24px #00000014;--card-box-shadow-hover:0 14px 28px #0000001f;--tag-bg:#ffffff1f;--tag-bg-hover:#ffffff2e;--category-bg:#ffffff14;--category-bg-hover:#ffffff24;--date-bg:#42a0ff2e;--date-border:#42a0ff40;--updated-bg:#ffc94733;--updated-border:#ffc9474d;--white-full:#fff;--white-95p:#fffffff2;--white-90p:#ffffffe6;--white-85p:#ffffffd9;--white-80p:#ffffffe6;--white-78p:#ffffffc7;--white-75p:#ffffffbf;--white-70p:#ffffffdb;--white-60p:#fff9;--white-50p:#ffffff80;--white-30p:#ffffff4d;--white-20p:#fff3;--white-15p:#ffffff26;--white-10p:#ffffff1a;--white-05p:#ffffff0d;--black-30p:#0000004d;--black-20p:#0003;--black-15p:#00000026;--black-10p:#0000001a;--black-05p:#0000000d;--accent-90p:rgb(var(--stalux-accent-rgb) / .9);--accent-85p:rgb(var(--stalux-accent-rgb) / .85);--accent-80p:rgb(var(--stalux-accent-rgb) / .8);--accent-70p:rgb(var(--stalux-accent-rgb) / .7);--accent-60p:rgb(var(--stalux-accent-rgb) / .6);--accent-50p:rgb(var(--stalux-accent-rgb) / .5);--accent-40p:rgb(var(--stalux-accent-rgb) / .4);--accent-30p:rgb(var(--stalux-accent-rgb) / .3);--accent-20p:rgb(var(--stalux-accent-rgb) / .2);--transition-fast:.18s ease;--transition-medium:.2s ease;--transition-normal:.25s ease;--transition-slow:.3s ease;--transition-slower:.5s ease;--transition-slowest:.6s ease;--easing-bounce:cubic-bezier(.175, .885, .32, 1.275);--space-2xs:.25rem;--space-xs:.75rem;--space-sm:.5rem;--space-md:1rem;--space-lg:1.5rem;--space-xl:2rem;--space-2xl:3rem;--space-3xl:4rem;--radius-sm:4px;--radius-md:6px;--radius-lg:8px;--radius-full:9999px;--shadow-sm:0 2px 5px #0000001a;--shadow-md:0 6px 16px #0003;--shadow-lg:0 8px 20px #0000004d;--shadow-xl:0 12px 26px #00000047;--shadow-sidebar:0 16px 20px -12px #000000d6, 10px 4px 16px -12px #00000094, -10px 4px 16px -12px #00000094;--shadow-raised-hover:0 20px 24px -13px #000000e6, 12px 5px 18px -13px #000000ad, -12px 5px 18px -13px #000000ad;--shadow-dark:#000000c0;--muted-text:#bbb;--font-body:"Noto Sans SC", "Noto Sans CJK SC", system-ui, sans-serif;--font-size-subtitle:1.35rem;--font-size-base:1.1rem;--font-size-small:.95rem;--font-size-smaller:.9rem;--font-size-tiny:.85rem;--border-thin:1px;--border-medium:2px;--border-thick:3px}@supports not (scrollbar-color:auto){::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:var(--stalux-scrollbar-track);border-radius:4px}::-webkit-scrollbar-thumb{background:var(--stalux-scrollbar-thumb);border-radius:4px;transition:background .3s ease-out}@media (hover:hover) and (pointer:fine){::-webkit-scrollbar-thumb:hover{background:var(--stalux-scrollbar-thumb-hover)}}::-webkit-scrollbar-corner{background:var(--stalux-scrollbar-track)}}.bg-layer{z-index:-10;background-position:50%;background-repeat:repeat;background-size:auto;background-color:var(--stalux-bg-color,transparent);filter:var(--stalux-bg-filter,none);pointer-events:none;opacity:0;forced-color-adjust:none;color-scheme:light only;transition:opacity .2s ease-out;position:fixed;inset:0}@media (prefers-reduced-motion:reduce){.bg-layer{transition-duration:0s}}footer{padding:var(--space-lg) var(--space-md);text-align:center;color:var(--muted-text);border-top:1px solid var(--white-10p);backdrop-filter:blur(16px);background:linear-gradient(#0c0e122e,#0c0e12b8)}}@media print{[data-stalux-offscreen-code],[data-stalux-offscreen-svg]{content-visibility:visible!important;contain-intrinsic-block-size:none!important}}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}[data-stalux-home-content]{flex-direction:column;align-items:center;width:100%;display:flex}@keyframes stalux-page-exit{0%{opacity:1}to{opacity:1}}@keyframes stalux-page-enter{0%{opacity:.9}to{opacity:1}}@keyframes stalux-page-enter-back{0%{opacity:.96}to{opacity:1}}@keyframes stalux-taxonomy-enter{0%{opacity:.9}to{opacity:1}}@keyframes stalux-taxonomy-enter-back{0%{opacity:.96}to{opacity:1}}@keyframes stalux-article-enter{0%{opacity:.9}to{opacity:1}}@keyframes stalux-article-enter-back{0%{opacity:.96}to{opacity:1}}@keyframes stalux-sidebar-left-in{0%{opacity:.96}to{opacity:1}}@keyframes stalux-sidebar-left-out{0%{opacity:1}to{opacity:1}}@keyframes stalux-sidebar-left-back-in{0%{opacity:.96}to{opacity:1}}@keyframes stalux-sidebar-left-back-out{0%{opacity:1}to{opacity:1}}@keyframes stalux-sidebar-right-in{0%{opacity:.96}to{opacity:1}}@keyframes stalux-sidebar-right-out{0%{opacity:1}to{opacity:1}}@keyframes stalux-sidebar-right-back-in{0%{opacity:.96}to{opacity:1}}@keyframes stalux-sidebar-right-back-out{0%{opacity:1}to{opacity:1}}[data-stalux-scroll-sentinel]{visibility:hidden;pointer-events:none;width:1px;height:1px;position:absolute;top:240px;left:0}@media (prefers-reduced-motion:reduce){.stalux-main,.stalux-main *,.postLayout *{scroll-behavior:auto!important;transition-duration:1ms!important;animation-duration:1ms!important;animation-iteration-count:1!important}}
|
|
2
|
+
@layer components{.stalux-ai-prompt{clip-path:inset(50%);white-space:pre-wrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.stalux-badge-group{border:none}.stalux-badge-group-arrow{font-size:.65rem;transition:transform .2s;display:inline-block}.stalux-badge-group-summary{user-select:none;cursor:pointer;color:var(--white-70p);gap:.4rem;padding:.2rem 0;font-size:.85rem;list-style-type:none;transition:color .2s}.stalux-beian-public-security-beian{color:#ffffffb3;gap:5px;font-size:.9rem;text-decoration:none;transition:color .3s;display:inline-flex}.stalux-card-time{gap:.45rem;margin:0;display:inline-flex}.stalux-copyright{color:var(--white-70p);gap:.3em;font-weight:500}.stalux-footer{backdrop-filter:blur(10px);color:var(--white-full);background-color:#0000001a;margin-top:auto;padding:1.5rem 0;font-size:.9rem}.stalux-footer-content{gap:.8rem;max-width:1200px;margin:0 auto;padding:0 1rem}.stalux-nav-list{transform:scale(var(--nav-scale,1));transform-origin:50%;box-sizing:border-box;gap:2rem;max-width:100%;transition:transform .22s cubic-bezier(.22,.72,.22,1);overflow:visible}.stalux-nav-overlay{pointer-events:none;z-index:999;opacity:0;background:#0009;height:100%;transition:opacity .3s;display:none;position:fixed;top:0;left:0}.stalux-nav-scroll-btn{background:var(--black-30p);backdrop-filter:blur(8px);box-shadow:var(--shadow-md);pointer-events:none;z-index:10;cursor:pointer;width:36px;height:36px;color:var(--white-full);opacity:0;border:none;border-radius:9999px;padding:0;transition:opacity .25s;display:none;position:absolute;top:50%;transform:translateY(-50%)}.stalux-nav-toggle{z-index:998;cursor:pointer;min-width:48px;min-height:48px;color:inherit;background:0 0;border:none;padding:.75rem;display:none}.stalux-stats-site-build-time{color:#fffc;margin:.5rem 0 0;font-size:.9rem}.stalux-stats-stats-separator{color:#ffffff80}.stalux-theme-info{color:var(--white-70p);gap:.3em;margin:0;font-size:.85rem}.stalux-nav-container{box-sizing:border-box;max-width:100%;position:relative;overflow:hidden}.stalux-beian-beian-info{gap:1rem;margin:0}.stalux-nav-item{text-shadow:var(--stalux-text-shadow);flex-shrink:0;margin-left:1em;margin-right:1em;font-size:1.3em}.stalux-page-description{color:var(--white-60p);margin-top:0;margin-bottom:1.5em;font-size:1.2em}.stalux-page-title{text-shadow:var(--stalux-text-shadow);margin-top:1.5em;font-size:2.5em}.stalux-badge,.stalux-badges-wrapper .stalux-badge{width:auto}.stalux-u-min-w-0{min-width:0}.stalux-u-w-full{width:100%}.stalux-u-flex{display:flex}.stalux-u-flex-col{flex-direction:column}.stalux-u-flex-wrap{flex-wrap:wrap}.stalux-u-items-center{align-items:center}.stalux-u-justify-center{justify-content:center}.stalux-badges,.stalux-badges-wrapper{gap:.5rem}.stalux-stats-site-stats{gap:.5rem;font-size:.9rem}.stalux-nav-text{white-space:nowrap;color:var(--white-full)}.stalux-badge-group-items{padding-top:.35rem}.stalux-u-text-center{text-align:center}.stalux-badge-group-hint{color:var(--white-70p);font-size:.7rem}.stalux-badge-group-title{color:var(--white-80p)}.stalux-weather-heading{font-size:inherit;font-weight:inherit;margin:0}nav{width:100%;min-width:0;max-width:100%}html{scroll-padding-top:var(--stalux-nav-offset,var(--stalux-site-header-height))}.stalux-site-header{z-index:990;width:100%;min-height:var(--stalux-site-header-min-height);isolation:isolate;justify-content:center;align-items:center;display:flex;position:sticky;top:0}.stalux-nav-scroll-btn[data-visible]{pointer-events:auto;opacity:1}.stalux-nav-scroll-btn[data-side=left]{left:4px}.stalux-nav-scroll-btn[data-side=right]{right:4px}.stalux-nav-scroll-btn svg{stroke:currentColor;stroke-width:2px;fill:none;width:20px;height:20px}.stalux-nav-link,.stalux-nav-link:visited{cursor:pointer;width:100%;color:inherit;min-height:44px;font:inherit;background:0 0;border:none;align-items:center;gap:.5rem;padding:.5rem .75rem;text-decoration:none;display:flex}.stalux-nav-link .nav-icon{stroke:var(--white-full)}.stalux-nav-toggle svg{width:32px;height:32px}.stalux-nav-overlay[data-state=show]{pointer-events:auto;opacity:1;display:block}#stalux-to-archive-archs{margin:2em 0 0}#stalux-date-date-time{text-shadow:var(--stalux-text-shadow);color:var(--white-full);flex-direction:column;align-items:center;margin:2em 0 0;display:flex}#stalux-date-date-time #stalux-date-date{min-height:1.25em;margin-bottom:.5em;font-size:2em;line-height:1.25}#stalux-date-date-time #stalux-date-time{font-variant-numeric:tabular-nums;min-height:1.25em;font-size:3em;line-height:1.25}.stalux-theme-info span,.stalux-copyright span{margin:0}.stalux-theme-info a{color:#fffc;margin:0 .2em;text-decoration:none;transition:color .3s}.stalux-beian-beian-info a{color:#ffffffb3;font-size:.9rem;text-decoration:none;transition:color .3s}.stalux-beian-public-security-beian img{width:15px;height:15px;display:inline-block}.stalux-badge-group-summary::-webkit-details-marker,.stalux-badge-group[open] .stalux-badge-group-hint[data-hint=collapsed],.stalux-badge-group:not([open]) .stalux-badge-group-hint[data-hint=expanded]{display:none}.stalux-badge-group[open] .stalux-badge-group-arrow{transform:rotate(90deg)}@media (hover:hover) and (pointer:fine){.stalux-nav-scroll-btn:hover{background:0 0}.stalux-nav-container:hover .stalux-nav-scroll-btn[data-visible]{opacity:1}.stalux-nav-link:hover .nav-icon,.stalux-nav-link:hover .stalux-nav-text{stroke:var(--stalux-accent-color);color:var(--stalux-accent-color)}.stalux-theme-info a:hover{color:#fff;text-decoration:none}.stalux-beian-beian-info a:hover,.stalux-beian-public-security-beian:hover{color:#ffffffe6;text-decoration:none}.stalux-badge-group-summary:hover{color:var(--white-70p)}}@media (width>=601px){.stalux-site-nav{isolation:isolate;border-radius:0 0 16px 16px;transition:background-color .18s}.stalux-site-nav[data-scrolled]{backdrop-filter:blur(20px)saturate(140%);box-shadow:0 1px 0 var(--white-10p), 0 8px 24px #0000001f;background:#181818c7}}@media (width<=1100px){.stalux-nav-list{gap:1rem}.stalux-nav-item{margin-left:.6em;margin-right:.6em;font-size:1em}}@media (width<=900px){.stalux-nav-item{margin-left:.25em;margin-right:.25em;font-size:.95em}.stalux-nav-list{gap:.5rem}}@media (width<=768px){.stalux-footer{padding:1.2rem 0;font-size:.8rem}.stalux-footer-content{gap:.6rem;padding:0 .8rem}.stalux-badges{gap:.3rem}.stalux-badge{width:auto}}@media (width<=600px){html{--stalux-site-header-min-height:4rem}.stalux-nav-toggle[data-state=open]{visibility:hidden;pointer-events:none}.stalux-nav-toggle[data-scrolled]{backdrop-filter:blur(20px)saturate(140%);box-shadow:0 1px 0 var(--white-10p), 0 8px 24px #0000001f;background:#181818c7;border-radius:12px}.stalux-nav-toggle{display:block;position:fixed;top:.75rem;left:.75rem}.stalux-nav-container{overflow:visible}nav{width:auto}.stalux-nav-list{pointer-events:none;z-index:1000;background:var(--black-20p);backdrop-filter:blur(20px);flex-direction:column;justify-content:flex-start;align-items:flex-start;gap:0;width:min(220px,100vw - 1rem);height:100vh;padding:.5rem 1rem 2rem;position:fixed;top:0;left:0;right:auto;overflow-y:auto;transform:translate(-100%)}.stalux-nav-list[data-state=open]{pointer-events:auto;transform:translate(0)}.stalux-nav-item{border-bottom:1px solid var(--white-10p);flex-shrink:0;width:100%;margin:0;font-size:.9em}.stalux-nav-text{display:inline}.stalux-nav-link{width:100%;min-height:44px;font-size:inherit;padding:.45rem .75rem}.stalux-nav-link .nav-icon{width:18px;height:18px}}@media (width<=480px){.stalux-footer{padding:1rem 0;font-size:.8rem}.stalux-footer-content{gap:.6rem;padding:0 .8rem}}.stalux-main,.stalux-post-page,.stalux-post-layout>*,.stalux-link-card-content,.stalux-word-list-item,.stalux-word-card{box-sizing:border-box;min-width:0;max-width:100%}.stalux-main{overflow-wrap:anywhere}.stalux-link-shell{min-width:0;max-width:100%;display:block}.stalux-link-card{box-sizing:border-box;width:100%;max-width:100%}.stalux-category-shell{width:100%;min-width:0}.stalux-author-figure>a{flex-shrink:0;display:inline-block}.stalux-author-figure img{display:block}.stalux-post-card-shell,.stalux-category-shell,.stalux-link-shell{position:relative}.stalux-post-card,.stalux-category-card,.stalux-link-card,.stalux-word-card{transition:transform .2s,background-color .2s,border-color .2s,box-shadow .2s}:is(.stalux-post-card-shell,.stalux-category-shell):focus-within>*,.stalux-link-shell:focus-visible>*{box-shadow:var(--card-box-shadow-hover)}:is(button,summary,[role=button]):focus-visible{outline:2px solid var(--stalux-accent-color);outline-offset:3px}@media (prefers-reduced-motion:reduce){.stalux-main *,.stalux-main :before,.stalux-main :after{transition-duration:0s!important;animation:none!important}.stalux-post-card,.stalux-category-card,.stalux-link-card,.stalux-link-card-content,.stalux-card-post-cover img,.stalux-category-icon,.stalux-author-figure img,.stalux-link-card-avatar img{transform:none!important}}@keyframes stalux-social-stalux-social-arrive{0%{opacity:0;transform:translateY(.75rem)rotate(-12deg)}to{opacity:1;transform:translateY(0)rotate(0)}}@keyframes stalux-random-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes stalux-link-avatar-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}}@layer utilities{.sr-only{clip:rect(0,0,0,0);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.visible{visibility:visible}.absolute{position:absolute}.static{position:static}.grid{display:grid}.block{display:block}.inline-block{display:inline-block}.hidden{display:none}.h-full{height:100%}.flex{display:flex}.flex-shrink{flex-shrink:1}.flex-wrap{flex-wrap:wrap}.transform{transform:translateX(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotateZ(var(--un-rotate-z)) skewX(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.b,.border{border-width:1px}.text-inherit{color:inherit}.no-underline{text-decoration:none}.outline{outline-style:solid}}@layer theme;@layer base{html,body{color:#fff;width:100%;height:100%;margin:0;& main{flex:1}scrollbar-color:var(--stalux-scrollbar-thumb) var(--stalux-scrollbar-track);scrollbar-width:auto;font-family:var(--font-body), "Noto Sans SC", "Noto Sans CJK SC", system-ui, -apple-system, sans-serif;text-rendering:optimizelegibility;line-height:1.25;display:block}body{height:auto;min-height:100%}html{scrollbar-gutter:stable;background-color:var(--stalux-bg-color,#202020)}html[data-clarity-id]{opacity:1!important}a{color:inherit;cursor:pointer;text-decoration-skip-ink:auto;background-color:#0000;text-decoration:none;transition:color .2s,text-shadow .2s;position:relative}.a-none{cursor:pointer;text-decoration-skip-ink:auto;background-color:#0000;color:inherit!important;text-decoration:none!important}.a-none:after{display:none!important}a:not(.a-none):not([data-stalux-card]):not(.stalux-nav-link):after{content:"";background:linear-gradient(90deg, var(--stalux-accent-color), var(--accent-50p));transform-origin:0;pointer-events:none;width:100%;height:1px;transition:transform .25s cubic-bezier(.25,.9,.2,1);position:absolute;bottom:-2px;left:0;transform:scaleX(0)}a:not(.a-none):not([data-stalux-card]):not(.stalux-nav-link):focus-visible:after,a:not(.a-none):not([data-stalux-card]):not(.stalux-nav-link):active:after{transform:scaleX(1)}@media (hover:hover) and (pointer:fine){a:not(.a-none):not([data-stalux-card]):not(.stalux-nav-link):hover:after{transform:scaleX(1)}}a:active,a:focus-visible{text-decoration:none}@media (hover:hover) and (pointer:fine){a:hover{text-decoration:none}}a:focus{outline:none}a:focus-visible{outline:2px solid var(--stalux-accent-color);outline-offset:2px}ul{margin:0;padding:0;list-style:none}.none{display:none}.stalux-root{color:#fff;min-height:100vh}.stalux-main{min-height:calc(100vh - var(--stalux-site-header-height,3rem))}:root{--stalux-bg-color:#202020;--stalux-bg-filter:none;--stalux-scrollbar-thumb:#7d7d7d;--stalux-scrollbar-thumb-hover:#9a9a9a;--stalux-scrollbar-track:#2a2a2a;--stalux-site-header-min-height:3.75rem;--stalux-site-header-height:var(--stalux-site-header-min-height);--stalux-text-shadow:var(--stalux-accent-color) .08rem .08rem .18rem;--stalux-accent-color:#eab308;--stalux-accent-rgb:234 179 8;--surface-glass:var(--black-05p);--surface-glass-shadow:var(--shadow-sidebar);--card-bg:var(--surface-glass);--card-border:#ffffff1a;--card-box-shadow:0 10px 24px #00000014;--card-box-shadow-hover:0 14px 28px #0000001f;--tag-bg:#ffffff1f;--tag-bg-hover:#ffffff2e;--category-bg:#ffffff14;--category-bg-hover:#ffffff24;--date-bg:#42a0ff2e;--date-border:#42a0ff40;--updated-bg:#ffc94733;--updated-border:#ffc9474d;--white-full:#fff;--white-95p:#fffffff2;--white-90p:#ffffffe6;--white-85p:#ffffffd9;--white-80p:#ffffffe6;--white-78p:#ffffffc7;--white-75p:#ffffffbf;--white-70p:#ffffffdb;--white-60p:#fff9;--white-50p:#ffffff80;--white-30p:#ffffff4d;--white-20p:#fff3;--white-15p:#ffffff26;--white-10p:#ffffff1a;--white-05p:#ffffff0d;--black-30p:#0000004d;--black-20p:#0003;--black-15p:#00000026;--black-10p:#0000001a;--black-05p:#0000000d;--accent-90p:rgb(var(--stalux-accent-rgb) / .9);--accent-85p:rgb(var(--stalux-accent-rgb) / .85);--accent-80p:rgb(var(--stalux-accent-rgb) / .8);--accent-70p:rgb(var(--stalux-accent-rgb) / .7);--accent-60p:rgb(var(--stalux-accent-rgb) / .6);--accent-50p:rgb(var(--stalux-accent-rgb) / .5);--accent-40p:rgb(var(--stalux-accent-rgb) / .4);--accent-30p:rgb(var(--stalux-accent-rgb) / .3);--accent-20p:rgb(var(--stalux-accent-rgb) / .2);--transition-fast:.18s ease;--transition-medium:.2s ease;--transition-normal:.25s ease;--transition-slow:.3s ease;--transition-slower:.5s ease;--transition-slowest:.6s ease;--easing-bounce:cubic-bezier(.175, .885, .32, 1.275);--space-2xs:.25rem;--space-xs:.75rem;--space-sm:.5rem;--space-md:1rem;--space-lg:1.5rem;--space-xl:2rem;--space-2xl:3rem;--space-3xl:4rem;--radius-sm:4px;--radius-md:6px;--radius-lg:8px;--radius-full:9999px;--shadow-sm:0 2px 5px #0000001a;--shadow-md:0 6px 16px #0003;--shadow-lg:0 8px 20px #0000004d;--shadow-xl:0 12px 26px #00000047;--shadow-sidebar:0 16px 20px -12px #000000d6, 10px 4px 16px -12px #00000094, -10px 4px 16px -12px #00000094;--shadow-raised-hover:0 20px 24px -13px #000000e6, 12px 5px 18px -13px #000000ad, -12px 5px 18px -13px #000000ad;--shadow-dark:#000000c0;--muted-text:#bbb;--font-body:"Noto Sans SC", "Noto Sans CJK SC", system-ui, sans-serif;--font-size-subtitle:1.35rem;--font-size-base:1.1rem;--font-size-small:.95rem;--font-size-smaller:.9rem;--font-size-tiny:.85rem;--border-thin:1px;--border-medium:2px;--border-thick:3px}@supports not (scrollbar-color:auto){::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:var(--stalux-scrollbar-track);border-radius:4px}::-webkit-scrollbar-thumb{background:var(--stalux-scrollbar-thumb);border-radius:4px;transition:background .3s ease-out}@media (hover:hover) and (pointer:fine){::-webkit-scrollbar-thumb:hover{background:var(--stalux-scrollbar-thumb-hover)}}::-webkit-scrollbar-corner{background:var(--stalux-scrollbar-track)}}.bg-layer{z-index:-10;background-position:50%;background-repeat:repeat;background-size:auto;background-color:var(--stalux-bg-color,transparent);filter:var(--stalux-bg-filter,none);pointer-events:none;opacity:0;forced-color-adjust:none;color-scheme:light only;transition:opacity .2s ease-out;position:fixed;inset:0}@media (prefers-reduced-motion:reduce){.bg-layer{transition-duration:0s}}footer{padding:var(--space-lg) var(--space-md);text-align:center;color:var(--muted-text);border-top:1px solid var(--white-10p);backdrop-filter:blur(16px);background:linear-gradient(#0c0e122e,#0c0e12b8)}}@media print{[data-stalux-offscreen-code],[data-stalux-offscreen-svg]{content-visibility:visible!important;contain-intrinsic-block-size:none!important}}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}[data-stalux-home-content]{flex-direction:column;align-items:center;width:100%;display:flex}[data-stalux-scroll-sentinel]{visibility:hidden;pointer-events:none;width:1px;height:1px;position:absolute;top:240px;left:0}@media (prefers-reduced-motion:reduce){.stalux-main,.stalux-main *,.postLayout *{scroll-behavior:auto!important;transition-duration:1ms!important;animation-duration:1ms!important;animation-iteration-count:1!important}}
|
|
3
3
|
/*$vite$:1*/
|
package/src/styles/motion.css
CHANGED
|
@@ -16,129 +16,6 @@
|
|
|
16
16
|
width: 100%;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
/* Public transition helpers retain their names as opacity-only compatibility
|
|
20
|
-
frames. Theme layouts no longer use them to move large content/sidebars. */
|
|
21
|
-
@keyframes stalux-page-exit {
|
|
22
|
-
from {
|
|
23
|
-
opacity: 1;
|
|
24
|
-
}
|
|
25
|
-
to {
|
|
26
|
-
opacity: 1;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
@keyframes stalux-page-enter {
|
|
30
|
-
from {
|
|
31
|
-
opacity: 0.9;
|
|
32
|
-
}
|
|
33
|
-
to {
|
|
34
|
-
opacity: 1;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
@keyframes stalux-page-enter-back {
|
|
38
|
-
from {
|
|
39
|
-
opacity: 0.96;
|
|
40
|
-
}
|
|
41
|
-
to {
|
|
42
|
-
opacity: 1;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
@keyframes stalux-taxonomy-enter {
|
|
46
|
-
from {
|
|
47
|
-
opacity: 0.9;
|
|
48
|
-
}
|
|
49
|
-
to {
|
|
50
|
-
opacity: 1;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
@keyframes stalux-taxonomy-enter-back {
|
|
54
|
-
from {
|
|
55
|
-
opacity: 0.96;
|
|
56
|
-
}
|
|
57
|
-
to {
|
|
58
|
-
opacity: 1;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
@keyframes stalux-article-enter {
|
|
62
|
-
from {
|
|
63
|
-
opacity: 0.9;
|
|
64
|
-
}
|
|
65
|
-
to {
|
|
66
|
-
opacity: 1;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
@keyframes stalux-article-enter-back {
|
|
70
|
-
from {
|
|
71
|
-
opacity: 0.96;
|
|
72
|
-
}
|
|
73
|
-
to {
|
|
74
|
-
opacity: 1;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
@keyframes stalux-sidebar-left-in {
|
|
78
|
-
from {
|
|
79
|
-
opacity: 0.96;
|
|
80
|
-
}
|
|
81
|
-
to {
|
|
82
|
-
opacity: 1;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
@keyframes stalux-sidebar-left-out {
|
|
86
|
-
from {
|
|
87
|
-
opacity: 1;
|
|
88
|
-
}
|
|
89
|
-
to {
|
|
90
|
-
opacity: 1;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
@keyframes stalux-sidebar-left-back-in {
|
|
94
|
-
from {
|
|
95
|
-
opacity: 0.96;
|
|
96
|
-
}
|
|
97
|
-
to {
|
|
98
|
-
opacity: 1;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
@keyframes stalux-sidebar-left-back-out {
|
|
102
|
-
from {
|
|
103
|
-
opacity: 1;
|
|
104
|
-
}
|
|
105
|
-
to {
|
|
106
|
-
opacity: 1;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
@keyframes stalux-sidebar-right-in {
|
|
110
|
-
from {
|
|
111
|
-
opacity: 0.96;
|
|
112
|
-
}
|
|
113
|
-
to {
|
|
114
|
-
opacity: 1;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
@keyframes stalux-sidebar-right-out {
|
|
118
|
-
from {
|
|
119
|
-
opacity: 1;
|
|
120
|
-
}
|
|
121
|
-
to {
|
|
122
|
-
opacity: 1;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
@keyframes stalux-sidebar-right-back-in {
|
|
126
|
-
from {
|
|
127
|
-
opacity: 0.96;
|
|
128
|
-
}
|
|
129
|
-
to {
|
|
130
|
-
opacity: 1;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
@keyframes stalux-sidebar-right-back-out {
|
|
134
|
-
from {
|
|
135
|
-
opacity: 1;
|
|
136
|
-
}
|
|
137
|
-
to {
|
|
138
|
-
opacity: 1;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
19
|
[data-stalux-scroll-sentinel] {
|
|
143
20
|
position: absolute;
|
|
144
21
|
top: 240px;
|
|
@@ -103,7 +103,7 @@ function pageUrl(site: string, path: string, exportMd: boolean): string {
|
|
|
103
103
|
|
|
104
104
|
/** 生成文章链接,可切换 .md 源码版本 */
|
|
105
105
|
export function postUrl(site: string, abbrlink: string | number, exportMd: boolean): string {
|
|
106
|
-
return exportMd && abbrlink ? `${site}/posts/${abbrlink}.md` : `${site}/posts/${abbrlink}
|
|
106
|
+
return exportMd && abbrlink ? `${site}/posts/${abbrlink}.md` : `${site}/posts/${abbrlink}`;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
/** 获取已发布文章并按日期降序排列 */
|
package/src/utils/feed.ts
CHANGED
|
@@ -70,7 +70,7 @@ export async function buildFeedItems(
|
|
|
70
70
|
title: post.data.title,
|
|
71
71
|
pubDate: new Date(toMachineDateTime(post.data.date, stalux.timezone)),
|
|
72
72
|
description: cached?.desc || post.data.desc || "",
|
|
73
|
-
link: `/posts/${post.data.abbrlink}
|
|
73
|
+
link: `/posts/${post.data.abbrlink}`,
|
|
74
74
|
categories: post.data.categories || [],
|
|
75
75
|
customData,
|
|
76
76
|
};
|
|
@@ -45,10 +45,20 @@ export function getMarkdownPath(pathname: string): string | undefined {
|
|
|
45
45
|
return undefined;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
* The public form of an HTML route. Every page route is emitted without a
|
|
50
|
+
* trailing slash (`/posts/x`, `/tags/x`, `/archives`); only the root keeps its
|
|
51
|
+
* single slash. Real files — Markdown exports, JSON/XML endpoints, images —
|
|
52
|
+
* are returned untouched so they keep the extension that identifies them.
|
|
53
|
+
*/
|
|
54
|
+
export function toRoutePath(pathname: string): string {
|
|
55
|
+
const path = normalizePublicPath(pathname);
|
|
56
|
+
return path === "/" ? "/" : path;
|
|
57
|
+
}
|
|
58
|
+
|
|
48
59
|
export function toPublicUrl(site: string, pathname: string, markdown = false): string {
|
|
49
60
|
const base = site.replace(/\/+$/u, "");
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return markdown ? `${base}${path}` : `${base}${path === "/" ? "/" : `${path}/`}`;
|
|
61
|
+
const path = markdown ? getMarkdownPath(pathname) : toRoutePath(pathname);
|
|
62
|
+
if (!path) return `${base}${toRoutePath(pathname)}`;
|
|
63
|
+
return `${base}${path}`;
|
|
54
64
|
}
|
|
@@ -59,8 +59,9 @@ export function buildSeoDocument(input: SeoDocumentInput): SeoDocument {
|
|
|
59
59
|
const routeKind = getRouteKind(pathname);
|
|
60
60
|
const siteUrl = normalizeSiteUrl(site.canonical ?? site.url);
|
|
61
61
|
const normalizedPath = normalizePublicPath(pathname);
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
// Canonical mirrors the URL the router actually serves: page routes carry no
|
|
63
|
+
// trailing slash, so /posts/x and /archives are canonical, /posts/x/ is not.
|
|
64
|
+
const canonical = new URL(normalizedPath, `${siteUrl}/`).href;
|
|
64
65
|
const title = routeKind === "home" && site.seoTitle ? site.seoTitle : page.title;
|
|
65
66
|
const siteName = site.title;
|
|
66
67
|
const siteTitleSuffix = ` | ${site.title}`;
|
|
@@ -1,112 +1,7 @@
|
|
|
1
|
+
// Route classification shared by SSR and the client router. The Astro View
|
|
2
|
+
// Transitions helpers that used to live here were removed together with the
|
|
3
|
+
// ClientRouter: Swup owns navigation and every cue, so route animation config
|
|
4
|
+
// and `view-transition-name` generation had no consumer left.
|
|
1
5
|
import { getRouteKind, type RouteKind } from "./public-routes";
|
|
2
|
-
import { productionStyleName } from "./style-name.ts";
|
|
3
6
|
|
|
4
7
|
export { getRouteKind, type RouteKind };
|
|
5
|
-
|
|
6
|
-
/** Stable, CSS-safe transition names for matching a post card to its title. */
|
|
7
|
-
export function getPostTitleTransitionName(postId: string | number): string {
|
|
8
|
-
let hash = 2166136261;
|
|
9
|
-
for (const character of String(postId)) {
|
|
10
|
-
hash ^= character.codePointAt(0) ?? 0;
|
|
11
|
-
hash = Math.imul(hash, 16777619);
|
|
12
|
-
}
|
|
13
|
-
return `stalux-post-title-${(hash >>> 0).toString(36)}`;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export type TransitionAnimation = {
|
|
17
|
-
name: string;
|
|
18
|
-
delay?: number | string;
|
|
19
|
-
duration?: number | string;
|
|
20
|
-
easing?: string;
|
|
21
|
-
fillMode?: string;
|
|
22
|
-
direction?: string;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export type SidebarSide = "left" | "right";
|
|
26
|
-
|
|
27
|
-
export type RouteAnimation = {
|
|
28
|
-
forwards: {
|
|
29
|
-
old: TransitionAnimation | TransitionAnimation[];
|
|
30
|
-
new: TransitionAnimation | TransitionAnimation[];
|
|
31
|
-
};
|
|
32
|
-
backwards: {
|
|
33
|
-
old: TransitionAnimation | TransitionAnimation[];
|
|
34
|
-
new: TransitionAnimation | TransitionAnimation[];
|
|
35
|
-
};
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const easing = "cubic-bezier(0.2, 0.7, 0.2, 1)";
|
|
39
|
-
const exitAnimation: TransitionAnimation = {
|
|
40
|
-
name: "stalux-page-exit",
|
|
41
|
-
duration: "0.1s",
|
|
42
|
-
easing,
|
|
43
|
-
fillMode: "both",
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
function createRouteAnimation(name: string, backName = `${name}-back`): RouteAnimation {
|
|
47
|
-
return {
|
|
48
|
-
forwards: {
|
|
49
|
-
old: exitAnimation,
|
|
50
|
-
new: {
|
|
51
|
-
name: productionStyleName(`stalux-${name}`),
|
|
52
|
-
duration: "0.16s",
|
|
53
|
-
easing,
|
|
54
|
-
fillMode: "both",
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
backwards: {
|
|
58
|
-
old: exitAnimation,
|
|
59
|
-
new: {
|
|
60
|
-
name: productionStyleName(`stalux-${backName}`),
|
|
61
|
-
duration: "0.16s",
|
|
62
|
-
easing,
|
|
63
|
-
fillMode: "both",
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const routeAnimations: Record<RouteKind, RouteAnimation> = {
|
|
70
|
-
home: createRouteAnimation("page-enter"),
|
|
71
|
-
archive: createRouteAnimation("page-enter"),
|
|
72
|
-
links: createRouteAnimation("page-enter"),
|
|
73
|
-
words: createRouteAnimation("page-enter"),
|
|
74
|
-
about: createRouteAnimation("page-enter"),
|
|
75
|
-
"tags-index": createRouteAnimation("page-enter"),
|
|
76
|
-
"tags-detail": createRouteAnimation("taxonomy-enter", "taxonomy-enter-back"),
|
|
77
|
-
"categories-index": createRouteAnimation("page-enter"),
|
|
78
|
-
"categories-detail": createRouteAnimation("taxonomy-enter", "taxonomy-enter-back"),
|
|
79
|
-
article: createRouteAnimation("article-enter", "article-enter-back"),
|
|
80
|
-
"not-found": createRouteAnimation("page-enter"),
|
|
81
|
-
other: createRouteAnimation("page-enter"),
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
export function getRouteAnimation(routeKind: RouteKind): RouteAnimation {
|
|
85
|
-
return routeAnimations[routeKind];
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function createSidebarAnimation(
|
|
89
|
-
side: SidebarSide,
|
|
90
|
-
phase: "in" | "out",
|
|
91
|
-
backwards: boolean,
|
|
92
|
-
): TransitionAnimation {
|
|
93
|
-
return {
|
|
94
|
-
name: productionStyleName(`stalux-sidebar-${side}-${backwards ? "back-" : ""}${phase}`),
|
|
95
|
-
duration: "0.16s",
|
|
96
|
-
easing,
|
|
97
|
-
fillMode: "both",
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export function getSidebarAnimation(side: SidebarSide): RouteAnimation {
|
|
102
|
-
return {
|
|
103
|
-
forwards: {
|
|
104
|
-
old: createSidebarAnimation(side, "out", false),
|
|
105
|
-
new: createSidebarAnimation(side, "in", false),
|
|
106
|
-
},
|
|
107
|
-
backwards: {
|
|
108
|
-
old: createSidebarAnimation(side, "out", true),
|
|
109
|
-
new: createSidebarAnimation(side, "in", true),
|
|
110
|
-
},
|
|
111
|
-
};
|
|
112
|
-
}
|