主页框架
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-03-31 22:54:14 +08:00
parent 36a6ff369d
commit a87c6faa1e
11 changed files with 1267 additions and 20 deletions

View File

@ -9,11 +9,13 @@ import vue from '@astrojs/vue';
import react from '@astrojs/react';
import icon from 'astro-icon';
// https://astro.build/config
export default defineConfig({
adapter: node({
mode: 'standalone',
}),
integrations: [svelte(), vue(), react()],
integrations: [svelte(), vue(), react(), icon()],
})

600
package-lock.json generated
View File

@ -11,11 +11,14 @@
"@astrojs/react": "^5.0.2",
"@astrojs/svelte": "^8.0.4",
"@astrojs/vue": "^6.0.1",
"@iconify-json/mdi": "^1.2.3",
"@markdoc/markdoc": "^0.5.7",
"@traptitech/markdown-it-katex": "^3.6.0",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@unocss/reset": "^66.6.7",
"astro": "^6.1.0",
"astro-icon": "^1.1.5",
"axios": "^1.13.6",
"katex": "^0.16.43",
"markdown-it": "^14.1.1",
@ -38,6 +41,28 @@
"node": ">=22.12.0"
}
},
"node_modules/@antfu/install-pkg": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz",
"integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==",
"license": "MIT",
"dependencies": {
"package-manager-detector": "^1.3.0",
"tinyexec": "^1.0.1"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@antfu/utils": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-8.1.1.tgz",
"integrity": "sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@astrojs/compiler": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-3.0.1.tgz",
@ -1298,6 +1323,107 @@
"url": "https://github.com/sponsors/nzakas"
}
},
"node_modules/@iconify-json/mdi": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@iconify-json/mdi/-/mdi-1.2.3.tgz",
"integrity": "sha512-O3cLwbDOK7NNDf2ihaQOH5F9JglnulNDFV7WprU2dSoZu3h3cWH//h74uQAB87brHmvFVxIOkuBX2sZSzYhScg==",
"license": "Apache-2.0",
"dependencies": {
"@iconify/types": "*"
}
},
"node_modules/@iconify/tools": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/@iconify/tools/-/tools-4.2.0.tgz",
"integrity": "sha512-WRxPva/ipxYkqZd1+CkEAQmd86dQmrwH0vwK89gmp2Kh2WyyVw57XbPng0NehP3x4V1LzLsXUneP1uMfTMZmUA==",
"license": "MIT",
"dependencies": {
"@iconify/types": "^2.0.0",
"@iconify/utils": "^2.3.0",
"cheerio": "^1.1.2",
"domhandler": "^5.0.3",
"extract-zip": "^2.0.1",
"local-pkg": "^1.1.2",
"pathe": "^2.0.3",
"svgo": "^3.3.2",
"tar": "^7.5.2"
}
},
"node_modules/@iconify/tools/node_modules/commander": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
"license": "MIT",
"engines": {
"node": ">= 10"
}
},
"node_modules/@iconify/tools/node_modules/css-tree": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
"integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
"license": "MIT",
"dependencies": {
"mdn-data": "2.0.30",
"source-map-js": "^1.0.1"
},
"engines": {
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
}
},
"node_modules/@iconify/tools/node_modules/mdn-data": {
"version": "2.0.30",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==",
"license": "CC0-1.0"
},
"node_modules/@iconify/tools/node_modules/svgo": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.3.tgz",
"integrity": "sha512-+wn7I4p7YgJhHs38k2TNjy1vCfPIfLIJWR5MnCStsN8WuuTcBnRKcMHQLMM2ijxGZmDoZwNv8ipl5aTTen62ng==",
"license": "MIT",
"dependencies": {
"commander": "^7.2.0",
"css-select": "^5.1.0",
"css-tree": "^2.3.1",
"css-what": "^6.1.0",
"csso": "^5.0.5",
"picocolors": "^1.0.0",
"sax": "^1.5.0"
},
"bin": {
"svgo": "bin/svgo"
},
"engines": {
"node": ">=14.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/svgo"
}
},
"node_modules/@iconify/types": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
"integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==",
"license": "MIT"
},
"node_modules/@iconify/utils": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.3.0.tgz",
"integrity": "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==",
"license": "MIT",
"dependencies": {
"@antfu/install-pkg": "^1.0.0",
"@antfu/utils": "^8.1.0",
"@iconify/types": "^2.0.0",
"debug": "^4.4.0",
"globals": "^15.14.0",
"kolorist": "^1.8.0",
"local-pkg": "^1.0.0",
"mlly": "^1.7.4"
}
},
"node_modules/@img/colour": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz",
@ -1764,6 +1890,18 @@
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@isaacs/fs-minipass": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
"integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
"license": "ISC",
"dependencies": {
"minipass": "^7.0.4"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
@ -2551,6 +2689,16 @@
"@types/unist": "*"
}
},
"node_modules/@types/node": {
"version": "25.5.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz",
"integrity": "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==",
"license": "MIT",
"optional": true,
"dependencies": {
"undici-types": "~7.18.0"
}
},
"node_modules/@types/react": {
"version": "19.2.14",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
@ -2581,6 +2729,16 @@
"integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
"license": "MIT"
},
"node_modules/@types/yauzl": {
"version": "2.10.3",
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
"integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
"license": "MIT",
"optional": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@typescript-eslint/parser": {
"version": "8.57.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.57.2.tgz",
@ -2728,6 +2886,15 @@
"integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
"license": "ISC"
},
"node_modules/@unocss/reset": {
"version": "66.6.7",
"resolved": "https://registry.npmjs.org/@unocss/reset/-/reset-66.6.7.tgz",
"integrity": "sha512-+OjpLDEaPmhTQ3Gj7EaKApNM92TM9f9gLgHNa79+66wIll9IfhKfEmJXnF9y1SE725n4PmPIQgC9k313HztMLA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vitejs/plugin-react": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz",
@ -3212,6 +3379,17 @@
"url": "https://opencollective.com/eslint"
}
},
"node_modules/astro-icon": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/astro-icon/-/astro-icon-1.1.5.tgz",
"integrity": "sha512-CJYS5nWOw9jz4RpGWmzNQY7D0y2ZZacH7atL2K9DeJXJVaz7/5WrxeyIxO8KASk1jCM96Q4LjRx/F3R+InjJrw==",
"license": "MIT",
"dependencies": {
"@iconify/tools": "^4.0.5",
"@iconify/types": "^2.0.0",
"@iconify/utils": "^2.1.30"
}
},
"node_modules/astrojs-compiler-sync": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/astrojs-compiler-sync/-/astrojs-compiler-sync-1.1.1.tgz",
@ -3363,6 +3541,15 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
"node_modules/buffer-crc32": {
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
"license": "MIT",
"engines": {
"node": "*"
}
},
"node_modules/bundle-name": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz",
@ -3451,6 +3638,48 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/cheerio": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz",
"integrity": "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==",
"license": "MIT",
"dependencies": {
"cheerio-select": "^2.1.0",
"dom-serializer": "^2.0.0",
"domhandler": "^5.0.3",
"domutils": "^3.2.2",
"encoding-sniffer": "^0.2.1",
"htmlparser2": "^10.1.0",
"parse5": "^7.3.0",
"parse5-htmlparser2-tree-adapter": "^7.1.0",
"parse5-parser-stream": "^7.1.2",
"undici": "^7.19.0",
"whatwg-mimetype": "^4.0.0"
},
"engines": {
"node": ">=20.18.1"
},
"funding": {
"url": "https://github.com/cheeriojs/cheerio?sponsor=1"
}
},
"node_modules/cheerio-select": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
"integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
"license": "BSD-2-Clause",
"dependencies": {
"boolbase": "^1.0.0",
"css-select": "^5.1.0",
"css-what": "^6.1.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
"domutils": "^3.0.1"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/chokidar": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz",
@ -3466,6 +3695,15 @@
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/chownr": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
"integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=18"
}
},
"node_modules/ci-info": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz",
@ -3530,6 +3768,12 @@
"node": ">= 18"
}
},
"node_modules/confbox": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.4.tgz",
"integrity": "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==",
"license": "MIT"
},
"node_modules/convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
@ -3958,6 +4202,28 @@
"node": ">= 0.8"
}
},
"node_modules/encoding-sniffer": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz",
"integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==",
"license": "MIT",
"dependencies": {
"iconv-lite": "^0.6.3",
"whatwg-encoding": "^3.1.1"
},
"funding": {
"url": "https://github.com/fb55/encoding-sniffer?sponsor=1"
}
},
"node_modules/end-of-stream": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
"integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
"license": "MIT",
"dependencies": {
"once": "^1.4.0"
}
},
"node_modules/entities": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
@ -4403,12 +4669,38 @@
"integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==",
"license": "MIT"
},
"node_modules/exsolve": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.8.tgz",
"integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==",
"license": "MIT"
},
"node_modules/extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
"license": "MIT"
},
"node_modules/extract-zip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
"integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
"license": "BSD-2-Clause",
"dependencies": {
"debug": "^4.1.1",
"get-stream": "^5.1.0",
"yauzl": "^2.10.0"
},
"bin": {
"extract-zip": "cli.js"
},
"engines": {
"node": ">= 10.17.0"
},
"optionalDependencies": {
"@types/yauzl": "^2.9.1"
}
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@ -4470,6 +4762,15 @@
"reusify": "^1.0.4"
}
},
"node_modules/fd-slicer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
"integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
"license": "MIT",
"dependencies": {
"pend": "~1.2.0"
}
},
"node_modules/fdir": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
@ -4716,6 +5017,21 @@
"node": ">= 0.4"
}
},
"node_modules/get-stream": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
"license": "MIT",
"dependencies": {
"pump": "^3.0.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/github-slugger": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz",
@ -4735,6 +5051,18 @@
"node": ">=10.13.0"
}
},
"node_modules/globals": {
"version": "15.15.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz",
"integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@ -5002,6 +5330,37 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/htmlparser2": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz",
"integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==",
"funding": [
"https://github.com/fb55/htmlparser2?sponsor=1",
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
],
"license": "MIT",
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
"domutils": "^3.2.2",
"entities": "^7.0.1"
}
},
"node_modules/htmlparser2/node_modules/entities": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
"integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/http-cache-semantics": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
@ -5028,6 +5387,18 @@
"url": "https://opencollective.com/express"
}
},
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@ -5299,6 +5670,23 @@
"uc.micro": "^2.0.0"
}
},
"node_modules/local-pkg": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.2.tgz",
"integrity": "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==",
"license": "MIT",
"dependencies": {
"mlly": "^1.7.4",
"pkg-types": "^2.3.0",
"quansync": "^0.2.11"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/locate-character": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
@ -6286,6 +6674,56 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/minipass": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
"integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/minizlib": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz",
"integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==",
"license": "MIT",
"dependencies": {
"minipass": "^7.1.2"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/mlly": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz",
"integrity": "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==",
"license": "MIT",
"dependencies": {
"acorn": "^8.16.0",
"pathe": "^2.0.3",
"pkg-types": "^1.3.1",
"ufo": "^1.6.3"
}
},
"node_modules/mlly/node_modules/confbox": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz",
"integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==",
"license": "MIT"
},
"node_modules/mlly/node_modules/pkg-types": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz",
"integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==",
"license": "MIT",
"dependencies": {
"confbox": "^0.1.8",
"mlly": "^1.7.4",
"pathe": "^2.0.1"
}
},
"node_modules/mrmime": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
@ -6426,6 +6864,15 @@
"node": ">= 0.8"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"license": "ISC",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/oniguruma-parser": {
"version": "0.12.1",
"resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz",
@ -6603,6 +7050,31 @@
"url": "https://github.com/inikulin/parse5?sponsor=1"
}
},
"node_modules/parse5-htmlparser2-tree-adapter": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz",
"integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==",
"license": "MIT",
"dependencies": {
"domhandler": "^5.0.3",
"parse5": "^7.0.0"
},
"funding": {
"url": "https://github.com/inikulin/parse5?sponsor=1"
}
},
"node_modules/parse5-parser-stream": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz",
"integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==",
"license": "MIT",
"dependencies": {
"parse5": "^7.0.0"
},
"funding": {
"url": "https://github.com/inikulin/parse5?sponsor=1"
}
},
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@ -6629,6 +7101,12 @@
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
"license": "MIT"
},
"node_modules/pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
"license": "MIT"
},
"node_modules/perfect-debounce": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.1.0.tgz",
@ -6659,6 +7137,17 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/pkg-types": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz",
"integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==",
"license": "MIT",
"dependencies": {
"confbox": "^0.2.2",
"exsolve": "^1.0.7",
"pathe": "^2.0.3"
}
},
"node_modules/postcss": {
"version": "8.5.8",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
@ -6774,6 +7263,16 @@
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"license": "MIT"
},
"node_modules/pump": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz",
"integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==",
"license": "MIT",
"dependencies": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
@ -6793,6 +7292,22 @@
"node": ">=6"
}
},
"node_modules/quansync": {
"version": "0.2.11",
"resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz",
"integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/antfu"
},
{
"type": "individual",
"url": "https://github.com/sponsors/sxzz"
}
],
"license": "MIT"
},
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@ -7197,6 +7712,12 @@
"dev": true,
"license": "MIT"
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
"node_modules/sass-formatter": {
"version": "0.7.9",
"resolved": "https://registry.npmjs.org/sass-formatter/-/sass-formatter-0.7.9.tgz",
@ -7540,6 +8061,31 @@
"url": "https://opencollective.com/synckit"
}
},
"node_modules/tar": {
"version": "7.5.13",
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.13.tgz",
"integrity": "sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng==",
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/fs-minipass": "^4.0.0",
"chownr": "^3.0.0",
"minipass": "^7.1.2",
"minizlib": "^3.1.0",
"yallist": "^5.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/tar/node_modules/yallist": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
"integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=18"
}
},
"node_modules/tiny-inflate": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
@ -7721,6 +8267,22 @@
"integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==",
"license": "MIT"
},
"node_modules/undici": {
"version": "7.24.6",
"resolved": "https://registry.npmjs.org/undici/-/undici-7.24.6.tgz",
"integrity": "sha512-Xi4agocCbRzt0yYMZGMA6ApD7gvtUFaxm4ZmeacWI4cZxaF6C+8I8QfofC20NAePiB/IcvZmzkJ7XPa471AEtA==",
"license": "MIT",
"engines": {
"node": ">=20.18.1"
}
},
"node_modules/undici-types": {
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
"license": "MIT",
"optional": true
},
"node_modules/unified": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz",
@ -8348,6 +8910,28 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/whatwg-encoding": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
"integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
"deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation",
"license": "MIT",
"dependencies": {
"iconv-lite": "0.6.3"
},
"engines": {
"node": ">=18"
}
},
"node_modules/whatwg-mimetype": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
"integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@ -8383,6 +8967,12 @@
"node": ">=0.10.0"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"license": "ISC"
},
"node_modules/wsl-utils": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz",
@ -8419,6 +9009,16 @@
"node": "^20.19.0 || ^22.12.0 || >=23"
}
},
"node_modules/yauzl": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
"integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
"license": "MIT",
"dependencies": {
"buffer-crc32": "~0.2.3",
"fd-slicer": "~1.1.0"
}
},
"node_modules/yocto-queue": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz",

View File

@ -16,11 +16,14 @@
"@astrojs/react": "^5.0.2",
"@astrojs/svelte": "^8.0.4",
"@astrojs/vue": "^6.0.1",
"@iconify-json/mdi": "^1.2.3",
"@markdoc/markdoc": "^0.5.7",
"@traptitech/markdown-it-katex": "^3.6.0",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@unocss/reset": "^66.6.7",
"astro": "^6.1.0",
"astro-icon": "^1.1.5",
"axios": "^1.13.6",
"katex": "^0.16.43",
"markdown-it": "^14.1.1",

View File

@ -7,13 +7,21 @@
:root {
color-scheme: light dark;
--color-bg-n: light-dark(oklch(100% 0 0), oklch(35% 0.02 270));
--color-bg-0: light-dark(oklch(95% 0 0), oklch(30% 0.02 270));
--color-fg-0: light-dark(oklch(25% 0.02 270), oklch(90% 0.02 270));
--color-bg-1: light-dark(oklch(90% 0 0), oklch(25% 0.02 270));
--color-link: light-dark(oklch(40% 0.2 270), oklch(80% 0.2 270));
--color-blue: light-dark(oklch(40% 0.2 270), oklch(80% 0.2 270));
--color-green: light-dark(oklch(50% 0.1 150), oklch(80% 0.15 150));
--color-link: var(--color-blue);
}
/* == 页面设置 == */
html {
scroll-behavior: smooth;
}
html,
body {
margin: 0;

View File

@ -52,4 +52,46 @@
}
</script>
<button onclick={click}>没用的按钮 | {clicks + clicksPending}</button>
<button class="useless-button" onclick={click}>
<span class="name">到此一游</span>
<span class="number">{clicks + clicksPending}</span>
</button>
<style>
.useless-button {
display: block;
background-color: var(--color-bg-n);
font-size: 1.25rem;
cursor: pointer;
border-radius: 1rem;
overflow: hidden;
transition: transform ease 0.1s;
&:hover {
transform: scale(1.02);
}
&:active {
transform: scale(0.97);
}
& > .name {
display: inline-block;
font-weight: 300;
padding-inline-start: 1rem;
padding-inline-end: 0.5rem;
padding-block: 0.5rem;
}
& > .number {
display: inline-block;
padding-inline-start: 0.75rem;
padding-inline-end: 0.75rem;
padding-block: 0.5rem;
background-color: var(--color-green);
color: var(--color-bg-n);
font-weight: 600;
}
}
</style>

View File

@ -0,0 +1,244 @@
<script lang="ts">
import { onMount } from 'svelte'
// 基础定义部分
type WriterStage = { text: string; editing: string[] } | string
type WriterWord = { stages: WriterStage[] }
// 辅助函数
const typeCharacters = (base: string, chars: string) => [
base,
...chars.split('').map((_, i) => base + chars.slice(0, i + 1)),
]
const words: WriterWord[] = [
{
stages: [
{ text: '', editing: ['x', 'xi', 'xih', "xi'hr"] },
{ text: '喜欢', editing: ['y', 'yb', 'ybl'] },
...typeCharacters('喜欢音', 'MAD'),
],
},
{
stages: [
{ text: '', editing: ['x', 'xi', 'xih', "xi'hr"] },
...typeCharacters('喜欢', 'YTPMV'),
],
},
{
stages: [
{ text: '', editing: ['x', 'xi', 'xih', "xi'hr"] },
{ text: '喜欢', editing: ['u', 'ui', 'uij', "ui'jt"] },
{ text: '喜欢视觉', editing: ['y', 'yi', 'yiu', "yi'uu"] },
'喜欢视觉艺术',
],
},
{
stages: [
{ text: '', editing: ['x', 'xt', 'xtx', "xt'xi"] },
{ text: '学习', editing: ['q', 'qm', 'qmd', "qm'dr"] },
{ text: '学习前端', editing: ['k', 'kd', 'kdf', "kd'fa"] },
'学习前端开发',
],
},
{
stages: [
{ text: '', editing: ['x', 'xt', 'xtx', "xt'xi"] },
{ text: '学习', editing: ['h', 'hz', "hz'd", "hz'dr"] },
{ text: '学习后端', editing: ['k', 'kd', 'kdf', "kd'fa"] },
'学习后端开发',
],
},
{
stages: [
{ text: '', editing: ['x', 'xt', 'xtx', "xt'xi"] },
{
text: '学习',
editing: ['q', 'qm', 'qmr', "qm'ru", "qm'ru'u", "qm'ru'ui"],
},
'学习嵌入式',
],
},
{
stages: [
{ text: '', editing: ['x', 'xt', 'xtx', "xt'xi"] },
...typeCharacters('学习', 'DevOps'),
],
},
{
stages: [
{ text: '', editing: ['z', 'zr', "zr'y", "zr'yj"] },
{ text: '钻研', editing: ['h', 'hy', 'hyd'] },
{ text: '钻研混', editing: ['m', 'mu'] },
'钻研混母',
],
},
{
stages: [
{ text: '', editing: ['z', 'zr', "zr'y", "zr'yj"] },
{ text: '钻研', editing: ['u', 'uz', "uz'g", "uz'gs"] },
{ text: '钻研手工', editing: ['k', 'kd', 'kdf', "kd'fa"] },
'钻研手工开发',
],
},
]
// 状态机定义
type StatusMachine = {
wipWord: number
wipStage: number
wipEditing: number
countdown: number
}
let status = $state<StatusMachine>({
wipWord: 0,
wipStage: 0,
wipEditing: 0,
countdown: 0,
})
// 显示
let wipWord = $derived(words[status.wipWord])
let wipStage = $derived(
wipWord.stages[Math.min(status.wipStage, wipWord.stages.length - 1)],
)
let currentText = $derived(
typeof wipStage == 'string' ? wipStage : wipStage.text,
)
let currentTextSliced = $derived(
status.wipStage >= wipWord.stages.length
? currentText.slice(0, currentText.length - status.wipEditing)
: currentText,
)
let currentEditing = $derived(
typeof wipStage == 'string' || status.wipEditing <= 0
? ''
: wipStage.editing[status.wipEditing - 1],
)
// 主要的状态更新逻辑
const DELAY_STEP_WORD = 250
const DELAY_STEP_STAGE = 80
const DELAY_STEP_EDIT = 80
const DELAY_STEP_DELETE = 50
const DELAY_DISPLAY_HOLD = 3000
// 调试用,如果发现动画有问题,可以在这里调慢动画
const DELAY_GLOBAL_FACTOR = 1
function step(status: StatusMachine, dt: number): StatusMachine {
if (status.countdown > 0) {
return {
...status,
countdown: status.countdown - dt / DELAY_GLOBAL_FACTOR,
}
}
if (typeof wipStage == 'object') {
if (status.wipEditing < wipStage.editing.length) {
return {
...status,
wipEditing: status.wipEditing + 1,
countdown: status.countdown + DELAY_STEP_EDIT,
}
}
} else if (status.wipStage >= wipWord.stages.length) {
// 此时执行删除操作
if (status.wipEditing < currentText.length) {
return {
...status,
wipEditing: status.wipEditing + 1,
countdown: status.countdown + DELAY_STEP_DELETE,
}
}
}
if (status.wipStage < wipWord.stages.length) {
return {
...status,
wipStage: status.wipStage + 1,
wipEditing: 0,
countdown:
status.wipStage == wipWord.stages.length - 1
? DELAY_DISPLAY_HOLD
: DELAY_STEP_STAGE,
}
}
return {
...status,
wipWord: (status.wipWord + 1) % words.length,
wipStage: 0,
wipEditing: 0,
countdown: DELAY_STEP_WORD,
}
}
// 时间循环
onMount(() => {
let enabled = true
let lastTime = Date.now()
function _step() {
if (!enabled) return
let currentTime = Date.now()
status = step(status, currentTime - lastTime)
lastTime = currentTime
requestAnimationFrame(_step)
}
_step()
return () => {
enabled = false
}
})
</script>
<span class="typewriter"
><span style="user-select: none;">&#xFEFF;</span><span class="text"
>{currentTextSliced}</span
><span class="edit">{currentEditing}</span></span
>
<style>
@keyframes blink {
from,
to {
opacity: 1;
}
50% {
opacity: 0;
}
}
.typewriter {
display: inline-block;
position: relative;
background-color: var(--color-bg-1);
padding: 0.25rem 0.5rem;
margin: 0 0.25rem;
border-radius: 0.5rem;
& > .edit {
text-decoration: underline;
/* font-family: var(--font-mono); */
}
&::after {
--gap-ud: 0.5rem;
content: '';
position: absolute;
inset-inline-end: 0.5rem;
inset-block-start: var(--gap-ud);
block-size: calc(100% - var(--gap-ud) * 2);
inline-size: 2px;
background-color: var(--color-fg-0);
animation: blink 1s step-end infinite;
}
}
</style>

View File

@ -2,6 +2,7 @@
import '../assets/style.css'
import '../assets/fonts.css'
import 'katex/dist/katex.min.css'
import '@unocss/reset/tailwind-v4.css'
interface Props {
title?: string

View File

@ -1,7 +1,7 @@
---
/* 在博客翻新时期使用的占位 Layout讲究的就是极简 */
import BaseLayout from '../layout/BaseLayout.astro'
import FullLayoutV1 from './FullLayoutV1.astro'
interface Props {
title?: string
@ -10,11 +10,11 @@ interface Props {
const { title = '小帕的小窝' } = Astro.props
---
<BaseLayout title={title}>
<FullLayoutV1 title={title}>
<div class="main">
<slot />
</div>
</BaseLayout>
</FullLayoutV1>
<style>
.main {
@ -29,6 +29,12 @@ const { title = '小帕的小窝' } = Astro.props
text-align: center;
box-sizing: border-box;
& :global(h1) {
font-size: 2rem;
font-weight: 700;
margin-block: 1rem;
}
& :global(a) {
color: var(--color-link);
text-decoration: none;

View File

@ -0,0 +1,104 @@
---
import BaseLayout from './BaseLayout.astro'
import { Icon } from 'astro-icon/components'
interface Props {
title?: string
}
const { title = '小帕的小窝' } = Astro.props
---
<BaseLayout title={title}>
<div class="nav-container">
<nav>
<ul class="left">
<li class="website-logo">
<a href="/">小帕的小窝</a>
</li>
<li>
<a href="https://legacy.passthem.top"
><Icon name="mdi:history" /> 旧博客系统*</a
>
</li>
<li>
<a href="/blogs"><Icon name="mdi:invoice-text-outline" />文章</a>
</li>
<li>
<a href="/about"
><Icon name="mdi:information-slab-circle-outline" />关于</a
>
</li>
</ul>
<ul class="right">Hello!</ul>
</nav>
</div>
<main>
<slot />
</main>
</BaseLayout>
<style>
.nav-container {
width: 100dvw;
height: 3rem;
position: fixed;
z-index: 100;
backdrop-filter: blur(4px);
background-color: rgb(from var(--color-bg-n) r g b / 0.5);
& > nav {
width: 100%;
height: 100%;
padding-inline: 40px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
max-width: 1400px;
margin-inline: auto;
font-weight: 400;
& > ul {
display: flex;
flex-direction: row;
}
& li {
height: 2rem;
&:hover {
background-color: rgb(from var(--color-fg-0) r g b / 0.1);
}
& > a {
padding-inline: 0.75rem;
width: 100%;
height: 100%;
display: flex;
align-items: center;
gap: 0.25rem;
& > svg {
font-size: 1.5rem;
}
}
}
& .website-logo > a {
gap: 0.5rem;
font-weight: 600;
/* & > .logo { */
/* --size: 2.5rem; */
/**/
/* width: var(--size); */
/* height: var(--size); */
/* display: inline-block; */
/* } */
}
}
}
</style>

View File

@ -1,6 +1,5 @@
---
import BaseLayout from '../layout/BaseLayout.astro'
import FullLayoutV1 from '../layout/FullLayoutV1.astro'
import { listBlogs } from '../lib/apis/legacy/blog'
export const prerender = false
@ -11,12 +10,34 @@ const page = isNaN(_page) ? 1 : Math.max(1, _page)
const blogs = await listBlogs({ page })
---
<BaseLayout>
{
blogs.map((blog) => (
<div>
<a href={`/blogs/${blog.id}`}>{blog.title}</a>
</div>
))
<FullLayoutV1>
<div class="__dev__caution">
<h1>仍在开发中,界面会崩坏</h1>
</div>
<section>
<ul>
{
blogs.map((blog) => (
<li>
<a href={`/blogs/${blog.id}`}>{blog.title}</a>
</li>
))
}
</ul>
</section>
</FullLayoutV1>
<style>
.__dev__caution {
width: 100dvw;
height: 100dvh;
display: flex;
align-items: center;
justify-content: center;
& > h1 {
font-size: 72px;
font-weight: 800;
}
}
</BaseLayout>
</style>

View File

@ -1,13 +1,19 @@
---
export const prerender = false
import BoringLayout from '../layout/BoringLayout.astro'
// import BoringLayout from '../layout/BoringLayout.astro'
import FullLayoutV1 from '../layout/FullLayoutV1.astro'
import MainpageButton from '../components/MainpageButton.svelte'
import MainpageTypewriter from '../components/MainpageTypewriter.svelte'
import { Image } from 'astro:assets'
import { mainpageGetClick } from '../lib/apis/legacy/mainpage'
// 无用按钮的数字预注入
// 常量定义
const AVATAR_URL =
'https://cdn.passthem.top/sharex/2026/03/%E6%93%A6%E6%B1%97%E5%90%8E_%E6%96%B9%E5%BD%A2.png.upscale.png'
// 无用按钮的数字预注入
let initialClicks = 0
try {
@ -18,10 +24,220 @@ try {
}
---
<BoringLayout>
<!--<BoringLayout>
<h1>博客系统翻新中...</h1>
<p>点击 <a href="https://legacy.passthem.top">这里</a> 查看旧版博客</p>
<p>或者了解更多 <a href="/about">关于这里</a></p>
<p>也欢迎你来 <a href="/contact">联络我</a></p>
<p><MainpageButton initialClicks={initialClicks} client:load /></p>
</BoringLayout>
</BoringLayout>-->
<FullLayoutV1 title="首页 - 小帕的小窝">
<!-- 就像写幻灯片一样的逻辑写它吧! -->
<section class="slide">
<!-- 自我介绍部分 -->
<div class="self-introduction">
<figure class="avatar">
<Image
src={AVATAR_URL}
alt="passthem 的头像,一个戴眼镜的男孩"
loading="eager"
width={240}
height={240}
/>
</figure>
<div class="descriptions">
<div class="motto">
<p>passthem¹</p>
<p>一个<MainpageTypewriter client:load />的</p>
<p>个人势创作者</p>
</div>
<div class="buttons">
<MainpageButton initialClicks={initialClicks} client:load />
</div>
</div>
</div>
<div class="notation">
<p>¹我在各个平台的惯用 ID开头字母大小写无所谓</p>
<p>
²头像由 <a href="https://space.bilibili.com/2017869">Yscao@bilibili</a> 绘制
</p>
<p>
³有人说这个配色像 <a
href="https://www.bilibili.com/video/av383664698/"
class="thsx">涂黑书信</a
>
</p>
</div>
</section>
<section class="slide" style="background-color: var(--color-bg-1);">
<div class="slide-title-design1">
<svg aria-hidden="true" width="800" height="240" viewBox="0 0 800 240">
<text x="10" y="220" class="stroke-layer">留言</text>
<text x="0" y="210" class="main-layer">留言</text>
</svg>
</div>
<h1>当前页面还在开发中......</h1>
</section>
<section class="slide">
<div class="slide-title-design1">
<svg aria-hidden="true" width="800" height="240" viewBox="0 0 800 240">
<text x="10" y="220" class="stroke-layer">友链</text>
<text x="0" y="210" class="main-layer">友链</text>
</svg>
</div>
<h1>当前页面还在开发中......</h1>
</section>
</FullLayoutV1>
<style>
.slide {
min-height: 100dvh;
display: flex;
align-items: center;
justify-content: center;
position: relative;
overflow: hidden;
& > .notation {
position: absolute;
width: 100dvw;
padding-inline-start: 2rem;
padding-block-end: 2rem;
inset-inline-start: 0;
inset-block-end: 0;
font-size: smaller;
color: var(--color-fg-0);
opacity: 0.3;
& a {
text-decoration: underline;
&:hover {
background-color: var(--color-fg-0);
color: var(--color-bg-0);
}
}
}
}
/* 自我介绍部分 */
.self-introduction {
display: flex;
flex-direction: column;
text-align: center;
align-items: center;
gap: 2rem;
@media (min-width: 768px) {
flex-direction: row-reverse;
text-align: left;
}
& > .avatar {
margin: 0;
border-radius: 50%;
width: clamp(160px, 30vw, 240px);
aspect-ratio: 1 / 1;
overflow: hidden;
}
& > .descriptions {
display: flex;
flex-direction: column;
gap: 3rem;
& > .motto {
font-size: clamp(2rem, 4vw, 4rem);
font-weight: 800;
display: grid;
grid-template-rows: repeat(3, 1fr);
align-items: center;
width: 11em;
& > p {
margin: 0;
width: max-content;
}
}
& > .buttons {
display: flex;
flex-direction: column;
align-items: center;
@media (min-width: 768px) {
flex-direction: row;
}
}
}
}
.thsx {
cursor: pointer;
text-decoration: underline;
}
.motto > p {
position: relative;
overflow: hidden;
&::before {
content: '';
display: block;
background-color: var(--color-fg-0);
width: 100%;
height: 100%;
position: absolute;
z-index: 2;
inset-inline-start: -100%;
}
}
section:has(.thsx:hover) .motto > p {
&:nth-child(1)::before {
transition-delay: 0;
}
&:nth-child(2)::before {
transition-delay: 0.1s;
}
&:nth-child(3)::before {
transition-delay: 0.2s;
}
&::before {
transition: inset-inline-start cubic-bezier(0.2, 1, 0.17, 1) 1s;
inset-inline-start: 0%;
}
}
section:has(.thsx:hover) .buttons {
transition: filter cubic-bezier(0.2, 1, 0.17, 1) 1s;
filter: grayscale(100%);
}
.slide-title-design1 {
position: absolute;
inset-inline-start: -1rem;
inset-block-start: -5rem;
opacity: 0.6;
& > svg {
font-weight: 900;
font-size: 10rem;
& > .stroke-layer {
fill: none;
stroke: var(--color-fg-0);
stroke-width: 1px;
stroke-linejoin: round;
user-select: none;
}
& > .main-layer {
fill: var(--color-fg-0);
}
}
}
</style>