style: overall optimized UI style
This commit is contained in:
parent
18abe2f3d9
commit
cd3581de17
26 changed files with 263 additions and 143 deletions
|
|
@ -42,7 +42,8 @@
|
|||
"lint-staged": "^15.2.11",
|
||||
"prettier": "^3.4.2",
|
||||
"prettier-plugin-astro": "^0.14.1",
|
||||
"prettier-plugin-tailwindcss": "^0.6.9"
|
||||
"prettier-plugin-tailwindcss": "^0.6.9",
|
||||
"sass": "^1.83.0"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*/**/*.{js,jsx,ts,tsx,astro}": [
|
||||
|
|
|
|||
66
pnpm-lock.yaml
generated
66
pnpm-lock.yaml
generated
|
|
@ -13,10 +13,10 @@ importers:
|
|||
version: 0.9.4(prettier-plugin-astro@0.14.1)(prettier@3.4.2)(typescript@5.7.2)
|
||||
'@astrojs/mdx':
|
||||
specifier: ^4.0.2
|
||||
version: 4.0.2(astro@5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(typescript@5.7.2)(yaml@2.6.1))
|
||||
version: 4.0.2(astro@5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(sass@1.83.0)(typescript@5.7.2)(yaml@2.6.1))
|
||||
'@astrojs/react':
|
||||
specifier: ^4.1.0
|
||||
version: 4.1.0(@types/node@22.10.2)(@types/react-dom@18.3.1)(@types/react@18.3.12)(jiti@2.4.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(yaml@2.6.1)
|
||||
version: 4.1.0(@types/node@22.10.2)(@types/react-dom@18.3.1)(@types/react@18.3.12)(jiti@2.4.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.83.0)(yaml@2.6.1)
|
||||
'@astrojs/rss':
|
||||
specifier: ^4.0.10
|
||||
version: 4.0.10
|
||||
|
|
@ -25,7 +25,7 @@ importers:
|
|||
version: 3.2.1
|
||||
'@astrojs/tailwind':
|
||||
specifier: ^5.1.3
|
||||
version: 5.1.3(astro@5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(typescript@5.7.2)(yaml@2.6.1))(tailwindcss@3.4.16)
|
||||
version: 5.1.3(astro@5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(sass@1.83.0)(typescript@5.7.2)(yaml@2.6.1))(tailwindcss@3.4.16)
|
||||
'@types/react':
|
||||
specifier: ^18.3.12
|
||||
version: 18.3.12
|
||||
|
|
@ -34,10 +34,10 @@ importers:
|
|||
version: 18.3.1
|
||||
astro:
|
||||
specifier: ^5.1.0
|
||||
version: 5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(typescript@5.7.2)(yaml@2.6.1)
|
||||
version: 5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(sass@1.83.0)(typescript@5.7.2)(yaml@2.6.1)
|
||||
astro-og-canvas:
|
||||
specifier: ^0.5.5
|
||||
version: 0.5.5(astro@5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(typescript@5.7.2)(yaml@2.6.1))
|
||||
version: 0.5.5(astro@5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(sass@1.83.0)(typescript@5.7.2)(yaml@2.6.1))
|
||||
canvaskit-wasm:
|
||||
specifier: ^0.39.1
|
||||
version: 0.39.1
|
||||
|
|
@ -99,6 +99,9 @@ importers:
|
|||
prettier-plugin-tailwindcss:
|
||||
specifier: ^0.6.9
|
||||
version: 0.6.9(prettier-plugin-astro@0.14.1)(prettier@3.4.2)
|
||||
sass:
|
||||
specifier: ^1.83.0
|
||||
version: 1.83.0
|
||||
|
||||
packages:
|
||||
|
||||
|
|
@ -2019,6 +2022,9 @@ packages:
|
|||
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
|
||||
engines: {node: '>= 4'}
|
||||
|
||||
immutable@5.0.3:
|
||||
resolution: {integrity: sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==}
|
||||
|
||||
import-fresh@3.3.0:
|
||||
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
|
||||
engines: {node: '>=6'}
|
||||
|
|
@ -3082,6 +3088,11 @@ packages:
|
|||
sass-formatter@0.7.9:
|
||||
resolution: {integrity: sha512-CWZ8XiSim+fJVG0cFLStwDvft1VI7uvXdCNJYXhDvowiv+DsbD1nXLiQ4zrE5UBvj5DWZJ93cwN0NX5PMsr1Pw==}
|
||||
|
||||
sass@1.83.0:
|
||||
resolution: {integrity: sha512-qsSxlayzoOjdvXMVLkzF84DJFc2HZEL/rFyGIKbbilYtAvlCxyuzUeff9LawTn4btVnLKg75Z8MMr1lxU1lfGw==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
hasBin: true
|
||||
|
||||
sax@1.4.1:
|
||||
resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==}
|
||||
|
||||
|
|
@ -3821,12 +3832,12 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@astrojs/mdx@4.0.2(astro@5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(typescript@5.7.2)(yaml@2.6.1))':
|
||||
'@astrojs/mdx@4.0.2(astro@5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(sass@1.83.0)(typescript@5.7.2)(yaml@2.6.1))':
|
||||
dependencies:
|
||||
'@astrojs/markdown-remark': 6.0.1
|
||||
'@mdx-js/mdx': 3.1.0(acorn@8.14.0)
|
||||
acorn: 8.14.0
|
||||
astro: 5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(typescript@5.7.2)(yaml@2.6.1)
|
||||
astro: 5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(sass@1.83.0)(typescript@5.7.2)(yaml@2.6.1)
|
||||
es-module-lexer: 1.5.4
|
||||
estree-util-visit: 2.0.0
|
||||
hast-util-to-html: 9.0.3
|
||||
|
|
@ -3844,15 +3855,15 @@ snapshots:
|
|||
dependencies:
|
||||
prismjs: 1.29.0
|
||||
|
||||
'@astrojs/react@4.1.0(@types/node@22.10.2)(@types/react-dom@18.3.1)(@types/react@18.3.12)(jiti@2.4.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(yaml@2.6.1)':
|
||||
'@astrojs/react@4.1.0(@types/node@22.10.2)(@types/react-dom@18.3.1)(@types/react@18.3.12)(jiti@2.4.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.83.0)(yaml@2.6.1)':
|
||||
dependencies:
|
||||
'@types/react': 18.3.12
|
||||
'@types/react-dom': 18.3.1
|
||||
'@vitejs/plugin-react': 4.3.4(vite@6.0.3(@types/node@22.10.2)(jiti@2.4.2)(yaml@2.6.1))
|
||||
'@vitejs/plugin-react': 4.3.4(vite@6.0.3(@types/node@22.10.2)(jiti@2.4.2)(sass@1.83.0)(yaml@2.6.1))
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
ultrahtml: 1.5.3
|
||||
vite: 6.0.3(@types/node@22.10.2)(jiti@2.4.2)(yaml@2.6.1)
|
||||
vite: 6.0.3(@types/node@22.10.2)(jiti@2.4.2)(sass@1.83.0)(yaml@2.6.1)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- jiti
|
||||
|
|
@ -3878,9 +3889,9 @@ snapshots:
|
|||
stream-replace-string: 2.0.0
|
||||
zod: 3.23.8
|
||||
|
||||
'@astrojs/tailwind@5.1.3(astro@5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(typescript@5.7.2)(yaml@2.6.1))(tailwindcss@3.4.16)':
|
||||
'@astrojs/tailwind@5.1.3(astro@5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(sass@1.83.0)(typescript@5.7.2)(yaml@2.6.1))(tailwindcss@3.4.16)':
|
||||
dependencies:
|
||||
astro: 5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(typescript@5.7.2)(yaml@2.6.1)
|
||||
astro: 5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(sass@1.83.0)(typescript@5.7.2)(yaml@2.6.1)
|
||||
autoprefixer: 10.4.20(postcss@8.4.49)
|
||||
postcss: 8.4.49
|
||||
postcss-load-config: 4.0.2(postcss@8.4.49)
|
||||
|
|
@ -4700,14 +4711,14 @@ snapshots:
|
|||
|
||||
'@ungap/structured-clone@1.2.0': {}
|
||||
|
||||
'@vitejs/plugin-react@4.3.4(vite@6.0.3(@types/node@22.10.2)(jiti@2.4.2)(yaml@2.6.1))':
|
||||
'@vitejs/plugin-react@4.3.4(vite@6.0.3(@types/node@22.10.2)(jiti@2.4.2)(sass@1.83.0)(yaml@2.6.1))':
|
||||
dependencies:
|
||||
'@babel/core': 7.26.0
|
||||
'@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0)
|
||||
'@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0)
|
||||
'@types/babel__core': 7.20.5
|
||||
react-refresh: 0.14.2
|
||||
vite: 6.0.3(@types/node@22.10.2)(jiti@2.4.2)(yaml@2.6.1)
|
||||
vite: 6.0.3(@types/node@22.10.2)(jiti@2.4.2)(sass@1.83.0)(yaml@2.6.1)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
|
|
@ -4884,14 +4895,14 @@ snapshots:
|
|||
- supports-color
|
||||
- typescript
|
||||
|
||||
astro-og-canvas@0.5.5(astro@5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(typescript@5.7.2)(yaml@2.6.1)):
|
||||
astro-og-canvas@0.5.5(astro@5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(sass@1.83.0)(typescript@5.7.2)(yaml@2.6.1)):
|
||||
dependencies:
|
||||
astro: 5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(typescript@5.7.2)(yaml@2.6.1)
|
||||
astro: 5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(sass@1.83.0)(typescript@5.7.2)(yaml@2.6.1)
|
||||
canvaskit-wasm: 0.39.1
|
||||
deterministic-object-hash: 2.0.2
|
||||
entities: 4.5.0
|
||||
|
||||
astro@5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(typescript@5.7.2)(yaml@2.6.1):
|
||||
astro@5.1.0(@types/node@22.10.2)(jiti@2.4.2)(rollup@4.27.4)(sass@1.83.0)(typescript@5.7.2)(yaml@2.6.1):
|
||||
dependencies:
|
||||
'@astrojs/compiler': 2.10.3
|
||||
'@astrojs/internal-helpers': 0.4.2
|
||||
|
|
@ -4943,8 +4954,8 @@ snapshots:
|
|||
unist-util-visit: 5.0.0
|
||||
unstorage: 1.14.1
|
||||
vfile: 6.0.3
|
||||
vite: 6.0.3(@types/node@22.10.2)(jiti@2.4.2)(yaml@2.6.1)
|
||||
vitefu: 1.0.4(vite@6.0.3(@types/node@22.10.2)(jiti@2.4.2)(yaml@2.6.1))
|
||||
vite: 6.0.3(@types/node@22.10.2)(jiti@2.4.2)(sass@1.83.0)(yaml@2.6.1)
|
||||
vitefu: 1.0.4(vite@6.0.3(@types/node@22.10.2)(jiti@2.4.2)(sass@1.83.0)(yaml@2.6.1))
|
||||
which-pm: 3.0.0
|
||||
xxhash-wasm: 1.1.0
|
||||
yargs-parser: 21.1.1
|
||||
|
|
@ -5954,6 +5965,8 @@ snapshots:
|
|||
|
||||
ignore@5.3.2: {}
|
||||
|
||||
immutable@5.0.3: {}
|
||||
|
||||
import-fresh@3.3.0:
|
||||
dependencies:
|
||||
parent-module: 1.0.1
|
||||
|
|
@ -7311,6 +7324,14 @@ snapshots:
|
|||
dependencies:
|
||||
suf-log: 2.5.3
|
||||
|
||||
sass@1.83.0:
|
||||
dependencies:
|
||||
chokidar: 4.0.1
|
||||
immutable: 5.0.3
|
||||
source-map-js: 1.2.1
|
||||
optionalDependencies:
|
||||
'@parcel/watcher': 2.5.0
|
||||
|
||||
sax@1.4.1: {}
|
||||
|
||||
scheduler@0.23.2:
|
||||
|
|
@ -7758,7 +7779,7 @@ snapshots:
|
|||
'@types/unist': 3.0.3
|
||||
vfile-message: 4.0.2
|
||||
|
||||
vite@6.0.3(@types/node@22.10.2)(jiti@2.4.2)(yaml@2.6.1):
|
||||
vite@6.0.3(@types/node@22.10.2)(jiti@2.4.2)(sass@1.83.0)(yaml@2.6.1):
|
||||
dependencies:
|
||||
esbuild: 0.24.0
|
||||
postcss: 8.4.49
|
||||
|
|
@ -7767,11 +7788,12 @@ snapshots:
|
|||
'@types/node': 22.10.2
|
||||
fsevents: 2.3.3
|
||||
jiti: 2.4.2
|
||||
sass: 1.83.0
|
||||
yaml: 2.6.1
|
||||
|
||||
vitefu@1.0.4(vite@6.0.3(@types/node@22.10.2)(jiti@2.4.2)(yaml@2.6.1)):
|
||||
vitefu@1.0.4(vite@6.0.3(@types/node@22.10.2)(jiti@2.4.2)(sass@1.83.0)(yaml@2.6.1)):
|
||||
optionalDependencies:
|
||||
vite: 6.0.3(@types/node@22.10.2)(jiti@2.4.2)(yaml@2.6.1)
|
||||
vite: 6.0.3(@types/node@22.10.2)(jiti@2.4.2)(sass@1.83.0)(yaml@2.6.1)
|
||||
|
||||
volar-service-css@0.0.62(@volar/language-service@2.4.10):
|
||||
dependencies:
|
||||
|
|
|
|||
BIN
public/noise.png
Normal file
BIN
public/noise.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
|
|
@ -1,7 +1,8 @@
|
|||
---
|
||||
import { latestPosts } from "~/config"
|
||||
import { getLangFromUrl, useTranslations } from "~/i18n/utils"
|
||||
import { formatDate, getPostsByLocale } from "~/utils"
|
||||
import { getPostsByLocale } from "~/utils"
|
||||
import PostList from "./post-list.astro"
|
||||
|
||||
const lang = getLangFromUrl(Astro.url)
|
||||
const t = useTranslations(lang)
|
||||
|
|
@ -13,13 +14,11 @@ const posts = allPosts.slice(0, latestPosts)
|
|||
<div class="my-8 text-xl font-medium md:my-8">{t("blog.latest")}</div>
|
||||
{
|
||||
posts.map((post: any) => (
|
||||
<a href={`/${lang}/posts/${post.id}/`} class="visited:text-purple-500/90">
|
||||
<div class="my-2 flex text-lg">
|
||||
<p class="flex w-36 flex-shrink-0 truncate text-gray-500 dark:text-gray-400">
|
||||
<time>{formatDate(post.data.pubDate)}</time>
|
||||
</p>
|
||||
<p class="line-clamp-2">{post.data.title}</p>
|
||||
</div>
|
||||
</a>
|
||||
<PostList
|
||||
post={post}
|
||||
lang={lang}
|
||||
dateFormat="YYYY-MM-DD"
|
||||
dateWidth="w-32"
|
||||
/>
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,16 @@
|
|||
const currentYear = new Date().getFullYear()
|
||||
---
|
||||
|
||||
<footer class="my-10 flex flex-wrap items-center gap-1">
|
||||
<footer class="relative z-10 my-10 flex flex-wrap items-center gap-1">
|
||||
<p>© {currentYear}</p>
|
||||
|
||||
{
|
||||
[
|
||||
{ text: "Designed By", link: "https://sunguoqi.com", label: "Guoqi Sun" },
|
||||
{
|
||||
text: "Designed By",
|
||||
link: "https://sunguoqi.com",
|
||||
label: "Guoqi Sun",
|
||||
},
|
||||
{
|
||||
text: "Powered By",
|
||||
link: "https://github.com/sun0225SUN/astro-air",
|
||||
|
|
|
|||
|
|
@ -7,6 +7,6 @@ const lang = getLangFromUrl(Astro.url)
|
|||
const IntroContent = lang === "zh" ? IntroContentZh : IntroContentEn
|
||||
---
|
||||
|
||||
<div class="my-10">
|
||||
<div class="relative z-10 my-10">
|
||||
<IntroContent />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { getLangFromUrl, useTranslations } from "~/i18n/utils"
|
|||
const lang = getLangFromUrl(Astro.url)
|
||||
const t = useTranslations(lang)
|
||||
|
||||
const { home, archive, tags, custom, about } =
|
||||
const { home, archive, custom, about } =
|
||||
lang === "zh" ? zh.navigation : en.navigation
|
||||
---
|
||||
|
||||
|
|
@ -27,16 +27,6 @@ const { home, archive, tags, custom, about } =
|
|||
</a>
|
||||
)
|
||||
}
|
||||
{
|
||||
tags && (
|
||||
<a
|
||||
href={`/${lang}/tags`}
|
||||
class="hover:underline hover:underline-offset-4"
|
||||
>
|
||||
<p>{t("nav.tags")}</p>
|
||||
</a>
|
||||
)
|
||||
}
|
||||
{
|
||||
custom?.map((tab) => (
|
||||
<a
|
||||
|
|
|
|||
23
src/components/astro/post-list.astro
Normal file
23
src/components/astro/post-list.astro
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
interface Props {
|
||||
post: any
|
||||
lang: string
|
||||
dateFormat?: string
|
||||
dateWidth?: string
|
||||
}
|
||||
|
||||
const { post, lang, dateFormat = "default", dateWidth = "w-36" } = Astro.props
|
||||
import { formatDate } from "~/utils"
|
||||
---
|
||||
|
||||
<a
|
||||
href={`/${lang}/posts/${post.id}/`}
|
||||
class="my-3 flex visited:text-purple-500/90 md:my-2"
|
||||
>
|
||||
<p
|
||||
class={`flex ${dateWidth} flex-shrink-0 truncate text-gray-500 dark:text-gray-400`}
|
||||
>
|
||||
<time>{formatDate(post.data.pubDate, dateFormat)}</time>
|
||||
</p>
|
||||
<p class="line-clamp-2 text-lg hover:underline">{post.data.title}</p>
|
||||
</a>
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
import { getLangFromUrl, useTranslations } from "~/i18n/utils"
|
||||
import MainLayout from "~/layouts/main.astro"
|
||||
import { formatDate } from "~/utils"
|
||||
import PostList from "./post-list.astro"
|
||||
|
||||
interface Props {
|
||||
posts: any[]
|
||||
|
|
@ -17,30 +17,24 @@ const filteredPosts = posts.filter((post: any) => post.data.tags?.includes(tag))
|
|||
---
|
||||
|
||||
<MainLayout>
|
||||
<div class="mb-4 mt-2 text-2xl">
|
||||
{tag}
|
||||
</div>
|
||||
<div class="relative z-10">
|
||||
<div class="my-9 mt-2 text-2xl font-semibold">#{tag}</div>
|
||||
|
||||
{
|
||||
filteredPosts.length > 0 ? (
|
||||
<ul class="space-y-4">
|
||||
{filteredPosts.map((post: any) => (
|
||||
<li>
|
||||
<a
|
||||
href={`/${lang}/posts/${post.id}/`}
|
||||
class="block rounded-lg p-2 transition-colors hover:bg-gray-100 dark:hover:bg-gray-800"
|
||||
>
|
||||
<div class="flex items-center text-lg">
|
||||
<p class="mr-4 w-36 flex-shrink-0 truncate text-gray-500 dark:text-gray-400">
|
||||
<time>{formatDate(post.data.pubDate)}</time>
|
||||
</p>
|
||||
<p class="line-clamp-2 flex-grow">{post.data.title}</p>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<PostList
|
||||
post={post}
|
||||
lang={lang}
|
||||
dateFormat="YYYY-MM-DD"
|
||||
dateWidth="w-32"
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
) : (
|
||||
<p class="text-gray-500">{t("tag.no_posts")}</p>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</MainLayout>
|
||||
|
|
|
|||
74
src/components/react/code-background.tsx
Normal file
74
src/components/react/code-background.tsx
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
import { useEffect, useState } from "react"
|
||||
|
||||
export function CodeBackground() {
|
||||
const charGroups = {
|
||||
brackets: {
|
||||
chars: ["{", "}", "(", ")", "[", "]", "<", ">"],
|
||||
weight: 3,
|
||||
},
|
||||
operators: {
|
||||
chars: ["=", "+", "-", "*", "/", "%", "=>", "&&", "||", "|", "&", "..."],
|
||||
weight: 2,
|
||||
},
|
||||
punctuation: {
|
||||
chars: [".", ";", ":", ","],
|
||||
weight: 4,
|
||||
},
|
||||
keywords: {
|
||||
chars: [
|
||||
"const",
|
||||
"let",
|
||||
"var",
|
||||
"function",
|
||||
"if",
|
||||
"else",
|
||||
"return",
|
||||
"class",
|
||||
"import",
|
||||
"export",
|
||||
"from",
|
||||
"async",
|
||||
"await",
|
||||
"try",
|
||||
"catch",
|
||||
"interface",
|
||||
"type",
|
||||
"extends",
|
||||
"implements",
|
||||
],
|
||||
weight: 1,
|
||||
},
|
||||
values: {
|
||||
chars: ["null", "undefined", "true", "false", "void", "any", "never"],
|
||||
weight: 1,
|
||||
},
|
||||
}
|
||||
|
||||
const [backgroundChars, setBackgroundChars] = useState<string[]>([])
|
||||
|
||||
useEffect(() => {
|
||||
const getWeightedRandomChar = () => {
|
||||
const weightedChars = Object.values(charGroups).reduce((acc, group) => {
|
||||
const chars = Array(group.weight).fill(group.chars).flat()
|
||||
return [...acc, ...chars]
|
||||
}, [] as string[])
|
||||
return weightedChars[Math.floor(Math.random() * weightedChars.length)]
|
||||
}
|
||||
|
||||
const chars = new Array(2000).fill(null).map(() => getWeightedRandomChar())
|
||||
setBackgroundChars(chars)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-0 flex h-screen w-screen select-none flex-wrap overflow-hidden">
|
||||
{backgroundChars.map((char, index) => (
|
||||
<span
|
||||
key={index}
|
||||
className="px-1 text-sm text-transparent duration-[0.8s] hover:text-black/50 hover:duration-0 dark:hover:text-white/50"
|
||||
>
|
||||
{char}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
export function NoiseBackground() {
|
||||
return (
|
||||
<div className="fixed inset-0 -z-10 h-full w-full bg-[url('https://framerusercontent.com/images/rR6HYXBrMmX4cRpXfXUOvpvpB0.png')] bg-[length:128px_128px] bg-repeat opacity-[0.06]"></div>
|
||||
<div className="fixed inset-0 z-[-1] h-full w-full bg-[url('/noise.png')] bg-[length:128px_128px] bg-repeat opacity-[0.06]"></div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
export const title = "About Me"
|
||||
|
||||
## {title}
|
||||
{title}
|
||||
|
||||
<img
|
||||
className="block dark:hidden"
|
||||
|
|
|
|||
|
|
@ -25,14 +25,13 @@ const common = {
|
|||
navigation: {
|
||||
home: true,
|
||||
archive: true,
|
||||
tags: true,
|
||||
about: true,
|
||||
custom: [
|
||||
{
|
||||
label: "CamLife",
|
||||
link: "https://camlife.cn",
|
||||
},
|
||||
],
|
||||
about: true,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
export const title = "关于我"
|
||||
|
||||
## {title}
|
||||
{title}
|
||||
|
||||
<img
|
||||
className="block dark:hidden"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: "我的第一篇博客文章"
|
||||
pubDate: 2020-07-01
|
||||
updatedDate: 2020-07-01
|
||||
description: "这是我 Astro 博客的第一篇文章。"
|
||||
author: "Astro 学习者"
|
||||
image:
|
||||
|
|
@ -22,3 +23,7 @@ tags: ["astro", "博客", "公开学习"]
|
|||
## 下一步计划
|
||||
|
||||
我将完成 Astro 教程,然后继续编写更多内容。关注我以获取更多信息。
|
||||
|
||||
```python
|
||||
print("Hello, World!")
|
||||
```
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ description: "全面指南,帮助您将 Astro 网站部署到各种平台"
|
|||
image:
|
||||
url: "https://docs.astro.build/assets/arc.webp"
|
||||
alt: "Astro 部署插图"
|
||||
pubDate: 2024-08-19
|
||||
pubDate: 2024-08-26
|
||||
tags: ["astro", "i18n", "本地化", "网页开发"]
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ export const ui = {
|
|||
en: {
|
||||
"nav.home": "Home",
|
||||
"nav.archive": "Archive",
|
||||
"nav.tags": "Tags",
|
||||
"nav.about": "About",
|
||||
"nav.twitter": "Twitter",
|
||||
"blog.latest": "Latest Posts",
|
||||
"archive.title": "All Posts",
|
||||
"tag.title": "Tag:",
|
||||
"tag.no_posts": "No posts found for tag",
|
||||
},
|
||||
|
|
@ -23,8 +23,8 @@ export const ui = {
|
|||
"nav.about": "关于",
|
||||
"nav.blog": "推特",
|
||||
"nav.archive": "归档",
|
||||
"nav.tags": "标签",
|
||||
"blog.latest": "最近文章",
|
||||
"blog.latest": "近期文章",
|
||||
"archive.title": "所有文章",
|
||||
"tag.title": "标签:",
|
||||
"tag.no_posts": "没有找到标签为的文章",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
import "~/styles/globals.css"
|
||||
import { NoiseBackground } from "~/components/react/noise-background"
|
||||
import { CodeBackground } from "~/components/react/code-background"
|
||||
import { ClientRouter } from "astro:transitions"
|
||||
import { getLangFromUrl } from "~/i18n/utils"
|
||||
import { en, zh } from "~/config"
|
||||
|
|
@ -71,10 +72,11 @@ const config = lang === "zh" ? zh.meta : en.meta
|
|||
})
|
||||
</script>
|
||||
</head>
|
||||
<body class="dark:bg-[#121212] dark:text-white">
|
||||
<div class="flex min-h-screen w-full justify-center px-6 md:p-0">
|
||||
<body
|
||||
class="flex min-h-screen w-full justify-center px-6 dark:bg-[#121212] dark:text-white md:px-0"
|
||||
>
|
||||
<slot />
|
||||
<NoiseBackground />
|
||||
</div>
|
||||
<CodeBackground client:load />
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -10,8 +10,10 @@ const openGraphImage = !ogImage ? `/og/${filename}.png` : ogImage
|
|||
|
||||
<BaseLayout title={title} description={description} ogImage={openGraphImage}>
|
||||
<main class="max-auto mb-10 w-full max-w-3xl">
|
||||
<div class="relative z-10">
|
||||
<Header />
|
||||
<Navigation />
|
||||
<slot />
|
||||
</div>
|
||||
</main>
|
||||
</BaseLayout>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ const ogImage = "https://sunguoqi.com/me.png"
|
|||
---
|
||||
|
||||
<MainLayout title="about" description="test" ogImage={ogImage}>
|
||||
<div class="prose dark:prose-invert">
|
||||
<div class="prose relative z-10 dark:prose-invert">
|
||||
<AboutContent />
|
||||
</div>
|
||||
</MainLayout>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
---
|
||||
import PostList from "~/components/astro/post-list.astro"
|
||||
import { getLangFromUrl } from "~/i18n/utils"
|
||||
import MainLayout from "~/layouts/main.astro"
|
||||
import { formatDate, getPostsByLocale } from "~/utils"
|
||||
import { getPostsByLocale } from "~/utils"
|
||||
import { getLanguagePaths } from "~/utils/langs"
|
||||
|
||||
const lang = getLangFromUrl(Astro.url)
|
||||
|
||||
export function getStaticPaths() {
|
||||
return getLanguagePaths()
|
||||
}
|
||||
|
||||
const lang = getLangFromUrl(Astro.url)
|
||||
|
||||
const posts = await getPostsByLocale(lang)
|
||||
|
||||
const postsByYear = posts.reduce(
|
||||
|
|
@ -28,24 +29,20 @@ const years = Object.keys(postsByYear).sort((a, b) => Number(b) - Number(a))
|
|||
---
|
||||
|
||||
<MainLayout>
|
||||
<div class="space-y-8">
|
||||
<div class="relative z-10">
|
||||
{
|
||||
years.map((year) => (
|
||||
<div class="year-group">
|
||||
<h2 class="mb-4 text-2xl font-bold">{year}</h2>
|
||||
<div class="space-y-2">
|
||||
<div class="year-group my-8">
|
||||
<h2 class="my-4 text-2xl font-bold">{year}</h2>
|
||||
{postsByYear[year].map((post: any) => (
|
||||
<a href={`/${lang}/posts/${post.id}/`}>
|
||||
<div class="my-2 flex text-lg">
|
||||
<p class="flex w-36 flex-shrink-0 truncate text-gray-500 dark:text-gray-400">
|
||||
<time>{formatDate(post.data.pubDate)}</time>
|
||||
</p>
|
||||
<p class="line-clamp-2">{post.data.title}</p>
|
||||
</div>
|
||||
</a>
|
||||
<PostList
|
||||
post={post}
|
||||
lang={lang}
|
||||
dateFormat="MM-DD"
|
||||
dateWidth="w-20"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
---
|
||||
import { langs } from "~/i18n/ui"
|
||||
import { getLangFromUrl } from "~/i18n/utils"
|
||||
import MainLayout from "~/layouts/main.astro"
|
||||
import "~/styles/post.css"
|
||||
import { getPostsByLocale } from "~/utils"
|
||||
import "~/styles/post.scss"
|
||||
import { formatDate, getPostsByLocale } from "~/utils"
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const allPaths = []
|
||||
|
|
@ -19,11 +21,30 @@ export async function getStaticPaths() {
|
|||
return allPaths
|
||||
}
|
||||
|
||||
const lang = getLangFromUrl(Astro.url)
|
||||
|
||||
const { post } = Astro.props
|
||||
---
|
||||
|
||||
<MainLayout {...post.data}>
|
||||
<article class="prose dark:prose-invert">
|
||||
<div set:html={post.rendered.html} />
|
||||
<article class="prose relative z-10 w-full max-w-full dark:prose-invert">
|
||||
<div class="flex flex-col gap-2">
|
||||
<h2 class="!my-0 text-3xl font-semibold">{post.data.title}</h2>
|
||||
<div class="my-3 text-gray-500 dark:text-white/80">
|
||||
{formatDate(post.data.pubDate)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-6" set:html={post.rendered.html} />
|
||||
|
||||
<div class="space-x-3 pb-10 text-sm text-gray-500">
|
||||
{
|
||||
post.data.tags.map((tag: string) => (
|
||||
<a href={`/${lang}/tags/${tag}`} class="no-underline">
|
||||
<p class="inline-block hover:scale-105">#{tag}</p>
|
||||
</a>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</article>
|
||||
</MainLayout>
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
---
|
||||
import { getLangFromUrl } from "~/i18n/utils"
|
||||
import MainLayout from "~/layouts/main.astro"
|
||||
import { getPostsByLocale } from "~/utils"
|
||||
import { getLanguagePaths } from "~/utils/langs"
|
||||
|
||||
export function getStaticPaths() {
|
||||
return getLanguagePaths()
|
||||
}
|
||||
|
||||
const lang = getLangFromUrl(Astro.url)
|
||||
const posts = await getPostsByLocale(lang)
|
||||
const tags = [...new Set(posts.map((post: any) => post.data.tags).flat())]
|
||||
---
|
||||
|
||||
<MainLayout>
|
||||
<div>
|
||||
{
|
||||
tags.map((tag) => (
|
||||
<span class="mx-4">
|
||||
<a href={`/${lang}/tags/${tag}`}>{tag}</a>
|
||||
</span>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</MainLayout>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
article code {
|
||||
@apply rounded bg-gray-100 px-1 dark:bg-gray-900;
|
||||
@apply rounded bg-orange-500/50 px-1 dark:bg-orange-500/80;
|
||||
}
|
||||
|
||||
article code::before,
|
||||
|
|
|
|||
5
src/styles/post.scss
Normal file
5
src/styles/post.scss
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
article {
|
||||
h2 {
|
||||
margin: 2rem 0 !important;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,21 @@
|
|||
import { getCollection } from "astro:content"
|
||||
|
||||
export const formatDate = (date: Date | string | undefined): string => {
|
||||
export const formatDate = (
|
||||
date: Date | string | undefined,
|
||||
format: string = "YYYY-MM-DD",
|
||||
): string => {
|
||||
const validDate = date ? new Date(date) : new Date()
|
||||
|
||||
const year = validDate.getFullYear()
|
||||
const month = String(validDate.getMonth() + 1).padStart(2, "0")
|
||||
const day = String(validDate.getDate()).padStart(2, "0")
|
||||
const tokens: Record<string, string> = {
|
||||
YYYY: validDate.getFullYear().toString(),
|
||||
MM: String(validDate.getMonth() + 1).padStart(2, "0"),
|
||||
DD: String(validDate.getDate()).padStart(2, "0"),
|
||||
HH: String(validDate.getHours()).padStart(2, "0"),
|
||||
mm: String(validDate.getMinutes()).padStart(2, "0"),
|
||||
ss: String(validDate.getSeconds()).padStart(2, "0"),
|
||||
}
|
||||
|
||||
return `${year}-${month}-${day}`
|
||||
return format.replace(/YYYY|MM|DD|HH|mm|ss/g, (match) => tokens[match])
|
||||
}
|
||||
|
||||
export const getPostsByLocale = async (locale: string) => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue