@xingwangzhe/stalux 1.41.5 → 1.43.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/README.md +19 -5
- package/package.json +12 -3
- package/src/components/stalux/archives/archivesList.astro +0 -2
- package/src/components/stalux/archives/toArchive.astro +1 -5
- package/src/components/stalux/common/Typewriter.astro +1 -7
- package/src/components/stalux/common/author.astro +1 -6
- package/src/components/stalux/common/date.astro +1 -11
- package/src/components/stalux/layout/PageHeading.astro +2 -11
- package/src/components/stalux/layout/footer.astro +1 -6
- package/src/components/stalux/layout/head.astro +9 -2
- package/src/components/stalux/links/socialMedia.astro +1 -10
- package/src/components/stalux/posts/ArticleSummary.astro +2 -8
- package/src/components/stalux/posts/PostTaxonomy.astro +3 -14
- package/src/components/stalux/posts/postCC.astro +2 -2
- package/src/components/stalux/posts/postCard.astro +1 -5
- package/src/components/stalux/posts/postContent.astro +4 -23
- package/src/components/stalux/posts/postLeft.astro +4 -22
- package/src/components/stalux/posts/postRight.astro +5 -27
- package/src/components/stalux/posts/postToc.astro +3 -10
- package/src/components/stalux/posts/randomPost.astro +0 -1
- package/src/components/stalux/tags/tagHeader.astro +1 -5
- package/src/env.d.ts +5 -0
- package/src/index.ts +41 -2
- package/src/internal/social-card-data.ts +34 -0
- package/src/internal/social-card-renderer.ts +307 -0
- package/src/internal/style-names.generated.ts +59 -69
- package/src/layouts/PostLayout.astro +1 -5
- package/src/layouts/Stalux.astro +6 -19
- package/src/pages/index.astro +1 -5
- package/src/pages/og/[image].[format].ts +47 -0
- package/src/pages/posts/[post].astro +8 -0
- package/src/pages/posts/[post].md.ts +1 -1
- package/src/schemas/collections.ts +9 -0
- package/src/scripts/navigation-client.ts +13 -0
- package/src/scripts/navigation-scripts.ts +191 -0
- package/src/scripts/route-motion.ts +78 -11
- package/src/scripts/swup-router.ts +366 -0
- package/src/scripts/tags-cloud.ts +1 -1
- package/src/scripts/view-transitions.ts +3 -233
- package/src/scripts/word-list.ts +9 -3
- package/src/styles/generated.css +1 -1
- package/src/styles/motion.css +2 -211
- package/src/utils/post-markdown.ts +2 -0
- package/src/utils/route-catalog.ts +1 -0
- package/src/utils/seo-document.ts +21 -4
- package/src/utils/social-image.ts +60 -0
- package/src/scripts/archive-reveal.ts +0 -76
package/README.md
CHANGED
|
@@ -18,9 +18,9 @@ Standalone images written as `` receive a `figure` and
|
|
|
18
18
|
|
|
19
19
|
Code blocks default to the single `dark-plus` theme, with system color-scheme switching and theme selectors disabled. To opt into another theme or switching behavior, explicitly override `themes`, `useDarkModeMediaQuery`, and `themeCssSelector` through `expressiveCode`. This only changes generated code styles and adds no telemetry.
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
Swup owns soft navigation and transition timing. Astro renders the static documents; the browser runtime replaces only `main[data-stalux-route]`, keeping the header, footer, scroll sentinel and two background layers alive. The incoming visible heading receives a brief opacity or directional hint selected by the route policy: entering an article can move 6px vertically, explicit previous/next article links use opposite 8px horizontal hints, and returning to a list uses a 4px upward hint. Other article links and taxonomy changes fade without inventing a reading direction. Desktop effects last 80–140ms; phones use an 80ms fade without translation. The article body and long lists stay immediately readable. Reduced motion and browser-provided history gestures skip content motion; same-page anchors use their scrolling behavior and same-URL clicks preserve the reading position. Standalone HTML and exported data use document navigation. See the [Swup transition architecture and route policy](docs/view-transitions-swup.md).
|
|
22
22
|
|
|
23
|
-
The
|
|
23
|
+
The runtime uses Swup's Head, Accessibility, Preload, Scroll and JS plugins with Stalux lifecycle handlers. It waits for incoming stylesheets and gives the destination font a bounded 150ms head start, disposes old interactions before replacement, loads first-seen page scripts, then dispatches the Astro-compatible page lifecycle events used by comments, counters, tag clouds and WebMCP. Backgrounds decode independently and crossfade after the content animation finishes; stale navigation work cannot replace the current background. History positions are restored by the Swup runtime, including reduced-motion visits. This requires no new configuration or telemetry. Animation duration describes the effect itself, not total navigation time or a measured performance improvement.
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
@@ -136,7 +136,7 @@ Processed pages are cached under `node_modules/.astro/stalux-page-output/`. The
|
|
|
136
136
|
|
|
137
137
|
### Visibility-aware loading and updates
|
|
138
138
|
|
|
139
|
-
The desktop tag cloud loads dynamically near the viewport. Switching to mobile, leaving the viewport or hiding the document destroys it and stops animation scheduling; becoming visible recreates it. Tag clicks use
|
|
139
|
+
The desktop tag cloud loads dynamically near the viewport. Switching to mobile, leaving the viewport or hiding the document destroys it and stops animation scheduling; becoming visible recreates it. Tag clicks use the same Swup navigation as ordinary internal links. Clocks and the footer runtime update only while visible, and the date changes only on a new day. Comments load within half a viewport (capped at 400px). Tag groups, archive months and category cards retain static HTML while deferring offscreen rendering.
|
|
140
140
|
|
|
141
141
|
### Modern JavaScript
|
|
142
142
|
|
|
@@ -195,7 +195,7 @@ id: head
|
|
|
195
195
|
bingClarityId: "YOUR_CLARITY_PROJECT_ID"
|
|
196
196
|
```
|
|
197
197
|
|
|
198
|
-
Google Analytics, Clarity, and Umami use low-priority native asynchronous scripts. Each SDK loads once per session, and failures do not block reading or navigation. Vercount rebinds visible counters after each `astro:page-load`. GA captures each URL, title, and referrer, then sends pageviews in visit order through separate background tasks after the
|
|
198
|
+
Google Analytics, Clarity, and Umami use low-priority native asynchronous scripts. Each SDK loads once per session, and failures do not block reading or navigation. Vercount rebinds visible counters after each `astro:page-load`. GA captures each URL, title, and referrer, then sends pageviews in visit order through separate background tasks after the shared Swup content-motion gate settles and a paint has been yielded. A bounded timer handles task starvation; hiding or leaving the document flushes pending views immediately. The SDK still runs on the main thread; this scheduling reduces synchronous work on the route's first frame. Umami disables automatic pageviews while retaining click tracking and captures page information before the SDK resolves so rapid navigation cannot mix visits. An existing older runtime or legacy Partytown session performs one full reload when it encounters the new runtime to prevent duplicate listeners and tracking.
|
|
199
199
|
|
|
200
200
|
For Google Analytics, turn off **Page changes based on browser history events** under **Admin → Data streams → Enhanced measurement → Page views → Advanced settings**. Stalux sets `send_page_view: false` and sends the URL and title for each navigation explicitly. GA's history tracking must also be disabled in the property to prevent duplicate soft-navigation pageviews. Other enhanced measurement options can remain enabled. See [Google's pageview documentation](https://developers.google.com/analytics/devguides/collection/ga4/views).
|
|
201
201
|
|
|
@@ -284,7 +284,7 @@ This is a build-time metadata field. It does not create a contact endpoint or ex
|
|
|
284
284
|
|
|
285
285
|
The root reserves scrollbar space and uses explicit line height. The homepage typewriter reserves the maximum wrapped height of its complete messages and keeps the text origin fixed; clocks reserve line boxes and use tabular digits. Existing typing, cursor and route animations remain enabled. No additional configuration is required.
|
|
286
286
|
|
|
287
|
-
|
|
287
|
+
Swup's pre-replacement preparation warms the destination body font without installing it on the old page. The font receives at most 150ms of preparation time; failure, timeout and superseding navigation release that font wait. Incoming stylesheets and first-seen page modules have separate bounded loading waits so the next page can initialize its interactions. Initial loads on slow networks may still show the system fallback. Content authors must reserve dimensions for remote images and third-party embeds. Reduced-motion and print behavior remain supported.
|
|
288
288
|
|
|
289
289
|
See [style maintenance](docs/STYLING.md) and [lifecycle and static interfaces](docs/RUNTIME.md). Astro development documentation is available through the [official MCP endpoint](https://mcp.docs.astro.build/mcp); `.codex/config.toml`, `.mcp.json` and `AGENTS.md` record the project setup. This development MCP is separate from the blog's browser WebMCP tools.
|
|
290
290
|
|
|
@@ -356,3 +356,17 @@ Theme code is **MIT**; the root [LICENSE](LICENSE) contains the standard text fo
|
|
|
356
356
|
| Font copyrights, reserved names and modification notices | Each font’s original license | [LICENSE-FONT-NOTICES.txt](LICENSES/LICENSE-FONT-NOTICES.txt) |
|
|
357
357
|
|
|
358
358
|
The npm package includes `LICENSES/` and font-specific texts in `public/fonts/`; builds synchronize font notices to the consumer’s public font directory alongside the served WOFF2 files. Native subsetting dependencies retain their [separate license inventory](https://github.com/xingwangzhe/cjk-font-split-native/blob/main/README.en.md#licenses-and-scope) and packaged `THIRD_PARTY_LICENSES.txt`. GitHub’s primary-license display identifies theme code; fonts and other third-party components retain the scopes listed above.
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
### Article social sharing cards
|
|
362
|
+
|
|
363
|
+
Image priority is **explicit `og:image` → a card with a valid `cover` → an automatic title card**. The article list continues to use `cover`. An explicit `og:image` is used as-is and accepts HTTP(S), protocol-relative URLs, or site-root paths; PNG/JPEG at 1200×630 is recommended. Omit it or leave it empty to generate a card automatically. Existing posts need no changes.
|
|
364
|
+
|
|
365
|
+
```yaml title="Article sharing images"
|
|
366
|
+
cover: /images/article-cover.webp
|
|
367
|
+
og:image: /images/custom-social-card.png
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
`@takumi-rs/core` renders a static 1200×630 WebP at `/og/<metadata-hash>.webp` using the bundled LXGW WenKai font. Cards include the title, summary, site identity, author, category, accent color and date in the site timezone. No renderer JavaScript is sent to the browser. Static `og:image`, `twitter:image` and BlogPosting `image` use the same absolute URL; generated images also declare dimensions and MIME type. Articles use `summary_large_image`. A second `og:image` points to a PNG fallback; platforms choose which format they can read. WebP quality is 86; AVIF is not the default.
|
|
371
|
+
|
|
372
|
+
Local covers are read from the final `publicDir`. Remote covers are requested by the build machine, with an 8-second timeout and an 8 MiB limit (remote bytes are cached for 24 hours); unreadable or undecodable artwork emits a warning and falls back to a title card. No remote image-generation service is used. WebP and PNG outputs are cached in `stalux-social-cards/` under Astro's cache directory and copied into each build output. Explicit sharing images are fetched by social platforms, so they must be publicly accessible images. Platforms maintain their own preview caches and may not refresh an existing share immediately after deployment.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xingwangzhe/stalux",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.43.0",
|
|
4
4
|
"description": "A powerful, modern Astro blog theme — use as template or install as plugin",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"astro",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"LICENSES"
|
|
51
51
|
],
|
|
52
52
|
"type": "module",
|
|
53
|
-
"packageManager": "bun@1.4.
|
|
53
|
+
"packageManager": "bun@1.4.4",
|
|
54
54
|
"exports": {
|
|
55
55
|
".": "./src/index.ts",
|
|
56
56
|
"./config": "./src/config.ts",
|
|
@@ -97,7 +97,8 @@
|
|
|
97
97
|
"styles:build": "node scripts/build-styles.ts && node scripts/build-style-names.ts",
|
|
98
98
|
"styles:watch": "node scripts/build-styles.ts --watch",
|
|
99
99
|
"benchmark:performance": "node scripts/benchmark-performance.ts",
|
|
100
|
-
"benchmark:builds": "python3 scripts/benchmark-builds.py"
|
|
100
|
+
"benchmark:builds": "python3 scripts/benchmark-builds.py",
|
|
101
|
+
"analyze": "SONDA=1 bun run build"
|
|
101
102
|
},
|
|
102
103
|
"dependencies": {
|
|
103
104
|
"@astrojs/compiler": "^4.0.0",
|
|
@@ -109,6 +110,12 @@
|
|
|
109
110
|
"@mcp-b/webmcp-polyfill": "^5.1.0",
|
|
110
111
|
"@microsoft/clarity": "1.0.2",
|
|
111
112
|
"@pagefind/component-ui": "^1.5.2",
|
|
113
|
+
"@swup/a11y-plugin": "^5.2.1",
|
|
114
|
+
"@swup/head-plugin": "^2.3.1",
|
|
115
|
+
"@swup/js-plugin": "^3.2.0",
|
|
116
|
+
"@swup/preload-plugin": "^3.2.12",
|
|
117
|
+
"@swup/scroll-plugin": "^4.0.0",
|
|
118
|
+
"@takumi-rs/core": "2.17.1",
|
|
112
119
|
"@waline/client": "^3.16.1",
|
|
113
120
|
"@xingwangzhe/cjk-font-split-native": "^0.4.10",
|
|
114
121
|
"@xingwangzhe/satteri-mermaid": "^0.8.2",
|
|
@@ -125,6 +132,7 @@
|
|
|
125
132
|
"photoswipe": "^5.4.4",
|
|
126
133
|
"satteri": "^0.10.5",
|
|
127
134
|
"simple-icons": "^16.35.0",
|
|
135
|
+
"swup": "4.10.0",
|
|
128
136
|
"temml": "^0.14.0",
|
|
129
137
|
"yaml": "^2.9.1"
|
|
130
138
|
},
|
|
@@ -137,6 +145,7 @@
|
|
|
137
145
|
"@vitest/coverage-v8": "^5.0.4",
|
|
138
146
|
"astro": "^7.4.2",
|
|
139
147
|
"knip": "^6.41.0",
|
|
148
|
+
"sonda": "^0.14.0",
|
|
140
149
|
"typescript": "npm:@typescript/typescript6@6.0.2",
|
|
141
150
|
"unocss": "^66.11.0",
|
|
142
151
|
"vite": "^8.3.4",
|
|
@@ -127,9 +127,7 @@ const archiveYears = [...archivesByYearMonth.entries()]
|
|
|
127
127
|
|
|
128
128
|
<script>
|
|
129
129
|
import { mountArchiveDescriptions } from "../../../scripts/archive-descriptions";
|
|
130
|
-
import { mountArchiveReveal } from "../../../scripts/archive-reveal";
|
|
131
130
|
import { registerPageLifecycle } from "../../../scripts/page-runtime";
|
|
132
131
|
|
|
133
|
-
registerPageLifecycle("archive-reveal", mountArchiveReveal);
|
|
134
132
|
registerPageLifecycle("archive-descriptions", mountArchiveDescriptions);
|
|
135
133
|
</script>
|
|
@@ -9,10 +9,6 @@ const siteConfig = getSiteData(configEntries);
|
|
|
9
9
|
const { t } = createTranslator(siteConfig.lang || "zh-CN");
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
-
<div
|
|
13
|
-
id={"stalux-to-archive-archs"}
|
|
14
|
-
transition:name="stalux-home-archive-link"
|
|
15
|
-
transition:animate="slide"
|
|
16
|
-
>
|
|
12
|
+
<div id={"stalux-to-archive-archs"}>
|
|
17
13
|
<a href="/archives" data-astro-prefetch>{t("archives.viewAll")}</a>
|
|
18
14
|
</div>
|
|
@@ -10,13 +10,7 @@ const texts = normalizeMessages(messages);
|
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
{texts.length > 0 && (
|
|
13
|
-
<div
|
|
14
|
-
class={className}
|
|
15
|
-
data-stalux-typewriter
|
|
16
|
-
data-messages={JSON.stringify(texts)}
|
|
17
|
-
transition:name="stalux-home-typewriter"
|
|
18
|
-
transition:animate="fade"
|
|
19
|
-
>
|
|
13
|
+
<div class={className} data-stalux-typewriter data-messages={JSON.stringify(texts)}>
|
|
20
14
|
<span class="stalux-typewriter-accessible">{texts.join(", ")}</span>
|
|
21
15
|
<span class="stalux-typewriter-reserve" aria-hidden="true">
|
|
22
16
|
{texts.map((text) => (
|
|
@@ -17,12 +17,7 @@ const isHomePage = Astro.url.pathname === "/";
|
|
|
17
17
|
const navigationHref = isHomePage ? "/about" : "/";
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
<article
|
|
21
|
-
class="stalux-author stalux-u-flex stalux-u-justify-center stalux-u-flex-col"
|
|
22
|
-
transition:persist-props
|
|
23
|
-
transition:name={isHomePage ? "stalux-home-author" : undefined}
|
|
24
|
-
transition:animate={isHomePage ? "fade" : undefined}
|
|
25
|
-
>
|
|
20
|
+
<article class="stalux-author stalux-u-flex stalux-u-justify-center stalux-u-flex-col">
|
|
26
21
|
<figure
|
|
27
22
|
class={`stalux-author-figure ${props.iscolum ? "stalux-author-figure-column stalux-u-flex-col" : ""}`}
|
|
28
23
|
>
|
|
@@ -1,14 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
const isHomePage = Astro.url.pathname === "/";
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
<div
|
|
6
|
-
id={"stalux-date-date-time"}
|
|
7
|
-
class="date-time"
|
|
8
|
-
transition:persist-props
|
|
9
|
-
transition:name={isHomePage ? "stalux-home-date-time" : undefined}
|
|
10
|
-
transition:animate={isHomePage ? "fade" : undefined}
|
|
11
|
-
>
|
|
1
|
+
<div id={"stalux-date-date-time"} class="date-time">
|
|
12
2
|
<time id={"stalux-date-date"} data-ref="date" datetime=""></time>
|
|
13
3
|
<time id={"stalux-date-time"} data-ref="time" datetime=""></time>
|
|
14
4
|
</div>
|
|
@@ -8,20 +8,11 @@ const { heading, description } = Astro.props;
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
<>
|
|
11
|
-
<h1
|
|
12
|
-
class="stalux-page-title stalux-u-text-center"
|
|
13
|
-
data-stalux-motion-focus
|
|
14
|
-
transition:animate="none"
|
|
15
|
-
>
|
|
11
|
+
<h1 class="stalux-page-title stalux-u-text-center" data-stalux-motion-focus>
|
|
16
12
|
{heading}
|
|
17
13
|
</h1>
|
|
18
14
|
{description && (
|
|
19
|
-
<div
|
|
20
|
-
class="stalux-page-description stalux-u-text-center"
|
|
21
|
-
data-stalux-motion-content
|
|
22
|
-
transition:name="stalux-page-description"
|
|
23
|
-
transition:animate="none"
|
|
24
|
-
>
|
|
15
|
+
<div class="stalux-page-description stalux-u-text-center" data-stalux-motion-content>
|
|
25
16
|
{description}
|
|
26
17
|
</div>
|
|
27
18
|
)}
|
|
@@ -51,12 +51,7 @@ const totalWordCount = await getTotalWordCount(Astro.logger);
|
|
|
51
51
|
const formattedWordCount = formatWordCount(totalWordCount, siteConfig.lang || "zh-CN");
|
|
52
52
|
---
|
|
53
53
|
|
|
54
|
-
<footer
|
|
55
|
-
class="stalux-footer stalux-u-w-full stalux-u-text-center"
|
|
56
|
-
data-stalux-font-group="footer"
|
|
57
|
-
transition:persist="stalux-site-footer"
|
|
58
|
-
transition:persist-props
|
|
59
|
-
>
|
|
54
|
+
<footer class="stalux-footer stalux-u-w-full stalux-u-text-center" data-stalux-font-group="footer">
|
|
60
55
|
<div class="stalux-footer-content stalux-u-flex stalux-u-flex-col">
|
|
61
56
|
<!-- 版权信息 -->
|
|
62
57
|
{footerConfig?.copyright?.enabled && (
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { Font } from "astro:assets";
|
|
3
3
|
import { getCollection } from "astro:content";
|
|
4
|
-
import { ClientRouter } from "astro:transitions";
|
|
5
4
|
// Emit a stable asset even while the search component JavaScript stays lazy.
|
|
6
5
|
// The closed search dialog does not need to block the page's first paint.
|
|
7
6
|
import pagefindStyles from "virtual:stalux-search-style";
|
|
@@ -54,7 +53,6 @@ const ldJson = JSON.stringify(seo.schema).replace(/<\//g, "<\\/");
|
|
|
54
53
|
|
|
55
54
|
<head>
|
|
56
55
|
<meta charset="utf-8">
|
|
57
|
-
<ClientRouter fallback="swap" />
|
|
58
56
|
<SEO
|
|
59
57
|
title={seo.title}
|
|
60
58
|
description={seo.description}
|
|
@@ -68,6 +66,15 @@ const ldJson = JSON.stringify(seo.schema).replace(/<\//g, "<\\/");
|
|
|
68
66
|
meta: seo.meta,
|
|
69
67
|
}}
|
|
70
68
|
/>
|
|
69
|
+
{seo.fallbackImage && (
|
|
70
|
+
<>
|
|
71
|
+
<meta property="og:image" content={seo.fallbackImage} />
|
|
72
|
+
<meta property="og:image:type" content="image/png" />
|
|
73
|
+
<meta property="og:image:width" content="1200" />
|
|
74
|
+
<meta property="og:image:height" content="630" />
|
|
75
|
+
<meta property="og:image:alt" content={seo.openGraph.basic.title} />
|
|
76
|
+
</>
|
|
77
|
+
)}
|
|
71
78
|
<!-- 代码字体由 Astro Fonts API 注入;正文按页面生成 native CJK 子集。 -->
|
|
72
79
|
<Font cssVariable="--font-code" />
|
|
73
80
|
<link rel="prefetch" as="style" href={pagefindStyles} data-stalux-search-style>
|
|
@@ -17,8 +17,6 @@ import {
|
|
|
17
17
|
const configEntries = await getCollection("config");
|
|
18
18
|
const mediaLinksSection = getMediaLinksData(configEntries);
|
|
19
19
|
const mediaLinks = mediaLinksSection?.items ?? [];
|
|
20
|
-
const isPostPage = Astro.url.pathname.startsWith("/posts/");
|
|
21
|
-
const isHomePage = Astro.url.pathname === "/";
|
|
22
20
|
|
|
23
21
|
// 静态图标映射表:新增图标时只需添加对应的 simple-icons 导入和映射
|
|
24
22
|
const iconMap: Record<string, SimpleIcon> = {
|
|
@@ -35,14 +33,7 @@ function getIconByTitle(iconName: string): SimpleIcon | undefined {
|
|
|
35
33
|
}
|
|
36
34
|
---
|
|
37
35
|
|
|
38
|
-
<nav
|
|
39
|
-
class="stalux-social"
|
|
40
|
-
transition:persist-props
|
|
41
|
-
transition:name={isHomePage ? "stalux-home-social" : undefined}
|
|
42
|
-
transition:animate={isHomePage ? "fade" : undefined}
|
|
43
|
-
aria-label="Social media"
|
|
44
|
-
data-stalux-social-animate={String(!isPostPage)}
|
|
45
|
-
>
|
|
36
|
+
<nav class="stalux-social" aria-label="Social media">
|
|
46
37
|
<ul>
|
|
47
38
|
{mediaLinks.map((item) => {
|
|
48
39
|
const icon = item.icon ? getIconByTitle(item.icon) : undefined;
|
|
@@ -4,18 +4,12 @@ interface Props {
|
|
|
4
4
|
label: string;
|
|
5
5
|
transitionName: string;
|
|
6
6
|
}
|
|
7
|
-
const { description, label
|
|
7
|
+
const { description, label } = Astro.props;
|
|
8
8
|
const summary = description?.trim();
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
{summary && (
|
|
12
|
-
<aside
|
|
13
|
-
class="stalux-article-summary"
|
|
14
|
-
data-stalux-motion-content
|
|
15
|
-
aria-label={label}
|
|
16
|
-
transition:name={transitionName}
|
|
17
|
-
transition:animate="none"
|
|
18
|
-
>
|
|
12
|
+
<aside class="stalux-article-summary" data-stalux-motion-content aria-label={label}>
|
|
19
13
|
<p class="stalux-article-summary-label">{label}</p>
|
|
20
14
|
<p class="stalux-article-summary-text">{summary}</p>
|
|
21
15
|
</aside>
|
|
@@ -43,15 +43,10 @@ const cfg = {
|
|
|
43
43
|
}[kind];
|
|
44
44
|
---
|
|
45
45
|
|
|
46
|
-
<nav
|
|
47
|
-
class="stalux-post-taxonomy-container"
|
|
48
|
-
transition:name={cfg.containerName}
|
|
49
|
-
transition:animate="none"
|
|
50
|
-
aria-label={title ?? cfg.heading}
|
|
51
|
-
>
|
|
46
|
+
<nav class="stalux-post-taxonomy-container" aria-label={title ?? cfg.heading}>
|
|
52
47
|
<h3 class="stalux-post-taxonomy-title">{title ?? cfg.heading}</h3>
|
|
53
48
|
{items.length > 0 ? (
|
|
54
|
-
<div class={cfg.listClass}
|
|
49
|
+
<div class={cfg.listClass}>
|
|
55
50
|
{items.map((item) => (
|
|
56
51
|
<a
|
|
57
52
|
href={`${cfg.prefix}${item}/`}
|
|
@@ -63,12 +58,6 @@ const cfg = {
|
|
|
63
58
|
))}
|
|
64
59
|
</div>
|
|
65
60
|
) : (
|
|
66
|
-
<div
|
|
67
|
-
class="stalux-post-taxonomy-empty"
|
|
68
|
-
transition:name={cfg.contentName}
|
|
69
|
-
transition:animate="fade"
|
|
70
|
-
>
|
|
71
|
-
{cfg.empty}
|
|
72
|
-
</div>
|
|
61
|
+
<div class="stalux-post-taxonomy-empty">{cfg.empty}</div>
|
|
73
62
|
)}
|
|
74
63
|
</nav>
|
|
@@ -20,13 +20,13 @@ const siteConfig = (configEntries.find((e) => e.id === "site")?.data ?? {}) as R
|
|
|
20
20
|
unknown
|
|
21
21
|
>;
|
|
22
22
|
const { t } = createTranslator((siteConfig.lang as string) || "zh-CN");
|
|
23
|
-
const { title, author, url, cc = "CC-BY-NC-SA-4.0"
|
|
23
|
+
const { title, author, url, cc = "CC-BY-NC-SA-4.0" } = Astro.props;
|
|
24
24
|
|
|
25
25
|
const licenseLink = buildCCLink(cc);
|
|
26
26
|
const licenseName = buildCCName(cc, t);
|
|
27
27
|
---
|
|
28
28
|
|
|
29
|
-
<div class="stalux-license-box"
|
|
29
|
+
<div class="stalux-license-box">
|
|
30
30
|
<div class="stalux-license-content">
|
|
31
31
|
<p class="stalux-license-title">{title}</p>
|
|
32
32
|
<p class="stalux-license-author">{t("post.author")}{author}</p>
|
|
@@ -4,7 +4,6 @@ import { getCollection } from "astro:content";
|
|
|
4
4
|
|
|
5
5
|
import { getSiteData } from "@utils/config-utils";
|
|
6
6
|
import { toMachineDateTime } from "@utils/semantic-time";
|
|
7
|
-
import { getPostTitleTransitionName } from "@utils/view-transitions";
|
|
8
7
|
|
|
9
8
|
interface Props {
|
|
10
9
|
post: CollectionEntry<"posts">;
|
|
@@ -42,10 +41,7 @@ const description = post.data.desc || "";
|
|
|
42
41
|
</div>
|
|
43
42
|
</a>
|
|
44
43
|
)}
|
|
45
|
-
<h2
|
|
46
|
-
class="stalux-card-post-title"
|
|
47
|
-
transition:name={priority ? getPostTitleTransitionName(post.data.abbrlink) : undefined}
|
|
48
|
-
>
|
|
44
|
+
<h2 class="stalux-card-post-title">
|
|
49
45
|
<a href={`/posts/${post.data.abbrlink}/`} class="a-none" data-astro-prefetch="viewport">
|
|
50
46
|
{post.data.title}
|
|
51
47
|
</a>
|
|
@@ -38,26 +38,13 @@ const exportMd = Boolean(promoteConfig?.export_md) && !isAboutPage;
|
|
|
38
38
|
const mdSourceUrl = exportMd ? `${Astro.url.pathname.replace(/\/$/, "")}.md` : "";
|
|
39
39
|
---
|
|
40
40
|
|
|
41
|
-
<article
|
|
42
|
-
class="stalux-article"
|
|
43
|
-
data-stalux-gallery={props.hasImage ? "true" : undefined}
|
|
44
|
-
transition:name={props.transitionName ?? "stalux-article-container"}
|
|
45
|
-
transition:animate="none"
|
|
46
|
-
>
|
|
41
|
+
<article class="stalux-article" data-stalux-gallery={props.hasImage ? "true" : undefined}>
|
|
47
42
|
<!-- Article Header -->
|
|
48
|
-
<header
|
|
49
|
-
class="stalux-post-article-header"
|
|
50
|
-
transition:name={`${transitionPrefix}-header`}
|
|
51
|
-
transition:animate="fade"
|
|
52
|
-
>
|
|
43
|
+
<header class="stalux-post-article-header">
|
|
53
44
|
<h1 class="stalux-post-title" data-stalux-motion-focus>
|
|
54
45
|
{props.title}
|
|
55
46
|
</h1>
|
|
56
|
-
<div
|
|
57
|
-
class="stalux-post-metadata"
|
|
58
|
-
transition:name={`${transitionPrefix}-metadata`}
|
|
59
|
-
transition:animate="none"
|
|
60
|
-
>
|
|
47
|
+
<div class="stalux-post-metadata">
|
|
61
48
|
{props.date && (
|
|
62
49
|
<time
|
|
63
50
|
class="stalux-post-meta-item"
|
|
@@ -78,11 +65,7 @@ const mdSourceUrl = exportMd ? `${Astro.url.pathname.replace(/\/$/, "")}.md` : "
|
|
|
78
65
|
</time>
|
|
79
66
|
)}
|
|
80
67
|
</div>
|
|
81
|
-
<div
|
|
82
|
-
class="stalux-post-page-stats"
|
|
83
|
-
transition:name={`${transitionPrefix}-stats`}
|
|
84
|
-
transition:animate="none"
|
|
85
|
-
>
|
|
68
|
+
<div class="stalux-post-page-stats">
|
|
86
69
|
{(props.readingMinutes ?? 0) > 0 && (
|
|
87
70
|
<span class="stalux-post-reading-time">
|
|
88
71
|
{t("post.readingTime")}
|
|
@@ -131,8 +114,6 @@ const mdSourceUrl = exportMd ? `${Astro.url.pathname.replace(/\/$/, "")}.md` : "
|
|
|
131
114
|
data-pagefind-body
|
|
132
115
|
data-stalux-post-id={props.postId === undefined ? undefined : String(props.postId)}
|
|
133
116
|
data-pagefind-filter={props.postId === undefined ? undefined : "post[data-stalux-post-id]"}
|
|
134
|
-
transition:name={`${transitionPrefix}-body`}
|
|
135
|
-
transition:animate="none"
|
|
136
117
|
>
|
|
137
118
|
<slot />
|
|
138
119
|
</section>
|
|
@@ -3,34 +3,16 @@ import "../../../styles/generated-article.css";
|
|
|
3
3
|
import SocialMedia from "@components/stalux/links/socialMedia.astro";
|
|
4
4
|
import PostAuthor from "@components/stalux/posts/postAuthor.astro";
|
|
5
5
|
import RandomPost from "@components/stalux/posts/randomPost.astro";
|
|
6
|
-
|
|
7
|
-
import { getSidebarAnimation } from "@utils/view-transitions";
|
|
8
6
|
---
|
|
9
7
|
|
|
10
|
-
<aside
|
|
11
|
-
class="stalux-sidebar"
|
|
12
|
-
transition:name="left-sidebar"
|
|
13
|
-
transition:animate={getSidebarAnimation("left")}
|
|
14
|
-
>
|
|
15
|
-
<div
|
|
16
|
-
class="stalux-sidebar-container"
|
|
17
|
-
transition:name="stalux-article-left-author"
|
|
18
|
-
transition:animate="fade"
|
|
19
|
-
>
|
|
8
|
+
<aside class="stalux-sidebar">
|
|
9
|
+
<div class="stalux-sidebar-container">
|
|
20
10
|
<PostAuthor />
|
|
21
11
|
</div>
|
|
22
|
-
<div
|
|
23
|
-
class="stalux-sidebar-container"
|
|
24
|
-
transition:name="stalux-article-left-social"
|
|
25
|
-
transition:animate="fade"
|
|
26
|
-
>
|
|
12
|
+
<div class="stalux-sidebar-container">
|
|
27
13
|
<SocialMedia />
|
|
28
14
|
</div>
|
|
29
|
-
<div
|
|
30
|
-
class="stalux-sidebar-container"
|
|
31
|
-
transition:name="stalux-article-left-random"
|
|
32
|
-
transition:animate="fade"
|
|
33
|
-
>
|
|
15
|
+
<div class="stalux-sidebar-container">
|
|
34
16
|
<RandomPost />
|
|
35
17
|
</div>
|
|
36
18
|
</aside>
|
|
@@ -5,8 +5,6 @@ import Weather from "@components/stalux/common/Weather.astro";
|
|
|
5
5
|
import PostTaxonomy from "@components/stalux/posts/PostTaxonomy.astro";
|
|
6
6
|
import PostToc from "@components/stalux/posts/postToc.astro";
|
|
7
7
|
|
|
8
|
-
import { getSidebarAnimation } from "@utils/view-transitions";
|
|
9
|
-
|
|
10
8
|
interface Props {
|
|
11
9
|
headings?: Array<{ depth: number; slug: string; text: string }>;
|
|
12
10
|
tags?: string[];
|
|
@@ -16,38 +14,18 @@ interface Props {
|
|
|
16
14
|
const { headings = [], tags = [], categories = [] } = Astro.props;
|
|
17
15
|
---
|
|
18
16
|
|
|
19
|
-
<aside
|
|
20
|
-
class="stalux-sidebar-
|
|
21
|
-
transition:name="right-sidebar"
|
|
22
|
-
transition:animate={getSidebarAnimation("right")}
|
|
23
|
-
>
|
|
24
|
-
<div
|
|
25
|
-
class="stalux-sidebar-container"
|
|
26
|
-
transition:name="stalux-article-right-date"
|
|
27
|
-
transition:animate="none"
|
|
28
|
-
>
|
|
17
|
+
<aside class="stalux-sidebar-right">
|
|
18
|
+
<div class="stalux-sidebar-container">
|
|
29
19
|
<PostDate />
|
|
30
20
|
<Weather />
|
|
31
21
|
</div>
|
|
32
|
-
<div
|
|
33
|
-
class="stalux-sidebar-container"
|
|
34
|
-
transition:name="stalux-article-right-toc"
|
|
35
|
-
transition:animate="none"
|
|
36
|
-
>
|
|
22
|
+
<div class="stalux-sidebar-container">
|
|
37
23
|
<PostToc headings={headings} />
|
|
38
24
|
</div>
|
|
39
|
-
<div
|
|
40
|
-
class="stalux-sidebar-container"
|
|
41
|
-
transition:name="stalux-article-right-tags"
|
|
42
|
-
transition:animate="none"
|
|
43
|
-
>
|
|
25
|
+
<div class="stalux-sidebar-container">
|
|
44
26
|
<PostTaxonomy kind="tag" items={tags} />
|
|
45
27
|
</div>
|
|
46
|
-
<div
|
|
47
|
-
class="stalux-sidebar-container"
|
|
48
|
-
transition:name="stalux-article-right-categories"
|
|
49
|
-
transition:animate="none"
|
|
50
|
-
>
|
|
28
|
+
<div class="stalux-sidebar-container">
|
|
51
29
|
<PostTaxonomy kind="category" items={categories} />
|
|
52
30
|
</div>
|
|
53
31
|
</aside>
|
|
@@ -29,15 +29,10 @@ const tocItems = headings
|
|
|
29
29
|
}));
|
|
30
30
|
---
|
|
31
31
|
|
|
32
|
-
<nav
|
|
33
|
-
transition:name="toc-container"
|
|
34
|
-
transition:animate="none"
|
|
35
|
-
data-toc-active-class="stalux-toc-active"
|
|
36
|
-
aria-label={t("taxonomy.toc")}
|
|
37
|
-
>
|
|
32
|
+
<nav data-toc-active-class="stalux-toc-active" aria-label={t("taxonomy.toc")}>
|
|
38
33
|
<h3 class="stalux-toc-title">{title}</h3>
|
|
39
34
|
{tocItems.length > 0 ? (
|
|
40
|
-
<ul class="stalux-toc-list"
|
|
35
|
+
<ul class="stalux-toc-list">
|
|
41
36
|
{tocItems.map((heading) => (
|
|
42
37
|
<li>
|
|
43
38
|
<a
|
|
@@ -51,9 +46,7 @@ const tocItems = headings
|
|
|
51
46
|
))}
|
|
52
47
|
</ul>
|
|
53
48
|
) : (
|
|
54
|
-
<div class="stalux-toc-empty"
|
|
55
|
-
{t("taxonomy.noToc")}
|
|
56
|
-
</div>
|
|
49
|
+
<div class="stalux-toc-empty">{t("taxonomy.noToc")}</div>
|
|
57
50
|
)}
|
|
58
51
|
</nav>
|
|
59
52
|
|
|
@@ -27,11 +27,7 @@ if (typeKey === "category" || typeKey === "categories" || typeKey === "分类")
|
|
|
27
27
|
}
|
|
28
28
|
---
|
|
29
29
|
|
|
30
|
-
<header
|
|
31
|
-
class="stalux-tag-header"
|
|
32
|
-
transition:name="stalux-taxonomy-page-header-shell"
|
|
33
|
-
transition:animate="none"
|
|
34
|
-
>
|
|
30
|
+
<header class="stalux-tag-header">
|
|
35
31
|
<h1 class="stalux-tag-page-title" data-stalux-motion-focus>
|
|
36
32
|
<span class="stalux-tag-category-icon">
|
|
37
33
|
<svg
|
package/src/env.d.ts
CHANGED