mirror of
https://github.com/afoim/fuwari.git
synced 2026-01-31 09:03:18 +08:00
style: biome
优化访客统计动画逻辑
This commit is contained in:
@@ -1,11 +1,16 @@
|
||||
import sitemap from "@astrojs/sitemap";
|
||||
import svelte from "@astrojs/svelte";
|
||||
import tailwind from "@astrojs/tailwind";
|
||||
import { pluginCollapsibleSections } from "@expressive-code/plugin-collapsible-sections";
|
||||
import { pluginLineNumbers } from "@expressive-code/plugin-line-numbers";
|
||||
import swup from "@swup/astro";
|
||||
import expressiveCode from "astro-expressive-code";
|
||||
import icon from "astro-icon";
|
||||
import { defineConfig } from "astro/config";
|
||||
import { defineConfig, passthroughImageService } from "astro/config";
|
||||
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
||||
import rehypeComponents from "rehype-components"; /* Render the custom directive content */
|
||||
import rehypeExternalLinks from "rehype-external-links";
|
||||
import rehypeKatex from "rehype-katex";
|
||||
import rehypeSlug from "rehype-slug";
|
||||
import remarkDirective from "remark-directive"; /* Handle directives */
|
||||
@@ -13,6 +18,9 @@ import remarkGithubAdmonitionsToDirectives from "remark-github-admonitions-to-di
|
||||
import remarkMath from "remark-math";
|
||||
import remarkSectionize from "remark-sectionize";
|
||||
import { imageFallbackConfig, siteConfig } from "./src/config.ts";
|
||||
import { expressiveCodeConfig } from "./src/config.ts";
|
||||
// import { pluginLanguageBadge } from "./src/plugins/expressive-code/language-badge.ts";
|
||||
import { pluginCustomCopyButton } from "./src/plugins/expressive-code/custom-copy-button.js";
|
||||
import { AdmonitionComponent } from "./src/plugins/rehype-component-admonition.mjs";
|
||||
import { GithubCardComponent } from "./src/plugins/rehype-component-github-card.mjs";
|
||||
import { UrlCardComponent } from "./src/plugins/rehype-component-url-card.mjs";
|
||||
@@ -20,19 +28,11 @@ import rehypeImageFallback from "./src/plugins/rehype-image-fallback.mjs";
|
||||
import { parseDirectiveNode } from "./src/plugins/remark-directive-rehype.js";
|
||||
import { remarkExcerpt } from "./src/plugins/remark-excerpt.js";
|
||||
import { remarkReadingTime } from "./src/plugins/remark-reading-time.mjs";
|
||||
import rehypeExternalLinks from 'rehype-external-links';
|
||||
import expressiveCode from "astro-expressive-code";
|
||||
import { pluginCollapsibleSections } from "@expressive-code/plugin-collapsible-sections";
|
||||
import { pluginLineNumbers } from "@expressive-code/plugin-line-numbers";
|
||||
import { expressiveCodeConfig } from "./src/config.ts";
|
||||
// import { pluginLanguageBadge } from "./src/plugins/expressive-code/language-badge.ts";
|
||||
import { pluginCustomCopyButton } from "./src/plugins/expressive-code/custom-copy-button.js";
|
||||
import { defineConfig, passthroughImageService } from 'astro/config';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
image: {
|
||||
service: passthroughImageService()
|
||||
service: passthroughImageService(),
|
||||
},
|
||||
site: "https://blog.acofork.com",
|
||||
base: "/",
|
||||
@@ -40,9 +40,11 @@ export default defineConfig({
|
||||
output: "static",
|
||||
redirects: {
|
||||
"/donate": "/sponsors",
|
||||
"/ak": "https://akile.io/register?aff_code=503fe5ea-e7c5-4d68-ae05-6de99513680e",
|
||||
"/ak":
|
||||
"https://akile.io/register?aff_code=503fe5ea-e7c5-4d68-ae05-6de99513680e",
|
||||
"/kook": "https://kook.vip/K29zpT",
|
||||
"/long": "https://iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii.iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii.in/",
|
||||
"/long":
|
||||
"https://iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii.iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii.in/",
|
||||
"/mly": "https://muleyun.com/aff/GOTRJLPN",
|
||||
"/tg": "https://t.me/+_07DERp7k1ljYTc1",
|
||||
"/tit": "/posts/pin/",
|
||||
@@ -50,11 +52,14 @@ export default defineConfig({
|
||||
"/wly": "https://wl.awcmam.com/#/register?code=FNQwOQBM",
|
||||
"/yyb": "https://www.rainyun.com/acofork_?s=bilibili",
|
||||
"/iku": "https://ikuuu.de/auth/register?code=Bjou",
|
||||
"/esa": "https://tianchi.aliyun.com/specials/promotion/freetier/esa?taskCode=25254&recordId=c856e61228828a0423417a767828d166"
|
||||
"/esa":
|
||||
"https://tianchi.aliyun.com/specials/promotion/freetier/esa?taskCode=25254&recordId=c856e61228828a0423417a767828d166",
|
||||
},
|
||||
integrations: [tailwind({
|
||||
integrations: [
|
||||
tailwind({
|
||||
nesting: true,
|
||||
}), swup({
|
||||
}),
|
||||
swup({
|
||||
theme: false,
|
||||
animationClass: "transition-swup-", // see https://swup.js.org/options/#animationselector
|
||||
// the default value `transition-` cause transition delay
|
||||
@@ -67,7 +72,8 @@ export default defineConfig({
|
||||
updateHead: true,
|
||||
updateBodyClass: false,
|
||||
globalInstance: true,
|
||||
}), icon({
|
||||
}),
|
||||
icon({
|
||||
include: {
|
||||
"preprocess: vitePreprocess(),": ["*"],
|
||||
"fa6-brands": ["*"],
|
||||
@@ -77,19 +83,21 @@ export default defineConfig({
|
||||
"material-symbols-light": ["*"],
|
||||
"material-symbols": ["*"],
|
||||
},
|
||||
}), svelte(), sitemap(),
|
||||
}),
|
||||
svelte(),
|
||||
sitemap(),
|
||||
expressiveCode({
|
||||
themes: [expressiveCodeConfig.theme, expressiveCodeConfig.theme],
|
||||
plugins: [
|
||||
pluginCollapsibleSections(),
|
||||
pluginLineNumbers(),
|
||||
// pluginLanguageBadge(),
|
||||
pluginCustomCopyButton()
|
||||
pluginCustomCopyButton(),
|
||||
],
|
||||
defaultProps: {
|
||||
wrap: true,
|
||||
overridesByLang: {
|
||||
'shellsession': {
|
||||
shellsession: {
|
||||
showLineNumbers: false,
|
||||
},
|
||||
},
|
||||
@@ -99,7 +107,8 @@ export default defineConfig({
|
||||
borderRadius: "0.25rem",
|
||||
borderColor: "none",
|
||||
codeFontSize: "0.875rem",
|
||||
codeFontFamily: "'JetBrains Mono Variable', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace",
|
||||
codeFontFamily:
|
||||
"'JetBrains Mono Variable', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace",
|
||||
codeLineHeight: "1.5rem",
|
||||
frames: {
|
||||
editorBackground: "var(--codeblock-bg)",
|
||||
@@ -110,17 +119,17 @@ export default defineConfig({
|
||||
editorActiveTabIndicatorBottomColor: "var(--primary)",
|
||||
editorActiveTabIndicatorTopColor: "none",
|
||||
editorTabBarBorderBottomColor: "var(--codeblock-topbar-bg)",
|
||||
terminalTitlebarBorderBottomColor: "none"
|
||||
terminalTitlebarBorderBottomColor: "none",
|
||||
},
|
||||
textMarkers: {
|
||||
delHue: 0,
|
||||
insHue: 180,
|
||||
markHue: 250
|
||||
}
|
||||
markHue: 250,
|
||||
},
|
||||
},
|
||||
frames: {
|
||||
showCopyToClipboardButton: false,
|
||||
}
|
||||
},
|
||||
}),
|
||||
],
|
||||
markdown: {
|
||||
@@ -154,7 +163,7 @@ export default defineConfig({
|
||||
[
|
||||
rehypeExternalLinks,
|
||||
{
|
||||
target: '_blank',
|
||||
target: "_blank",
|
||||
},
|
||||
],
|
||||
[
|
||||
|
||||
@@ -7,7 +7,14 @@
|
||||
},
|
||||
"files": {
|
||||
"ignoreUnknown": false,
|
||||
"ignore": ["src/**/*.css","src/public/**/*", "dist/**/*", "node_modules/**/*"]
|
||||
"ignore": [
|
||||
"src/**/*.css",
|
||||
"public/**/*",
|
||||
".astro/**/*",
|
||||
"src/content/.obsidian/**/*",
|
||||
"dist/**/*",
|
||||
"node_modules/**/*"
|
||||
]
|
||||
},
|
||||
"formatter": {
|
||||
"enabled": true,
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/check": "^0.9.4",
|
||||
"@astrojs/react": "^4.4.2",
|
||||
"@astrojs/rss": "^4.0.11",
|
||||
"@astrojs/sitemap": "^3.3.1",
|
||||
"@astrojs/svelte": "7.0.12",
|
||||
@@ -27,6 +28,7 @@
|
||||
"@fancyapps/ui": "^6.0.5",
|
||||
"@fontsource-variable/jetbrains-mono": "^5.2.5",
|
||||
"@fontsource/roboto": "^5.2.5",
|
||||
"@gsap/react": "^2.1.2",
|
||||
"@iconify-json/fa6-brands": "^1.2.5",
|
||||
"@iconify-json/fa6-regular": "^1.2.3",
|
||||
"@iconify-json/fa6-solid": "^1.2.3",
|
||||
@@ -35,11 +37,14 @@
|
||||
"@iconify/svelte": "^4.2.0",
|
||||
"@swup/astro": "^1.6.0",
|
||||
"@tailwindcss/typography": "^0.5.16",
|
||||
"@types/react": "^19.2.7",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vercel/analytics": "^1.5.0",
|
||||
"astro": "5.7.9",
|
||||
"astro-expressive-code": "^0.41.3",
|
||||
"astro-icon": "^1.1.5",
|
||||
"glob": "^11.0.3",
|
||||
"gsap": "^3.14.2",
|
||||
"hastscript": "^9.0.1",
|
||||
"katex": "^0.16.22",
|
||||
"markdown-it": "^14.1.0",
|
||||
@@ -47,6 +52,8 @@
|
||||
"node-html-parser": "^7.0.1",
|
||||
"overlayscrollbars": "^2.11.1",
|
||||
"photoswipe": "^5.4.4",
|
||||
"react": "^19.2.3",
|
||||
"react-dom": "^19.2.3",
|
||||
"reading-time": "^1.5.0",
|
||||
"rehype-autolink-headings": "^7.1.0",
|
||||
"rehype-components": "^0.3.0",
|
||||
|
||||
434
pnpm-lock.yaml
generated
434
pnpm-lock.yaml
generated
@@ -16,6 +16,9 @@ importers:
|
||||
'@astrojs/check':
|
||||
specifier: ^0.9.4
|
||||
version: 0.9.4(typescript@5.8.3)
|
||||
'@astrojs/react':
|
||||
specifier: ^4.4.2
|
||||
version: 4.4.2(@types/node@22.14.1)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(jiti@1.21.7)(lightningcss@1.29.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.80.4)(stylus@0.64.0)(terser@5.39.0)(yaml@2.7.0)
|
||||
'@astrojs/rss':
|
||||
specifier: ^4.0.11
|
||||
version: 4.0.11
|
||||
@@ -30,7 +33,7 @@ importers:
|
||||
version: 6.0.2(astro@5.7.9(patch_hash=ysrllw3gj6hylybllnynya5oma)(@types/node@22.14.1)(jiti@1.21.7)(lightningcss@1.29.3)(rollup@2.79.2)(sass@1.80.4)(stylus@0.64.0)(terser@5.39.0)(typescript@5.8.3)(yaml@2.7.0))(tailwindcss@3.4.17)
|
||||
'@astrojs/vercel':
|
||||
specifier: ^8.2.7
|
||||
version: 8.2.7(astro@5.7.9(patch_hash=ysrllw3gj6hylybllnynya5oma)(@types/node@22.14.1)(jiti@1.21.7)(lightningcss@1.29.3)(rollup@2.79.2)(sass@1.80.4)(stylus@0.64.0)(terser@5.39.0)(typescript@5.8.3)(yaml@2.7.0))(rollup@2.79.2)(svelte@5.28.2)
|
||||
version: 8.2.7(astro@5.7.9(patch_hash=ysrllw3gj6hylybllnynya5oma)(@types/node@22.14.1)(jiti@1.21.7)(lightningcss@1.29.3)(rollup@2.79.2)(sass@1.80.4)(stylus@0.64.0)(terser@5.39.0)(typescript@5.8.3)(yaml@2.7.0))(react@19.2.3)(rollup@2.79.2)(svelte@5.28.2)
|
||||
'@expressive-code/core':
|
||||
specifier: ^0.41.3
|
||||
version: 0.41.3
|
||||
@@ -49,6 +52,9 @@ importers:
|
||||
'@fontsource/roboto':
|
||||
specifier: ^5.2.5
|
||||
version: 5.2.5
|
||||
'@gsap/react':
|
||||
specifier: ^2.1.2
|
||||
version: 2.1.2(gsap@3.14.2)(react@19.2.3)
|
||||
'@iconify-json/fa6-brands':
|
||||
specifier: ^1.2.5
|
||||
version: 1.2.5
|
||||
@@ -73,9 +79,15 @@ importers:
|
||||
'@tailwindcss/typography':
|
||||
specifier: ^0.5.16
|
||||
version: 0.5.16(tailwindcss@3.4.17)
|
||||
'@types/react':
|
||||
specifier: ^19.2.7
|
||||
version: 19.2.7
|
||||
'@types/react-dom':
|
||||
specifier: ^19.2.3
|
||||
version: 19.2.3(@types/react@19.2.7)
|
||||
'@vercel/analytics':
|
||||
specifier: ^1.5.0
|
||||
version: 1.5.0(svelte@5.28.2)
|
||||
version: 1.5.0(react@19.2.3)(svelte@5.28.2)
|
||||
astro:
|
||||
specifier: 5.7.9
|
||||
version: 5.7.9(patch_hash=ysrllw3gj6hylybllnynya5oma)(@types/node@22.14.1)(jiti@1.21.7)(lightningcss@1.29.3)(rollup@2.79.2)(sass@1.80.4)(stylus@0.64.0)(terser@5.39.0)(typescript@5.8.3)(yaml@2.7.0)
|
||||
@@ -88,6 +100,9 @@ importers:
|
||||
glob:
|
||||
specifier: ^11.0.3
|
||||
version: 11.0.3
|
||||
gsap:
|
||||
specifier: ^3.14.2
|
||||
version: 3.14.2
|
||||
hastscript:
|
||||
specifier: ^9.0.1
|
||||
version: 9.0.1
|
||||
@@ -109,6 +124,12 @@ importers:
|
||||
photoswipe:
|
||||
specifier: ^5.4.4
|
||||
version: 5.4.4
|
||||
react:
|
||||
specifier: ^19.2.3
|
||||
version: 19.2.3
|
||||
react-dom:
|
||||
specifier: ^19.2.3
|
||||
version: 19.2.3(react@19.2.3)
|
||||
reading-time:
|
||||
specifier: ^1.5.0
|
||||
version: 1.5.0
|
||||
@@ -248,6 +269,15 @@ packages:
|
||||
resolution: {integrity: sha512-GilTHKGCW6HMq7y3BUv9Ac7GMe/MO9gi9GW62GzKtth0SwukCu/qp2wLiGpEujhY+VVhaG9v7kv/5vFzvf4NYw==}
|
||||
engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0}
|
||||
|
||||
'@astrojs/react@4.4.2':
|
||||
resolution: {integrity: sha512-1tl95bpGfuaDMDn8O3x/5Dxii1HPvzjvpL2YTuqOOrQehs60I2DKiDgh1jrKc7G8lv+LQT5H15V6QONQ+9waeQ==}
|
||||
engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0}
|
||||
peerDependencies:
|
||||
'@types/react': ^17.0.50 || ^18.0.21 || ^19.0.0
|
||||
'@types/react-dom': ^17.0.17 || ^18.0.6 || ^19.0.0
|
||||
react: ^17.0.2 || ^18.0.0 || ^19.0.0
|
||||
react-dom: ^17.0.2 || ^18.0.0 || ^19.0.0
|
||||
|
||||
'@astrojs/rss@4.0.11':
|
||||
resolution: {integrity: sha512-3e3H8i6kc97KGnn9iaZBJpIkdoQi8MmR5zH5R+dWsfCM44lLTszOqy1OBfGGxDt56mpQkYVtZJWoxMyWuUZBfw==}
|
||||
|
||||
@@ -287,18 +317,34 @@ packages:
|
||||
resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/code-frame@7.27.1':
|
||||
resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/compat-data@7.26.8':
|
||||
resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/compat-data@7.28.5':
|
||||
resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/core@7.26.10':
|
||||
resolution: {integrity: sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/core@7.28.5':
|
||||
resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/generator@7.27.0':
|
||||
resolution: {integrity: sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/generator@7.28.5':
|
||||
resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/helper-annotate-as-pure@7.25.9':
|
||||
resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -307,6 +353,10 @@ packages:
|
||||
resolution: {integrity: sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/helper-compilation-targets@7.27.2':
|
||||
resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/helper-create-class-features-plugin@7.27.0':
|
||||
resolution: {integrity: sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -324,6 +374,10 @@ packages:
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
|
||||
|
||||
'@babel/helper-globals@7.28.0':
|
||||
resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/helper-member-expression-to-functions@7.25.9':
|
||||
resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -332,12 +386,22 @@ packages:
|
||||
resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/helper-module-imports@7.27.1':
|
||||
resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/helper-module-transforms@7.26.0':
|
||||
resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0
|
||||
|
||||
'@babel/helper-module-transforms@7.28.3':
|
||||
resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0
|
||||
|
||||
'@babel/helper-optimise-call-expression@7.25.9':
|
||||
resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -346,6 +410,10 @@ packages:
|
||||
resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/helper-plugin-utils@7.27.1':
|
||||
resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/helper-remap-async-to-generator@7.25.9':
|
||||
resolution: {integrity: sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -378,10 +446,18 @@ packages:
|
||||
resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/helper-validator-identifier@7.28.5':
|
||||
resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/helper-validator-option@7.25.9':
|
||||
resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/helper-validator-option@7.27.1':
|
||||
resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/helper-wrap-function@7.25.9':
|
||||
resolution: {integrity: sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -390,6 +466,10 @@ packages:
|
||||
resolution: {integrity: sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/helpers@7.28.4':
|
||||
resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/parser@7.27.0':
|
||||
resolution: {integrity: sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
@@ -400,6 +480,11 @@ packages:
|
||||
engines: {node: '>=6.0.0'}
|
||||
hasBin: true
|
||||
|
||||
'@babel/parser@7.28.5':
|
||||
resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
hasBin: true
|
||||
|
||||
'@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9':
|
||||
resolution: {integrity: sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -723,6 +808,18 @@ packages:
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0-0
|
||||
|
||||
'@babel/plugin-transform-react-jsx-self@7.27.1':
|
||||
resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0-0
|
||||
|
||||
'@babel/plugin-transform-react-jsx-source@7.27.1':
|
||||
resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0-0
|
||||
|
||||
'@babel/plugin-transform-react-jsx@7.25.9':
|
||||
resolution: {integrity: sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -838,10 +935,18 @@ packages:
|
||||
resolution: {integrity: sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/template@7.27.2':
|
||||
resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/traverse@7.27.0':
|
||||
resolution: {integrity: sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/traverse@7.28.5':
|
||||
resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/types@7.27.0':
|
||||
resolution: {integrity: sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -850,6 +955,10 @@ packages:
|
||||
resolution: {integrity: sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/types@7.28.5':
|
||||
resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@biomejs/biome@1.9.4':
|
||||
resolution: {integrity: sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
@@ -1130,6 +1239,12 @@ packages:
|
||||
'@fontsource/roboto@5.2.5':
|
||||
resolution: {integrity: sha512-70r2UZ0raqLn5W+sPeKhqlf8wGvUXFWlofaDlcbt/S3d06+17gXKr3VNqDODB0I1ASme3dGT5OJj9NABt7OTZQ==}
|
||||
|
||||
'@gsap/react@2.1.2':
|
||||
resolution: {integrity: sha512-JqliybO1837UcgH2hVOM4VO+38APk3ECNrsuSM4MuXp+rbf+/2IG2K1YJiqfTcXQHH7XlA0m3ykniFYstfq0Iw==}
|
||||
peerDependencies:
|
||||
gsap: ^3.12.5
|
||||
react: '>=17'
|
||||
|
||||
'@iconify-json/fa6-brands@1.2.5':
|
||||
resolution: {integrity: sha512-U/iFfziz6jSN9zArOJZYTtoj2tQyh6MxPdI8M84DQ2kEulPaj8j+h9bqvjmzszNHmD7v+kmmKd/MLkMKk+3Zuw==}
|
||||
|
||||
@@ -1418,10 +1533,16 @@ packages:
|
||||
resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.13':
|
||||
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.8':
|
||||
resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
|
||||
'@jridgewell/remapping@2.3.5':
|
||||
resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
|
||||
|
||||
'@jridgewell/resolve-uri@3.1.2':
|
||||
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
@@ -1439,6 +1560,9 @@ packages:
|
||||
'@jridgewell/trace-mapping@0.3.25':
|
||||
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
|
||||
|
||||
'@jridgewell/trace-mapping@0.3.31':
|
||||
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
|
||||
|
||||
'@mapbox/node-pre-gyp@2.0.0':
|
||||
resolution: {integrity: sha512-llMXd39jtP0HpQLVI37Bf1m2ADlEb35GYSh1SDSLsBhR+5iCxiNGlT31yqbNtVHygHAtMy6dWFERpU2JgufhPg==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -1551,6 +1675,9 @@ packages:
|
||||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
'@rolldown/pluginutils@1.0.0-beta.27':
|
||||
resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==}
|
||||
|
||||
'@rollup/plugin-alias@3.1.9':
|
||||
resolution: {integrity: sha512-QI5fsEvm9bDzt32k39wpOwZhVzRcL5ydcffUHMyLVaVaLeC70I8TJZ17F1z1eMoLu4E/UOcH9BWVkKpIKdrfiw==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
@@ -1928,6 +2055,14 @@ packages:
|
||||
'@types/parse-json@4.0.2':
|
||||
resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
|
||||
|
||||
'@types/react-dom@19.2.3':
|
||||
resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==}
|
||||
peerDependencies:
|
||||
'@types/react': ^19.2.0
|
||||
|
||||
'@types/react@19.2.7':
|
||||
resolution: {integrity: sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==}
|
||||
|
||||
'@types/resolve@1.17.1':
|
||||
resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==}
|
||||
|
||||
@@ -1999,6 +2134,12 @@ packages:
|
||||
'@vercel/routing-utils@5.1.1':
|
||||
resolution: {integrity: sha512-EyOik06V2fPXAbKY087BM7DMOQOJK+9mubwwox1TkDi21tMeJcMYwsXwepm6ZmyZ5u0j1TpJW172fP4MbzaCcg==}
|
||||
|
||||
'@vitejs/plugin-react@4.7.0':
|
||||
resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
|
||||
|
||||
'@volar/kit@2.4.12':
|
||||
resolution: {integrity: sha512-f9JE8oy9C2rBcCWxUYKUF23hOXz4mwgVXFjk7nHhxzplaoVjEOsKpBm8NI2nBH7Cwu8DRxDwBsbIxMl/8wlLxw==}
|
||||
peerDependencies:
|
||||
@@ -2500,6 +2641,9 @@ packages:
|
||||
resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==}
|
||||
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
|
||||
|
||||
csstype@3.2.3:
|
||||
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
|
||||
|
||||
data-view-buffer@1.0.2:
|
||||
resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -2967,6 +3111,9 @@ packages:
|
||||
graceful-fs@4.2.11:
|
||||
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
|
||||
|
||||
gsap@3.14.2:
|
||||
resolution: {integrity: sha512-P8/mMxVLU7o4+55+1TCnQrPmgjPKnwkzkXOK1asnR9Jg2lna4tEY5qBJjMmAaOBDDZWtlRjBXjLa0w53G/uBLA==}
|
||||
|
||||
gzip-size@3.0.0:
|
||||
resolution: {integrity: sha512-6s8trQiK+OMzSaCSVXX+iqIcLV9tC+E73jrJrJTyS4h/AJhlxHvzFKqM1YLDJWRGgHX8uLkBeXkA0njNj39L4w==}
|
||||
engines: {node: '>=0.12.0'}
|
||||
@@ -4404,6 +4551,19 @@ packages:
|
||||
randombytes@2.1.0:
|
||||
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
|
||||
|
||||
react-dom@19.2.3:
|
||||
resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==}
|
||||
peerDependencies:
|
||||
react: ^19.2.3
|
||||
|
||||
react-refresh@0.17.0:
|
||||
resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
react@19.2.3:
|
||||
resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
read-cache@1.0.0:
|
||||
resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
|
||||
|
||||
@@ -4657,6 +4817,9 @@ packages:
|
||||
sax@1.4.1:
|
||||
resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==}
|
||||
|
||||
scheduler@0.27.0:
|
||||
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
|
||||
|
||||
scrl@2.0.0:
|
||||
resolution: {integrity: sha512-BbbVXxrOn58Ge4wjOORIRVZamssQu08ISLL/AC2z9aATIsKqZLESwZVW5YR0Yz0C7qqDRHb4yNXJlQ8yW0SGHw==}
|
||||
|
||||
@@ -5216,6 +5379,46 @@ packages:
|
||||
yaml:
|
||||
optional: true
|
||||
|
||||
vite@6.4.1:
|
||||
resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==}
|
||||
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
|
||||
jiti: '>=1.21.0'
|
||||
less: '*'
|
||||
lightningcss: ^1.21.0
|
||||
sass: '*'
|
||||
sass-embedded: '*'
|
||||
stylus: '*'
|
||||
sugarss: '*'
|
||||
terser: ^5.16.0
|
||||
tsx: ^4.8.1
|
||||
yaml: ^2.4.2
|
||||
peerDependenciesMeta:
|
||||
'@types/node':
|
||||
optional: true
|
||||
jiti:
|
||||
optional: true
|
||||
less:
|
||||
optional: true
|
||||
lightningcss:
|
||||
optional: true
|
||||
sass:
|
||||
optional: true
|
||||
sass-embedded:
|
||||
optional: true
|
||||
stylus:
|
||||
optional: true
|
||||
sugarss:
|
||||
optional: true
|
||||
terser:
|
||||
optional: true
|
||||
tsx:
|
||||
optional: true
|
||||
yaml:
|
||||
optional: true
|
||||
|
||||
vitefu@1.0.6:
|
||||
resolution: {integrity: sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA==}
|
||||
peerDependencies:
|
||||
@@ -5556,6 +5759,29 @@ snapshots:
|
||||
dependencies:
|
||||
prismjs: 1.30.0
|
||||
|
||||
'@astrojs/react@4.4.2(@types/node@22.14.1)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(jiti@1.21.7)(lightningcss@1.29.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.80.4)(stylus@0.64.0)(terser@5.39.0)(yaml@2.7.0)':
|
||||
dependencies:
|
||||
'@types/react': 19.2.7
|
||||
'@types/react-dom': 19.2.3(@types/react@19.2.7)
|
||||
'@vitejs/plugin-react': 4.7.0(vite@6.4.1(@types/node@22.14.1)(jiti@1.21.7)(lightningcss@1.29.3)(sass@1.80.4)(stylus@0.64.0)(terser@5.39.0)(yaml@2.7.0))
|
||||
react: 19.2.3
|
||||
react-dom: 19.2.3(react@19.2.3)
|
||||
ultrahtml: 1.6.0
|
||||
vite: 6.4.1(@types/node@22.14.1)(jiti@1.21.7)(lightningcss@1.29.3)(sass@1.80.4)(stylus@0.64.0)(terser@5.39.0)(yaml@2.7.0)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- jiti
|
||||
- less
|
||||
- lightningcss
|
||||
- sass
|
||||
- sass-embedded
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
- tsx
|
||||
- yaml
|
||||
|
||||
'@astrojs/rss@4.0.11':
|
||||
dependencies:
|
||||
fast-xml-parser: 4.5.3
|
||||
@@ -5621,10 +5847,10 @@ snapshots:
|
||||
semver: 7.7.1
|
||||
vscode-languageserver-textdocument: 1.0.12
|
||||
|
||||
'@astrojs/vercel@8.2.7(astro@5.7.9(patch_hash=ysrllw3gj6hylybllnynya5oma)(@types/node@22.14.1)(jiti@1.21.7)(lightningcss@1.29.3)(rollup@2.79.2)(sass@1.80.4)(stylus@0.64.0)(terser@5.39.0)(typescript@5.8.3)(yaml@2.7.0))(rollup@2.79.2)(svelte@5.28.2)':
|
||||
'@astrojs/vercel@8.2.7(astro@5.7.9(patch_hash=ysrllw3gj6hylybllnynya5oma)(@types/node@22.14.1)(jiti@1.21.7)(lightningcss@1.29.3)(rollup@2.79.2)(sass@1.80.4)(stylus@0.64.0)(terser@5.39.0)(typescript@5.8.3)(yaml@2.7.0))(react@19.2.3)(rollup@2.79.2)(svelte@5.28.2)':
|
||||
dependencies:
|
||||
'@astrojs/internal-helpers': 0.7.2
|
||||
'@vercel/analytics': 1.5.0(svelte@5.28.2)
|
||||
'@vercel/analytics': 1.5.0(react@19.2.3)(svelte@5.28.2)
|
||||
'@vercel/functions': 2.2.13
|
||||
'@vercel/nft': 0.29.4(rollup@2.79.2)
|
||||
'@vercel/routing-utils': 5.1.1
|
||||
@@ -5654,8 +5880,16 @@ snapshots:
|
||||
js-tokens: 4.0.0
|
||||
picocolors: 1.1.1
|
||||
|
||||
'@babel/code-frame@7.27.1':
|
||||
dependencies:
|
||||
'@babel/helper-validator-identifier': 7.27.1
|
||||
js-tokens: 4.0.0
|
||||
picocolors: 1.1.1
|
||||
|
||||
'@babel/compat-data@7.26.8': {}
|
||||
|
||||
'@babel/compat-data@7.28.5': {}
|
||||
|
||||
'@babel/core@7.26.10':
|
||||
dependencies:
|
||||
'@ampproject/remapping': 2.3.0
|
||||
@@ -5676,6 +5910,26 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@babel/core@7.28.5':
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.27.1
|
||||
'@babel/generator': 7.28.5
|
||||
'@babel/helper-compilation-targets': 7.27.2
|
||||
'@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5)
|
||||
'@babel/helpers': 7.28.4
|
||||
'@babel/parser': 7.28.5
|
||||
'@babel/template': 7.27.2
|
||||
'@babel/traverse': 7.28.5
|
||||
'@babel/types': 7.28.5
|
||||
'@jridgewell/remapping': 2.3.5
|
||||
convert-source-map: 2.0.0
|
||||
debug: 4.4.0
|
||||
gensync: 1.0.0-beta.2
|
||||
json5: 2.2.3
|
||||
semver: 6.3.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@babel/generator@7.27.0':
|
||||
dependencies:
|
||||
'@babel/parser': 7.27.0
|
||||
@@ -5684,6 +5938,14 @@ snapshots:
|
||||
'@jridgewell/trace-mapping': 0.3.25
|
||||
jsesc: 3.1.0
|
||||
|
||||
'@babel/generator@7.28.5':
|
||||
dependencies:
|
||||
'@babel/parser': 7.28.5
|
||||
'@babel/types': 7.28.5
|
||||
'@jridgewell/gen-mapping': 0.3.13
|
||||
'@jridgewell/trace-mapping': 0.3.31
|
||||
jsesc: 3.1.0
|
||||
|
||||
'@babel/helper-annotate-as-pure@7.25.9':
|
||||
dependencies:
|
||||
'@babel/types': 7.27.0
|
||||
@@ -5696,6 +5958,14 @@ snapshots:
|
||||
lru-cache: 5.1.1
|
||||
semver: 6.3.1
|
||||
|
||||
'@babel/helper-compilation-targets@7.27.2':
|
||||
dependencies:
|
||||
'@babel/compat-data': 7.28.5
|
||||
'@babel/helper-validator-option': 7.27.1
|
||||
browserslist: 4.24.4
|
||||
lru-cache: 5.1.1
|
||||
semver: 6.3.1
|
||||
|
||||
'@babel/helper-create-class-features-plugin@7.27.0(@babel/core@7.26.10)':
|
||||
dependencies:
|
||||
'@babel/core': 7.26.10
|
||||
@@ -5727,6 +5997,8 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@babel/helper-globals@7.28.0': {}
|
||||
|
||||
'@babel/helper-member-expression-to-functions@7.25.9':
|
||||
dependencies:
|
||||
'@babel/traverse': 7.27.0
|
||||
@@ -5741,6 +6013,13 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@babel/helper-module-imports@7.27.1':
|
||||
dependencies:
|
||||
'@babel/traverse': 7.28.5
|
||||
'@babel/types': 7.28.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@babel/helper-module-transforms@7.26.0(@babel/core@7.26.10)':
|
||||
dependencies:
|
||||
'@babel/core': 7.26.10
|
||||
@@ -5750,12 +6029,23 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)':
|
||||
dependencies:
|
||||
'@babel/core': 7.28.5
|
||||
'@babel/helper-module-imports': 7.27.1
|
||||
'@babel/helper-validator-identifier': 7.27.1
|
||||
'@babel/traverse': 7.28.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@babel/helper-optimise-call-expression@7.25.9':
|
||||
dependencies:
|
||||
'@babel/types': 7.27.0
|
||||
|
||||
'@babel/helper-plugin-utils@7.26.5': {}
|
||||
|
||||
'@babel/helper-plugin-utils@7.27.1': {}
|
||||
|
||||
'@babel/helper-remap-async-to-generator@7.25.9(@babel/core@7.26.10)':
|
||||
dependencies:
|
||||
'@babel/core': 7.26.10
|
||||
@@ -5783,16 +6073,18 @@ snapshots:
|
||||
|
||||
'@babel/helper-string-parser@7.25.9': {}
|
||||
|
||||
'@babel/helper-string-parser@7.27.1':
|
||||
optional: true
|
||||
'@babel/helper-string-parser@7.27.1': {}
|
||||
|
||||
'@babel/helper-validator-identifier@7.25.9': {}
|
||||
|
||||
'@babel/helper-validator-identifier@7.27.1':
|
||||
optional: true
|
||||
'@babel/helper-validator-identifier@7.27.1': {}
|
||||
|
||||
'@babel/helper-validator-identifier@7.28.5': {}
|
||||
|
||||
'@babel/helper-validator-option@7.25.9': {}
|
||||
|
||||
'@babel/helper-validator-option@7.27.1': {}
|
||||
|
||||
'@babel/helper-wrap-function@7.25.9':
|
||||
dependencies:
|
||||
'@babel/template': 7.27.0
|
||||
@@ -5806,6 +6098,11 @@ snapshots:
|
||||
'@babel/template': 7.27.0
|
||||
'@babel/types': 7.27.0
|
||||
|
||||
'@babel/helpers@7.28.4':
|
||||
dependencies:
|
||||
'@babel/template': 7.27.2
|
||||
'@babel/types': 7.28.5
|
||||
|
||||
'@babel/parser@7.27.0':
|
||||
dependencies:
|
||||
'@babel/types': 7.27.0
|
||||
@@ -5813,7 +6110,10 @@ snapshots:
|
||||
'@babel/parser@7.28.0':
|
||||
dependencies:
|
||||
'@babel/types': 7.28.2
|
||||
optional: true
|
||||
|
||||
'@babel/parser@7.28.5':
|
||||
dependencies:
|
||||
'@babel/types': 7.28.5
|
||||
|
||||
'@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.26.10)':
|
||||
dependencies:
|
||||
@@ -6162,6 +6462,16 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.5)':
|
||||
dependencies:
|
||||
'@babel/core': 7.28.5
|
||||
'@babel/helper-plugin-utils': 7.27.1
|
||||
|
||||
'@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.5)':
|
||||
dependencies:
|
||||
'@babel/core': 7.28.5
|
||||
'@babel/helper-plugin-utils': 7.27.1
|
||||
|
||||
'@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.10)':
|
||||
dependencies:
|
||||
'@babel/core': 7.26.10
|
||||
@@ -6358,6 +6668,12 @@ snapshots:
|
||||
'@babel/parser': 7.27.0
|
||||
'@babel/types': 7.27.0
|
||||
|
||||
'@babel/template@7.27.2':
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.27.1
|
||||
'@babel/parser': 7.28.5
|
||||
'@babel/types': 7.28.5
|
||||
|
||||
'@babel/traverse@7.27.0':
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.26.2
|
||||
@@ -6370,6 +6686,18 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@babel/traverse@7.28.5':
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.27.1
|
||||
'@babel/generator': 7.28.5
|
||||
'@babel/helper-globals': 7.28.0
|
||||
'@babel/parser': 7.28.5
|
||||
'@babel/template': 7.27.2
|
||||
'@babel/types': 7.28.5
|
||||
debug: 4.4.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@babel/types@7.27.0':
|
||||
dependencies:
|
||||
'@babel/helper-string-parser': 7.25.9
|
||||
@@ -6379,7 +6707,11 @@ snapshots:
|
||||
dependencies:
|
||||
'@babel/helper-string-parser': 7.27.1
|
||||
'@babel/helper-validator-identifier': 7.27.1
|
||||
optional: true
|
||||
|
||||
'@babel/types@7.28.5':
|
||||
dependencies:
|
||||
'@babel/helper-string-parser': 7.27.1
|
||||
'@babel/helper-validator-identifier': 7.28.5
|
||||
|
||||
'@biomejs/biome@1.9.4':
|
||||
optionalDependencies:
|
||||
@@ -6581,6 +6913,11 @@ snapshots:
|
||||
|
||||
'@fontsource/roboto@5.2.5': {}
|
||||
|
||||
'@gsap/react@2.1.2(gsap@3.14.2)(react@19.2.3)':
|
||||
dependencies:
|
||||
gsap: 3.14.2
|
||||
react: 19.2.3
|
||||
|
||||
'@iconify-json/fa6-brands@1.2.5':
|
||||
dependencies:
|
||||
'@iconify/types': 2.0.0
|
||||
@@ -6814,12 +7151,22 @@ snapshots:
|
||||
dependencies:
|
||||
minipass: 7.1.2
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.13':
|
||||
dependencies:
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
'@jridgewell/trace-mapping': 0.3.31
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.8':
|
||||
dependencies:
|
||||
'@jridgewell/set-array': 1.2.1
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
'@jridgewell/trace-mapping': 0.3.25
|
||||
|
||||
'@jridgewell/remapping@2.3.5':
|
||||
dependencies:
|
||||
'@jridgewell/gen-mapping': 0.3.8
|
||||
'@jridgewell/trace-mapping': 0.3.25
|
||||
|
||||
'@jridgewell/resolve-uri@3.1.2': {}
|
||||
|
||||
'@jridgewell/set-array@1.2.1': {}
|
||||
@@ -6836,6 +7183,11 @@ snapshots:
|
||||
'@jridgewell/resolve-uri': 3.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
|
||||
'@jridgewell/trace-mapping@0.3.31':
|
||||
dependencies:
|
||||
'@jridgewell/resolve-uri': 3.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
|
||||
'@mapbox/node-pre-gyp@2.0.0':
|
||||
dependencies:
|
||||
consola: 3.4.2
|
||||
@@ -6927,6 +7279,8 @@ snapshots:
|
||||
'@pkgjs/parseargs@0.11.0':
|
||||
optional: true
|
||||
|
||||
'@rolldown/pluginutils@1.0.0-beta.27': {}
|
||||
|
||||
'@rollup/plugin-alias@3.1.9(rollup@2.79.2)':
|
||||
dependencies:
|
||||
rollup: 2.79.2
|
||||
@@ -7279,23 +7633,19 @@ snapshots:
|
||||
'@types/babel__generator': 7.27.0
|
||||
'@types/babel__template': 7.4.4
|
||||
'@types/babel__traverse': 7.28.0
|
||||
optional: true
|
||||
|
||||
'@types/babel__generator@7.27.0':
|
||||
dependencies:
|
||||
'@babel/types': 7.28.2
|
||||
optional: true
|
||||
|
||||
'@types/babel__template@7.4.4':
|
||||
dependencies:
|
||||
'@babel/parser': 7.28.0
|
||||
'@babel/types': 7.28.2
|
||||
optional: true
|
||||
|
||||
'@types/babel__traverse@7.28.0':
|
||||
dependencies:
|
||||
'@babel/types': 7.28.2
|
||||
optional: true
|
||||
|
||||
'@types/debug@4.1.12':
|
||||
dependencies:
|
||||
@@ -7342,6 +7692,14 @@ snapshots:
|
||||
|
||||
'@types/parse-json@4.0.2': {}
|
||||
|
||||
'@types/react-dom@19.2.3(@types/react@19.2.7)':
|
||||
dependencies:
|
||||
'@types/react': 19.2.7
|
||||
|
||||
'@types/react@19.2.7':
|
||||
dependencies:
|
||||
csstype: 3.2.3
|
||||
|
||||
'@types/resolve@1.17.1':
|
||||
dependencies:
|
||||
'@types/node': 22.14.1
|
||||
@@ -7370,8 +7728,9 @@ snapshots:
|
||||
|
||||
'@ungap/structured-clone@1.3.0': {}
|
||||
|
||||
'@vercel/analytics@1.5.0(svelte@5.28.2)':
|
||||
'@vercel/analytics@1.5.0(react@19.2.3)(svelte@5.28.2)':
|
||||
optionalDependencies:
|
||||
react: 19.2.3
|
||||
svelte: 5.28.2
|
||||
|
||||
'@vercel/functions@2.2.13':
|
||||
@@ -7409,6 +7768,18 @@ snapshots:
|
||||
optionalDependencies:
|
||||
ajv: 6.12.6
|
||||
|
||||
'@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@22.14.1)(jiti@1.21.7)(lightningcss@1.29.3)(sass@1.80.4)(stylus@0.64.0)(terser@5.39.0)(yaml@2.7.0))':
|
||||
dependencies:
|
||||
'@babel/core': 7.28.5
|
||||
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5)
|
||||
'@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.5)
|
||||
'@rolldown/pluginutils': 1.0.0-beta.27
|
||||
'@types/babel__core': 7.20.5
|
||||
react-refresh: 0.17.0
|
||||
vite: 6.4.1(@types/node@22.14.1)(jiti@1.21.7)(lightningcss@1.29.3)(sass@1.80.4)(stylus@0.64.0)(terser@5.39.0)(yaml@2.7.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@volar/kit@2.4.12(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@volar/language-service': 2.4.12
|
||||
@@ -8076,6 +8447,8 @@ snapshots:
|
||||
dependencies:
|
||||
css-tree: 2.2.1
|
||||
|
||||
csstype@3.2.3: {}
|
||||
|
||||
data-view-buffer@1.0.2:
|
||||
dependencies:
|
||||
call-bound: 1.0.4
|
||||
@@ -8614,6 +8987,8 @@ snapshots:
|
||||
|
||||
graceful-fs@4.2.11: {}
|
||||
|
||||
gsap@3.14.2: {}
|
||||
|
||||
gzip-size@3.0.0:
|
||||
dependencies:
|
||||
duplexer: 0.1.2
|
||||
@@ -10296,6 +10671,15 @@ snapshots:
|
||||
dependencies:
|
||||
safe-buffer: 5.2.1
|
||||
|
||||
react-dom@19.2.3(react@19.2.3):
|
||||
dependencies:
|
||||
react: 19.2.3
|
||||
scheduler: 0.27.0
|
||||
|
||||
react-refresh@0.17.0: {}
|
||||
|
||||
react@19.2.3: {}
|
||||
|
||||
read-cache@1.0.0:
|
||||
dependencies:
|
||||
pify: 2.3.0
|
||||
@@ -10701,6 +11085,8 @@ snapshots:
|
||||
|
||||
sax@1.4.1: {}
|
||||
|
||||
scheduler@0.27.0: {}
|
||||
|
||||
scrl@2.0.0: {}
|
||||
|
||||
semver@6.3.1: {}
|
||||
@@ -11372,6 +11758,24 @@ snapshots:
|
||||
terser: 5.39.0
|
||||
yaml: 2.7.0
|
||||
|
||||
vite@6.4.1(@types/node@22.14.1)(jiti@1.21.7)(lightningcss@1.29.3)(sass@1.80.4)(stylus@0.64.0)(terser@5.39.0)(yaml@2.7.0):
|
||||
dependencies:
|
||||
esbuild: 0.25.3
|
||||
fdir: 6.4.4(picomatch@4.0.2)
|
||||
picomatch: 4.0.2
|
||||
postcss: 8.5.3
|
||||
rollup: 4.40.1
|
||||
tinyglobby: 0.2.13
|
||||
optionalDependencies:
|
||||
'@types/node': 22.14.1
|
||||
fsevents: 2.3.3
|
||||
jiti: 1.21.7
|
||||
lightningcss: 1.29.3
|
||||
sass: 1.80.4
|
||||
stylus: 0.64.0
|
||||
terser: 5.39.0
|
||||
yaml: 2.7.0
|
||||
|
||||
vitefu@1.0.6(vite@6.3.3(@types/node@22.14.1)(jiti@1.21.7)(lightningcss@1.29.3)(sass@1.80.4)(stylus@0.64.0)(terser@5.39.0)(yaml@2.7.0)):
|
||||
optionalDependencies:
|
||||
vite: 6.3.3(@types/node@22.14.1)(jiti@1.21.7)(lightningcss@1.29.3)(sass@1.80.4)(stylus@0.64.0)(terser@5.39.0)(yaml@2.7.0)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import postcssImport from 'postcss-import';
|
||||
import postcssNesting from 'tailwindcss/nesting/index.js';
|
||||
import tailwindcss from 'tailwindcss';
|
||||
import postcssImport from "postcss-import";
|
||||
import tailwindcss from "tailwindcss";
|
||||
import postcssNesting from "tailwindcss/nesting/index.js";
|
||||
|
||||
export default {
|
||||
plugins: {
|
||||
'postcss-import': postcssImport, // to combine multiple css files
|
||||
'tailwindcss/nesting': postcssNesting,
|
||||
"postcss-import": postcssImport, // to combine multiple css files
|
||||
"tailwindcss/nesting": postcssNesting,
|
||||
tailwindcss: tailwindcss,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
* Static Random Pic API
|
||||
* Generated by build script
|
||||
*/
|
||||
(function() {
|
||||
var counts = {"h":979,"v":3596};
|
||||
var domain = 'https://pic.acofork.com';
|
||||
(() => {
|
||||
var counts = { h: 979, v: 3596 };
|
||||
var domain = "https://pic.acofork.com";
|
||||
|
||||
// State management for session consistency
|
||||
var sessionRandomH = null;
|
||||
@@ -12,49 +12,55 @@
|
||||
|
||||
// Helper: Get random URL for a type (h or v), persistent per session
|
||||
function getRandomUrl(type) {
|
||||
if (!counts[type] || counts[type] === 0) return '';
|
||||
if (!counts[type] || counts[type] === 0) return "";
|
||||
|
||||
// Return existing session URL if available
|
||||
if (type === 'h' && sessionRandomH) return sessionRandomH;
|
||||
if (type === 'v' && sessionRandomV) return sessionRandomV;
|
||||
if (type === "h" && sessionRandomH) return sessionRandomH;
|
||||
if (type === "v" && sessionRandomV) return sessionRandomV;
|
||||
|
||||
// Generate new if not exists
|
||||
var num = Math.floor(Math.random() * counts[type]) + 1;
|
||||
var url = domain + '/ri/' + type + '/' + num + '.webp';
|
||||
var url = domain + "/ri/" + type + "/" + num + ".webp";
|
||||
|
||||
// Save to session state
|
||||
if (type === 'h') sessionRandomH = url;
|
||||
if (type === 'v') sessionRandomV = url;
|
||||
if (type === "h") sessionRandomH = url;
|
||||
if (type === "v") sessionRandomV = url;
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
// Expose global functions
|
||||
window.getRandomPicH = function() { return getRandomUrl('h'); };
|
||||
window.getRandomPicV = function() { return getRandomUrl('v'); };
|
||||
window.getRandomPicH = () => getRandomUrl("h");
|
||||
window.getRandomPicV = () => getRandomUrl("v");
|
||||
|
||||
// 1. Logic for Background (Customized based on user request)
|
||||
function setRandomBackground() {
|
||||
// Get random URL using the helper (Dynamic count & domain)
|
||||
const bgUrl = getRandomUrl('h');
|
||||
const bgUrl = getRandomUrl("h");
|
||||
|
||||
// Find the background box element
|
||||
const bgBox = document.getElementById('bg-box');
|
||||
const bgBox = document.getElementById("bg-box");
|
||||
|
||||
if (bgBox) {
|
||||
// Preload image
|
||||
const img = new Image();
|
||||
img.onload = function() {
|
||||
img.onload = () => {
|
||||
bgBox.style.backgroundImage = `url('${bgUrl}')`;
|
||||
bgBox.classList.add('loaded');
|
||||
console.log('Random background loaded:', bgUrl);
|
||||
bgBox.classList.add("loaded");
|
||||
console.log("Random background loaded:", bgUrl);
|
||||
|
||||
// Set CSS variables for transparency effects
|
||||
document.documentElement.style.setProperty('--card-bg', 'var(--card-bg-transparent)');
|
||||
document.documentElement.style.setProperty('--float-panel-bg', 'var(--float-panel-bg-transparent)');
|
||||
document.documentElement.style.setProperty(
|
||||
"--card-bg",
|
||||
"var(--card-bg-transparent)",
|
||||
);
|
||||
document.documentElement.style.setProperty(
|
||||
"--float-panel-bg",
|
||||
"var(--float-panel-bg-transparent)",
|
||||
);
|
||||
};
|
||||
img.onerror = function() {
|
||||
console.error('Failed to load background image:', bgUrl);
|
||||
img.onerror = () => {
|
||||
console.error("Failed to load background image:", bgUrl);
|
||||
};
|
||||
img.src = bgUrl;
|
||||
} else {
|
||||
@@ -66,35 +72,38 @@
|
||||
|
||||
// 2. Logic for Image Tags (Generic)
|
||||
function initImgTags() {
|
||||
var imgTags = document.getElementsByTagName('img');
|
||||
var imgTags = document.getElementsByTagName("img");
|
||||
for (var i = 0; i < imgTags.length; i++) {
|
||||
var img = imgTags[i];
|
||||
var alt = img.getAttribute('alt');
|
||||
var src = img.getAttribute('src');
|
||||
var alt = img.getAttribute("alt");
|
||||
var src = img.getAttribute("src");
|
||||
|
||||
if (alt === 'random:h' || (src && src.indexOf('/random/h') !== -1)) {
|
||||
img.src = getRandomUrl('h');
|
||||
} else if (alt === 'random:v' || (src && src.indexOf('/random/v') !== -1)) {
|
||||
img.src = getRandomUrl('v');
|
||||
if (alt === "random:h" || (src && src.indexOf("/random/h") !== -1)) {
|
||||
img.src = getRandomUrl("h");
|
||||
} else if (
|
||||
alt === "random:v" ||
|
||||
(src && src.indexOf("/random/v") !== -1)
|
||||
) {
|
||||
img.src = getRandomUrl("v");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper for generic data-random-bg (as a backup or secondary feature)
|
||||
function initGenericBackgrounds() {
|
||||
var bgElements = document.querySelectorAll('[data-random-bg]');
|
||||
bgElements.forEach(function(el) {
|
||||
var bgElements = document.querySelectorAll("[data-random-bg]");
|
||||
bgElements.forEach((el) => {
|
||||
// Skip if it is the bg-box we already handled (though setRandomBackground handles #bg-box specifically)
|
||||
if (el.id === 'bg-box') return;
|
||||
if (el.id === "bg-box") return;
|
||||
|
||||
var type = el.getAttribute('data-random-bg');
|
||||
if (type === 'h' || type === 'v') {
|
||||
var type = el.getAttribute("data-random-bg");
|
||||
if (type === "h" || type === "v") {
|
||||
var url = getRandomUrl(type);
|
||||
if (url) {
|
||||
var img = new Image();
|
||||
img.onload = function() {
|
||||
img.onload = () => {
|
||||
el.style.backgroundImage = 'url("' + url + '")';
|
||||
el.classList.add('loaded');
|
||||
el.classList.add("loaded");
|
||||
};
|
||||
img.src = url;
|
||||
}
|
||||
@@ -108,8 +117,8 @@
|
||||
}
|
||||
|
||||
// Run on initial load
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
@@ -118,17 +127,17 @@
|
||||
function setupSwup() {
|
||||
if (window.swup && window.swup.hooks) {
|
||||
// Register hook for content replacement
|
||||
window.swup.hooks.on('content:replace', init);
|
||||
console.log('Random Pic API: Registered with Swup hooks.');
|
||||
window.swup.hooks.on("content:replace", init);
|
||||
console.log("Random Pic API: Registered with Swup hooks.");
|
||||
}
|
||||
}
|
||||
|
||||
if (window.swup) {
|
||||
setupSwup();
|
||||
} else {
|
||||
document.addEventListener('swup:enable', setupSwup);
|
||||
document.addEventListener("swup:enable", setupSwup);
|
||||
}
|
||||
|
||||
// Legacy Swup support
|
||||
document.addEventListener('swup:contentReplaced', init);
|
||||
document.addEventListener("swup:contentReplaced", init);
|
||||
})();
|
||||
@@ -1,5 +1,5 @@
|
||||
(function (global) {
|
||||
const cacheKey = 'umami-share-cache';
|
||||
((global) => {
|
||||
const cacheKey = "umami-share-cache";
|
||||
const cacheTTL = 3600_000; // 1h
|
||||
|
||||
async function fetchShareData(baseUrl, shareId) {
|
||||
@@ -16,10 +16,13 @@
|
||||
}
|
||||
const res = await fetch(`${baseUrl}/api/share/${shareId}`);
|
||||
if (!res.ok) {
|
||||
throw new Error('获取 Umami 分享信息失败');
|
||||
throw new Error("获取 Umami 分享信息失败");
|
||||
}
|
||||
const data = await res.json();
|
||||
localStorage.setItem(cacheKey, JSON.stringify({ timestamp: Date.now(), value: data }));
|
||||
localStorage.setItem(
|
||||
cacheKey,
|
||||
JSON.stringify({ timestamp: Date.now(), value: data }),
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -30,21 +33,28 @@
|
||||
* @param {string} shareId
|
||||
* @returns {Promise<{websiteId: string, token: string}>}
|
||||
*/
|
||||
global.getUmamiShareData = function (baseUrl, shareId) {
|
||||
global.getUmamiShareData = (baseUrl, shareId) => {
|
||||
if (!global.__umamiSharePromise) {
|
||||
global.__umamiSharePromise = fetchShareData(baseUrl, shareId).catch((err) => {
|
||||
global.__umamiSharePromise = fetchShareData(baseUrl, shareId).catch(
|
||||
(err) => {
|
||||
delete global.__umamiSharePromise;
|
||||
throw err;
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
return global.__umamiSharePromise;
|
||||
};
|
||||
|
||||
global.clearUmamiShareCache = function () {
|
||||
global.clearUmamiShareCache = () => {
|
||||
localStorage.removeItem(cacheKey);
|
||||
delete global.__umamiSharePromise;
|
||||
};
|
||||
|
||||
// 初始化全局缓存 Map
|
||||
if (!global.__umamiDataCache) {
|
||||
global.__umamiDataCache = new Map();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Umami 统计数据
|
||||
* 自动处理 token 获取和过期重试
|
||||
@@ -53,25 +63,38 @@
|
||||
* @param {object} queryParams
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
global.fetchUmamiStats = async function (baseUrl, shareId, queryParams) {
|
||||
global.fetchUmamiStats = async (baseUrl, shareId, queryParams) => {
|
||||
// 生成缓存键:baseUrl + shareId + queryParams的字符串表示
|
||||
const cacheKey = `${baseUrl}|${shareId}|${JSON.stringify(queryParams)}`;
|
||||
|
||||
// 检查全局内存缓存
|
||||
if (global.__umamiDataCache.has(cacheKey)) {
|
||||
const data = global.__umamiDataCache.get(cacheKey);
|
||||
// 标记数据来自缓存
|
||||
return { ...data, _fromCache: true };
|
||||
}
|
||||
|
||||
async function doFetch(isRetry = false) {
|
||||
const { websiteId, token } = await global.getUmamiShareData(baseUrl, shareId);
|
||||
const { websiteId, token } = await global.getUmamiShareData(
|
||||
baseUrl,
|
||||
shareId,
|
||||
);
|
||||
const currentTimestamp = Date.now();
|
||||
const params = new URLSearchParams({
|
||||
startAt: 0,
|
||||
endAt: currentTimestamp,
|
||||
unit: 'hour',
|
||||
timezone: queryParams.timezone || 'Asia/Shanghai',
|
||||
unit: "hour",
|
||||
timezone: queryParams.timezone || "Asia/Shanghai",
|
||||
compare: false,
|
||||
...queryParams
|
||||
...queryParams,
|
||||
});
|
||||
|
||||
const statsUrl = `${baseUrl}/api/websites/${websiteId}/stats?${params.toString()}`;
|
||||
|
||||
const res = await fetch(statsUrl, {
|
||||
headers: {
|
||||
'x-umami-share-token': token
|
||||
}
|
||||
"x-umami-share-token": token,
|
||||
},
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
@@ -79,13 +102,15 @@
|
||||
global.clearUmamiShareCache();
|
||||
return doFetch(true);
|
||||
}
|
||||
throw new Error('获取统计数据失败');
|
||||
throw new Error("获取统计数据失败");
|
||||
}
|
||||
|
||||
return await res.json();
|
||||
const data = await res.json();
|
||||
// 写入全局缓存
|
||||
global.__umamiDataCache.set(cacheKey, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
return doFetch();
|
||||
};
|
||||
|
||||
})(window);
|
||||
@@ -1,9 +1,9 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { glob } from 'glob';
|
||||
import { fileURLToPath } from 'url';
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { glob } from "glob";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
@@ -14,22 +14,30 @@ const __dirname = path.dirname(__filename);
|
||||
* 查找 src/content/assets 中未被引用的图片并删除
|
||||
*/
|
||||
|
||||
const CONTENT_DIR = path.join(process.cwd(), 'src/content');
|
||||
const POSTS_DIR = path.join(CONTENT_DIR, 'posts');
|
||||
const ASSETS_DIR = path.join(CONTENT_DIR, 'assets');
|
||||
const CONTENT_DIR = path.join(process.cwd(), "src/content");
|
||||
const POSTS_DIR = path.join(CONTENT_DIR, "posts");
|
||||
const ASSETS_DIR = path.join(CONTENT_DIR, "assets");
|
||||
|
||||
// 支持的图片格式
|
||||
const IMAGE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg', '.avif'];
|
||||
const IMAGE_EXTENSIONS = [
|
||||
".jpg",
|
||||
".jpeg",
|
||||
".png",
|
||||
".gif",
|
||||
".webp",
|
||||
".svg",
|
||||
".avif",
|
||||
];
|
||||
|
||||
/**
|
||||
* 获取所有 markdown 文件
|
||||
*/
|
||||
async function getAllMarkdownFiles() {
|
||||
try {
|
||||
const pattern = path.join(POSTS_DIR, '**/*.md').replace(/\\/g, '/');
|
||||
const pattern = path.join(POSTS_DIR, "**/*.md").replace(/\\/g, "/");
|
||||
return await glob(pattern);
|
||||
} catch (error) {
|
||||
console.error('获取 markdown 文件失败:', error.message);
|
||||
console.error("获取 markdown 文件失败:", error.message);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -39,11 +47,13 @@ async function getAllMarkdownFiles() {
|
||||
*/
|
||||
async function getAllImageFiles() {
|
||||
try {
|
||||
const extensions = IMAGE_EXTENSIONS.join(',');
|
||||
const pattern = path.join(ASSETS_DIR, `**/*{${extensions}}`).replace(/\\/g, '/');
|
||||
const extensions = IMAGE_EXTENSIONS.join(",");
|
||||
const pattern = path
|
||||
.join(ASSETS_DIR, `**/*{${extensions}}`)
|
||||
.replace(/\\/g, "/");
|
||||
return await glob(pattern);
|
||||
} catch (error) {
|
||||
console.error('获取图片文件失败:', error.message);
|
||||
console.error("获取图片文件失败:", error.message);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -55,7 +65,8 @@ function extractImageReferences(content) {
|
||||
const references = new Set();
|
||||
|
||||
// 匹配 YAML frontmatter 中的 image 字段(支持带引号和不带引号的值)
|
||||
const yamlImageRegex = /^---[\s\S]*?image:\s*(?:['"]([^'"]+)['"]|([^\s\n]+))[\s\S]*?^---/m;
|
||||
const yamlImageRegex =
|
||||
/^---[\s\S]*?image:\s*(?:['"]([^'"]+)['"]|([^\s\n]+))[\s\S]*?^---/m;
|
||||
let match = yamlImageRegex.exec(content);
|
||||
if (match) {
|
||||
// match[1] 是带引号的值,match[2] 是不带引号的值
|
||||
@@ -75,7 +86,8 @@ function extractImageReferences(content) {
|
||||
}
|
||||
|
||||
// 匹配 Astro Image 组件引用
|
||||
const astroImageRegex = /import\s+.*?\s+from\s+["']([^"']+\.(jpg|jpeg|png|gif|webp|svg|avif))["']/gi;
|
||||
const astroImageRegex =
|
||||
/import\s+.*?\s+from\s+["']([^"']+\.(jpg|jpeg|png|gif|webp|svg|avif))["']/gi;
|
||||
while ((match = astroImageRegex.exec(content)) !== null) {
|
||||
references.add(match[1]);
|
||||
}
|
||||
@@ -88,17 +100,17 @@ function extractImageReferences(content) {
|
||||
*/
|
||||
function normalizePath(imagePath, markdownFilePath) {
|
||||
// 跳过外部 URL
|
||||
if (imagePath.startsWith('http://') || imagePath.startsWith('https://')) {
|
||||
if (imagePath.startsWith("http://") || imagePath.startsWith("https://")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 跳过以 / 开头的绝对路径(通常指向 public 目录)
|
||||
if (imagePath.startsWith('/')) {
|
||||
if (imagePath.startsWith("/")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 处理相对路径
|
||||
if (imagePath.startsWith('./') || imagePath.startsWith('../')) {
|
||||
if (imagePath.startsWith("./") || imagePath.startsWith("../")) {
|
||||
const markdownDir = path.dirname(markdownFilePath);
|
||||
return path.resolve(markdownDir, imagePath);
|
||||
}
|
||||
@@ -112,7 +124,7 @@ function normalizePath(imagePath, markdownFilePath) {
|
||||
* 主函数
|
||||
*/
|
||||
async function cleanUnusedImages() {
|
||||
console.log('🔍 开始扫描未使用的图片资源...');
|
||||
console.log("🔍 开始扫描未使用的图片资源...");
|
||||
|
||||
// 检查目录是否存在
|
||||
if (!fs.existsSync(POSTS_DIR)) {
|
||||
@@ -133,7 +145,7 @@ async function cleanUnusedImages() {
|
||||
console.log(`🖼️ 找到 ${imageFiles.length} 个图片文件`);
|
||||
|
||||
if (imageFiles.length === 0) {
|
||||
console.log('✅ 没有找到图片文件,无需清理');
|
||||
console.log("✅ 没有找到图片文件,无需清理");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -142,7 +154,7 @@ async function cleanUnusedImages() {
|
||||
|
||||
for (const mdFile of markdownFiles) {
|
||||
try {
|
||||
const content = fs.readFileSync(mdFile, 'utf-8');
|
||||
const content = fs.readFileSync(mdFile, "utf-8");
|
||||
const references = extractImageReferences(content);
|
||||
|
||||
for (const ref of references) {
|
||||
@@ -174,7 +186,7 @@ async function cleanUnusedImages() {
|
||||
console.log(`🗑️ 找到 ${unusedImages.length} 个未使用的图片`);
|
||||
|
||||
if (unusedImages.length === 0) {
|
||||
console.log('✅ 所有图片都在使用中,无需清理');
|
||||
console.log("✅ 所有图片都在使用中,无需清理");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -233,11 +245,12 @@ function cleanEmptyDirectories(dir) {
|
||||
// 运行脚本
|
||||
// 检查是否直接运行此脚本
|
||||
const scriptPath = fileURLToPath(import.meta.url);
|
||||
const isMainModule = process.argv[1] && path.resolve(process.argv[1]) === path.resolve(scriptPath);
|
||||
const isMainModule =
|
||||
process.argv[1] && path.resolve(process.argv[1]) === path.resolve(scriptPath);
|
||||
|
||||
if (isMainModule) {
|
||||
cleanUnusedImages().catch(error => {
|
||||
console.error('❌ 脚本执行失败:', error.message);
|
||||
cleanUnusedImages().catch((error) => {
|
||||
console.error("❌ 脚本执行失败:", error.message);
|
||||
console.error(error.stack);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
/* This is a script to create a new post markdown file with front-matter */
|
||||
|
||||
import fs from "fs"
|
||||
import path from "path"
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
function getDate() {
|
||||
const today = new Date()
|
||||
const year = today.getFullYear()
|
||||
const month = String(today.getMonth() + 1).padStart(2, "0")
|
||||
const day = String(today.getDate()).padStart(2, "0")
|
||||
const hours = String(today.getHours()).padStart(2, "0")
|
||||
const minutes = String(today.getMinutes()).padStart(2, "0")
|
||||
const seconds = String(today.getSeconds()).padStart(2, "0")
|
||||
const today = new Date();
|
||||
const year = today.getFullYear();
|
||||
const month = String(today.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(today.getDate()).padStart(2, "0");
|
||||
const hours = String(today.getHours()).padStart(2, "0");
|
||||
const minutes = String(today.getMinutes()).padStart(2, "0");
|
||||
const seconds = String(today.getSeconds()).padStart(2, "0");
|
||||
|
||||
return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`
|
||||
return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`;
|
||||
}
|
||||
|
||||
const args = process.argv.slice(2)
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
if (args.length === 0) {
|
||||
console.error(`Error: No filename argument provided
|
||||
Usage: npm run new-post -- <filename>`)
|
||||
process.exit(1) // Terminate the script and return error code 1
|
||||
Usage: npm run new-post -- <filename>`);
|
||||
process.exit(1); // Terminate the script and return error code 1
|
||||
}
|
||||
|
||||
let fileName = args[0]
|
||||
let fileName = args[0];
|
||||
|
||||
// Add .md extension if not present
|
||||
const fileExtensionRegex = /\.(md|mdx)$/i
|
||||
const fileExtensionRegex = /\.(md|mdx)$/i;
|
||||
if (!fileExtensionRegex.test(fileName)) {
|
||||
fileName += ".md"
|
||||
fileName += ".md";
|
||||
}
|
||||
|
||||
const targetDir = "./src/content/posts/"
|
||||
const fullPath = path.join(targetDir, fileName)
|
||||
const targetDir = "./src/content/posts/";
|
||||
const fullPath = path.join(targetDir, fileName);
|
||||
|
||||
if (fs.existsSync(fullPath)) {
|
||||
console.error(`Error: File ${fullPath} already exists `)
|
||||
process.exit(1)
|
||||
console.error(`Error: File ${fullPath} already exists `);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// recursive mode creates multi-level directories
|
||||
const dirPath = path.dirname(fullPath)
|
||||
const dirPath = path.dirname(fullPath);
|
||||
if (!fs.existsSync(dirPath)) {
|
||||
fs.mkdirSync(dirPath, { recursive: true })
|
||||
fs.mkdirSync(dirPath, { recursive: true });
|
||||
}
|
||||
|
||||
const content = `---
|
||||
@@ -54,8 +54,8 @@ image: ''
|
||||
draft: false
|
||||
lang: ''
|
||||
---
|
||||
`
|
||||
`;
|
||||
|
||||
fs.writeFileSync(path.join(targetDir, fileName), content)
|
||||
fs.writeFileSync(path.join(targetDir, fileName), content);
|
||||
|
||||
console.log(`Post ${fullPath} created`)
|
||||
console.log(`Post ${fullPath} created`);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
|
||||
import { execSync } from "node:child_process";
|
||||
import { profileConfig } from "../config";
|
||||
import { url } from "../utils/url-utils";
|
||||
import { execSync } from "child_process";
|
||||
|
||||
const currentYear = new Date().getFullYear();
|
||||
|
||||
@@ -10,15 +10,15 @@ let commitHash = "unknown";
|
||||
let buildDate = "unknown";
|
||||
|
||||
try {
|
||||
commitHash = execSync('git rev-parse --short=7 HEAD').toString().trim();
|
||||
commitHash = execSync("git rev-parse --short=7 HEAD").toString().trim();
|
||||
|
||||
const date = new Date();
|
||||
const year = date.getFullYear();
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
||||
const day = date.getDate().toString().padStart(2, '0');
|
||||
const hours = date.getHours().toString().padStart(2, '0');
|
||||
const minutes = date.getMinutes().toString().padStart(2, '0');
|
||||
const seconds = date.getSeconds().toString().padStart(2, '0');
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, "0");
|
||||
const day = date.getDate().toString().padStart(2, "0");
|
||||
const hours = date.getHours().toString().padStart(2, "0");
|
||||
const minutes = date.getMinutes().toString().padStart(2, "0");
|
||||
const seconds = date.getSeconds().toString().padStart(2, "0");
|
||||
buildDate = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
} catch (e) {
|
||||
console.warn("Failed to get git info", e);
|
||||
|
||||
@@ -3,11 +3,11 @@ import path from "node:path";
|
||||
import type { CollectionEntry } from "astro:content";
|
||||
import { Icon } from "astro-icon/components";
|
||||
|
||||
import { getDir } from "../utils/url-utils";
|
||||
import { umamiConfig } from "../config";
|
||||
import { formatDateToYYYYMMDD } from "../utils/date-utils";
|
||||
import { getDir } from "../utils/url-utils";
|
||||
import PostMetadata from "./PostMeta.astro";
|
||||
import ImageWrapper from "./misc/ImageWrapper.astro";
|
||||
import { umamiConfig } from "../config";
|
||||
|
||||
interface Props {
|
||||
class?: string;
|
||||
@@ -21,16 +21,8 @@ interface Props {
|
||||
draft: boolean;
|
||||
style: string;
|
||||
}
|
||||
const {
|
||||
entry,
|
||||
title,
|
||||
url,
|
||||
published,
|
||||
updated,
|
||||
image,
|
||||
description,
|
||||
style,
|
||||
} = Astro.props;
|
||||
const { entry, title, url, published, updated, image, description, style } =
|
||||
Astro.props;
|
||||
|
||||
const isPinned = entry.data.pinned === true;
|
||||
const className = Astro.props.class;
|
||||
@@ -108,3 +100,72 @@ const { remarkPluginFrontmatter } = await entry.render();
|
||||
|
||||
<style define:vars={{coverWidth}}>
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// 数字动画函数
|
||||
function animateValue(obj, start, end, duration) {
|
||||
let startTimestamp = null;
|
||||
const step = (timestamp) => {
|
||||
if (!startTimestamp) startTimestamp = timestamp;
|
||||
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
|
||||
obj.innerHTML = Math.floor(progress * (end - start) + start);
|
||||
if (progress < 1) {
|
||||
window.requestAnimationFrame(step);
|
||||
} else {
|
||||
obj.innerHTML = end;
|
||||
}
|
||||
};
|
||||
window.requestAnimationFrame(step);
|
||||
}
|
||||
|
||||
async function loadCardStats() {
|
||||
const elements = document.querySelectorAll('.post-pageviews');
|
||||
|
||||
elements.forEach(async (el) => {
|
||||
// 如果元素已经处理过,且已有内容(非0),则不再处理
|
||||
if (el.classList.contains('processed') && el.textContent !== '0') return;
|
||||
|
||||
el.classList.add('processed');
|
||||
const url = el.dataset.url;
|
||||
const baseUrl = el.dataset.umamiBaseUrl;
|
||||
const shareId = el.dataset.umamiShareId;
|
||||
const timezone = el.dataset.umamiTimezone;
|
||||
|
||||
if (!baseUrl || !shareId) return;
|
||||
|
||||
try {
|
||||
// Check if fetchUmamiStats exists
|
||||
if (typeof window.fetchUmamiStats !== 'function') return;
|
||||
|
||||
const statsData = await window.fetchUmamiStats(baseUrl, shareId, {
|
||||
url: url,
|
||||
timezone: timezone
|
||||
});
|
||||
|
||||
const pageviews = (statsData.pageviews && statsData.pageviews.value) || statsData.pageviews || 0;
|
||||
|
||||
// 如果数据来自缓存,直接显示结果,跳过动画
|
||||
if (statsData._fromCache) {
|
||||
el.innerHTML = pageviews;
|
||||
return;
|
||||
}
|
||||
|
||||
const startVal = parseInt(el.textContent) || 0;
|
||||
|
||||
if (startVal !== pageviews) {
|
||||
// 只有当开始值是0的时候才播放动画(首次加载)
|
||||
if (startVal === 0) {
|
||||
animateValue(el, startVal, pageviews, 1000);
|
||||
} else {
|
||||
el.innerHTML = pageviews;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to load stats for', url, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', loadCardStats);
|
||||
document.addEventListener('swup:contentReplaced', loadCardStats);
|
||||
</script>
|
||||
@@ -1,9 +1,9 @@
|
||||
---
|
||||
import { Icon } from "astro-icon/components";
|
||||
|
||||
import { getDir, url } from "../utils/url-utils";
|
||||
import { formatDateToYYYYMMDD } from "../utils/date-utils";
|
||||
import { umamiConfig } from "../config";
|
||||
import { formatDateToYYYYMMDD } from "../utils/date-utils";
|
||||
import { url, getDir } from "../utils/url-utils";
|
||||
|
||||
interface Props {
|
||||
class: string;
|
||||
@@ -52,13 +52,13 @@ const className = Astro.props.class;
|
||||
<div class="meta-icon">
|
||||
<Icon name="material-symbols:visibility-outline-rounded" class="text-xl"></Icon>
|
||||
</div>
|
||||
<span class="text-50 text-sm font-medium" id={`page-views-${slug}`}>-</span>
|
||||
<span class="text-50 text-sm font-medium" id={`page-views-${slug}`}>0 次</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="meta-icon">
|
||||
<Icon name="material-symbols:person" class="text-xl"></Icon>
|
||||
</div>
|
||||
<span class="text-50 text-sm font-medium" id={`page-visitors-${slug}`}>-</span>
|
||||
<span class="text-50 text-sm font-medium" id={`page-visitors-${slug}`}>0 人</span>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
@@ -66,6 +66,21 @@ const className = Astro.props.class;
|
||||
|
||||
{slug && (
|
||||
<script define:vars={{ slug, umamiConfig }}>
|
||||
// 数字动画函数
|
||||
function animateValue(obj, start, end, duration, suffix = '') {
|
||||
let startTimestamp = null;
|
||||
const step = (timestamp) => {
|
||||
if (!startTimestamp) startTimestamp = timestamp;
|
||||
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
|
||||
obj.innerHTML = `${Math.floor(progress * (end - start) + start)} ${suffix}`;
|
||||
if (progress < 1) {
|
||||
window.requestAnimationFrame(step);
|
||||
} else {
|
||||
obj.innerHTML = `${end} ${suffix}`;
|
||||
}
|
||||
};
|
||||
window.requestAnimationFrame(step);
|
||||
}
|
||||
|
||||
// 获取访问量统计
|
||||
async function fetchPageViews() {
|
||||
@@ -76,19 +91,42 @@ const className = Astro.props.class;
|
||||
path: `eq./posts/${slug}/`
|
||||
});
|
||||
|
||||
const pageViews = statsData.pageviews || 0;
|
||||
const visits = statsData.visitors || 0;
|
||||
const pageViews = (statsData.pageviews && statsData.pageviews.value) || statsData.pageviews || 0;
|
||||
const visits = (statsData.visitors && statsData.visitors.value) || statsData.visitors || 0;
|
||||
|
||||
const viewsElement = document.getElementById(`page-views-${slug}`);
|
||||
const visitorsElement = document.getElementById(`page-visitors-${slug}`);
|
||||
if (viewsElement) viewsElement.textContent = `${pageViews} 次`;
|
||||
if (visitorsElement) visitorsElement.textContent = `${visits} 人`;
|
||||
|
||||
// 如果数据来自缓存,直接显示结果,跳过动画
|
||||
if (statsData._fromCache) {
|
||||
if (viewsElement) viewsElement.innerHTML = `${pageViews} 次`;
|
||||
if (visitorsElement) visitorsElement.innerHTML = `${visits} 人`;
|
||||
return;
|
||||
}
|
||||
|
||||
if (viewsElement) {
|
||||
const currentViews = parseInt(viewsElement.textContent) || 0;
|
||||
if (currentViews !== pageViews) {
|
||||
if (currentViews === 0) {
|
||||
animateValue(viewsElement, currentViews, pageViews, 1000, '次');
|
||||
} else {
|
||||
viewsElement.innerHTML = `${pageViews} 次`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (visitorsElement) {
|
||||
const currentVisits = parseInt(visitorsElement.textContent) || 0;
|
||||
if (currentVisits !== visits) {
|
||||
if (currentVisits === 0) {
|
||||
animateValue(visitorsElement, currentVisits, visits, 1000, '人');
|
||||
} else {
|
||||
visitorsElement.innerHTML = `${visits} 人`;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching page views:', error);
|
||||
const viewsElement = document.getElementById(`page-views-${slug}`);
|
||||
const visitorsElement = document.getElementById(`page-visitors-${slug}`);
|
||||
if (viewsElement) viewsElement.textContent = '-';
|
||||
if (visitorsElement) visitorsElement.textContent = '-';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script lang="ts">
|
||||
|
||||
import Icon from "@iconify/svelte";
|
||||
import { url } from "@utils/url-utils.ts";
|
||||
import { onMount } from "svelte";
|
||||
@@ -17,6 +16,7 @@ let keywordDesktop = "";
|
||||
let keywordMobile = "";
|
||||
let result: SearchResult[] = [];
|
||||
let isSearching = false;
|
||||
// biome-ignore lint/suspicious/noExplicitAny: Temporary usage of any for posts array
|
||||
let posts: any[] = [];
|
||||
|
||||
const togglePanel = () => {
|
||||
@@ -59,33 +59,35 @@ const search = async (keyword: string, isDesktop: boolean): Promise<void> => {
|
||||
const urlPath = `/posts/${post.link}`;
|
||||
|
||||
// 支持内容搜索和URL后缀搜索
|
||||
return searchText.includes(keywordLower) ||
|
||||
return (
|
||||
searchText.includes(keywordLower) ||
|
||||
urlPath.toLowerCase().includes(keywordLower) ||
|
||||
post.link.toLowerCase().includes(keywordLower);
|
||||
post.link.toLowerCase().includes(keywordLower)
|
||||
);
|
||||
})
|
||||
.map((post) => {
|
||||
const contentLower = post.content.toLowerCase();
|
||||
const keywordLower = keyword.toLowerCase();
|
||||
const contentIndex = contentLower.indexOf(keywordLower);
|
||||
|
||||
let excerpt = '';
|
||||
let excerpt = "";
|
||||
if (contentIndex !== -1) {
|
||||
const start = Math.max(0, contentIndex - 50);
|
||||
const end = Math.min(post.content.length, contentIndex + 100);
|
||||
excerpt = post.content.substring(start, end);
|
||||
if (start > 0) excerpt = '...' + excerpt;
|
||||
if (end < post.content.length) excerpt = excerpt + '...';
|
||||
if (start > 0) excerpt = `...${excerpt}`;
|
||||
if (end < post.content.length) excerpt = `${excerpt}...`;
|
||||
} else {
|
||||
excerpt = post.description || post.content.substring(0, 150) + '...';
|
||||
excerpt = post.description || `${post.content.substring(0, 150)}...`;
|
||||
}
|
||||
|
||||
return {
|
||||
url: url(`/posts/${post.link}/`),
|
||||
meta: {
|
||||
title: post.title
|
||||
title: post.title,
|
||||
},
|
||||
excerpt: highlightText(excerpt, keyword),
|
||||
urlPath: `/posts/${post.link}`
|
||||
urlPath: `/posts/${post.link}`,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -124,7 +126,10 @@ onMount(async () => {
|
||||
title: item.querySelector("title")?.textContent || "",
|
||||
description: item.querySelector("description")?.textContent || "",
|
||||
content: content,
|
||||
link: item.querySelector("link")?.textContent?.replace(/.*\/posts\/(.*?)\//, "$1") || "",
|
||||
link:
|
||||
item
|
||||
.querySelector("link")
|
||||
?.textContent?.replace(/.*\/posts\/(.*?)\//, "$1") || "",
|
||||
};
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
@@ -9,8 +9,8 @@ interface Props {
|
||||
basePath?: string;
|
||||
}
|
||||
import { Image } from "astro:assets";
|
||||
import { url } from "../../utils/url-utils";
|
||||
import { imageFallbackConfig, siteConfig } from "../../config";
|
||||
import { url } from "../../utils/url-utils";
|
||||
|
||||
const { id, src, alt, position = "center", basePath = "/" } = Astro.props;
|
||||
const className = Astro.props.class;
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { AUTO_MODE, DARK_MODE, LIGHT_MODE } from "@constants/constants";
|
||||
import Icon from "@iconify/svelte";
|
||||
import {
|
||||
getDefaultHue,
|
||||
getHue,
|
||||
setHue,
|
||||
getStoredTheme,
|
||||
setTheme,
|
||||
getRainbowMode,
|
||||
setRainbowMode,
|
||||
getRainbowSpeed,
|
||||
setRainbowSpeed,
|
||||
getBgBlur,
|
||||
getDefaultHue,
|
||||
getDevMode,
|
||||
getDevServer,
|
||||
getHideBg,
|
||||
getHue,
|
||||
getRainbowMode,
|
||||
getRainbowSpeed,
|
||||
getStoredTheme,
|
||||
setBgBlur,
|
||||
setBgHueRotate,
|
||||
getHideBg,
|
||||
setHideBg,
|
||||
getDevMode,
|
||||
setDevMode,
|
||||
getDevServer,
|
||||
setDevServer,
|
||||
setHideBg,
|
||||
setHue,
|
||||
setRainbowMode,
|
||||
setRainbowSpeed,
|
||||
setTheme,
|
||||
} from "@utils/setting-utils";
|
||||
import { AUTO_MODE, DARK_MODE, LIGHT_MODE } from "@constants/constants";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
let hue = getHue();
|
||||
let theme = getStoredTheme();
|
||||
@@ -102,7 +102,7 @@ onMount(() => {
|
||||
}
|
||||
return () => {
|
||||
if (animationId) cancelAnimationFrame(animationId);
|
||||
}
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
import { Icon } from "astro-icon/components";
|
||||
import { profileConfig, umamiConfig, siteConfig } from "../../config";
|
||||
import { profileConfig, siteConfig, umamiConfig } from "../../config";
|
||||
|
||||
const config = profileConfig;
|
||||
---
|
||||
@@ -35,14 +35,14 @@ const config = profileConfig;
|
||||
<Icon name="material-symbols:visibility-outline" class="text-base"></Icon>
|
||||
<span class="text-xs">访问量</span>
|
||||
</div>
|
||||
<div id="site-views" class="font-bold text-lg text-neutral-700 dark:text-neutral-300">-</div>
|
||||
<div id="site-views" class="font-bold text-lg text-neutral-700 dark:text-neutral-300">0</div>
|
||||
</div>
|
||||
<div class="text-center border-l border-neutral-300 dark:border-neutral-700">
|
||||
<div class="text-xs text-neutral-500 mb-1 flex items-center justify-center gap-1">
|
||||
<Icon name="material-symbols:person" class="text-base"></Icon>
|
||||
<span class="text-xs">访客数</span>
|
||||
</div>
|
||||
<div id="site-visitors" class="font-bold text-lg text-neutral-700 dark:text-neutral-300">-</div>
|
||||
<div id="site-visitors" class="font-bold text-lg text-neutral-700 dark:text-neutral-300">0</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -68,6 +68,22 @@ const config = profileConfig;
|
||||
</style>
|
||||
|
||||
<script define:vars={{ umamiConfig}}>
|
||||
// 数字动画函数
|
||||
function animateValue(obj, start, end, duration) {
|
||||
let startTimestamp = null;
|
||||
const step = (timestamp) => {
|
||||
if (!startTimestamp) startTimestamp = timestamp;
|
||||
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
|
||||
obj.innerHTML = Math.floor(progress * (end - start) + start);
|
||||
if (progress < 1) {
|
||||
window.requestAnimationFrame(step);
|
||||
} else {
|
||||
obj.innerHTML = end;
|
||||
}
|
||||
};
|
||||
window.requestAnimationFrame(step);
|
||||
}
|
||||
|
||||
// 获取全站访问量统计
|
||||
async function loadSiteStats() {
|
||||
if (!umamiConfig.enable) return;
|
||||
@@ -81,8 +97,22 @@ const config = profileConfig;
|
||||
|
||||
const viewsElement = document.getElementById('site-views');
|
||||
const visitorsElement = document.getElementById('site-visitors');
|
||||
if (viewsElement) viewsElement.textContent = pageviews;
|
||||
if (visitorsElement) visitorsElement.textContent = visitors;
|
||||
|
||||
if (viewsElement) {
|
||||
const startVal = parseInt(viewsElement.textContent) || 0;
|
||||
// 如果当前值已经是目标值,就不执行动画
|
||||
if (startVal !== pageviews) {
|
||||
animateValue(viewsElement, startVal, pageviews, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
if (visitorsElement) {
|
||||
const startVal = parseInt(visitorsElement.textContent) || 0;
|
||||
// 如果当前值已经是目标值,就不执行动画
|
||||
if (startVal !== visitors) {
|
||||
animateValue(visitorsElement, startVal, visitors, 1000);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取全站统计失败:', error);
|
||||
}
|
||||
@@ -90,4 +120,6 @@ const config = profileConfig;
|
||||
|
||||
// 页面加载完成后获取统计数据
|
||||
document.addEventListener('DOMContentLoaded', loadSiteStats);
|
||||
// 监听 Swup 内容替换事件,确保页面切换后重新获取数据
|
||||
document.addEventListener('content:replace', loadSiteStats);
|
||||
</script>
|
||||
@@ -79,13 +79,13 @@ export const navBarConfig: NavBarConfig = {
|
||||
{
|
||||
name: "他站",
|
||||
url: "/posts/other-sites/", // Internal links should not include the base path, as it is automatically added
|
||||
external: true, // Show an external link icon and will open in a new tab
|
||||
external: false, // Show an external link icon and will open in a new tab
|
||||
},
|
||||
{
|
||||
name: "统计",
|
||||
url: "https://umami.acofork.com/share/CdkXbGgZr6ECKOyK", // Internal links should not include the base path, as it is automatically added
|
||||
external: true, // Show an external link icon and will open in a new tab
|
||||
}
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { LinkPreset, type NavBarLink } from "@/types/config";
|
||||
|
||||
|
||||
export const LinkPresets: { [key in LinkPreset]: NavBarLink } = {
|
||||
[LinkPreset.Home]: {
|
||||
name: "首页",
|
||||
|
||||
4
src/content/.obsidian/community-plugins.json
vendored
4
src/content/.obsidian/community-plugins.json
vendored
@@ -1,3 +1 @@
|
||||
[
|
||||
"obsidian-paste-image-rename"
|
||||
]
|
||||
["obsidian-paste-image-rename"]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,7 @@ const postsCollection = defineCollection({
|
||||
});
|
||||
|
||||
const assetsCollection = defineCollection({
|
||||
type: 'data',
|
||||
type: "data",
|
||||
schema: z.object({
|
||||
title: z.string().optional(),
|
||||
description: z.string().optional(),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
import Analytics from '@vercel/analytics/astro'
|
||||
import Analytics from "@vercel/analytics/astro";
|
||||
import "@fontsource/roboto/400.css";
|
||||
import "@fontsource/roboto/500.css";
|
||||
import "@fontsource/roboto/700.css";
|
||||
@@ -730,3 +730,12 @@ if (window.swup) {
|
||||
document.addEventListener("swup:enable", setup)
|
||||
}
|
||||
</script>
|
||||
|
||||
<svg style="position: absolute; width: 0; height: 0; overflow: hidden;" aria-hidden="true">
|
||||
<defs>
|
||||
<filter id="liquid-glass">
|
||||
<feTurbulence type="fractalNoise" baseFrequency="0.05" numOctaves="2" result="noise" />
|
||||
<feDisplacementMap in="SourceGraphic" in2="noise" scale="20" xChannelSelector="R" yChannelSelector="G" />
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
import { siteConfig } from "@/config";
|
||||
import Layout from "@/layouts/Layout.astro";
|
||||
import MainGridLayout from "@/layouts/MainGridLayout.astro";
|
||||
import { Icon } from "astro-icon/components";
|
||||
import { siteConfig } from "@/config";
|
||||
---
|
||||
|
||||
<Layout title="页面未找到">
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
---
|
||||
import { siteConfig } from "@/config";
|
||||
import type { Friend } from "@/types/data";
|
||||
import MainGridLayout from "@layouts/MainGridLayout.astro";
|
||||
import { Icon } from "astro-icon/components";
|
||||
import type { Friend } from "@/types/data";
|
||||
import { siteConfig } from "@/config";
|
||||
|
||||
const friends = Object.values(import.meta.glob<Friend>("@/data/friends/*.json", { eager: true, import: "default" }));
|
||||
const friends = Object.values(
|
||||
import.meta.glob<Friend>("@/data/friends/*.json", {
|
||||
eager: true,
|
||||
import: "default",
|
||||
}),
|
||||
);
|
||||
---
|
||||
|
||||
<MainGridLayout title="友链">
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Icon } from "astro-icon/components";
|
||||
import { gitHubEditConfig, licenseConfig } from "src/config";
|
||||
import PostMetadata from "../../components/PostMeta.astro";
|
||||
import ImageWrapper from "../../components/misc/ImageWrapper.astro";
|
||||
import { profileConfig, siteConfig } from "../../config";
|
||||
import { profileConfig, siteConfig, umamiConfig } from "../../config";
|
||||
import { formatDateToYYYYMMDD } from "../../utils/date-utils";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
@@ -278,6 +278,60 @@ const jsonLd = {
|
||||
document.addEventListener('swup:contentReplaced', setupImageLoading);
|
||||
</script>
|
||||
|
||||
<script define:vars={{ umamiConfig, postUrl: getPostUrlBySlug(entry.slug) }}>
|
||||
// 数字动画函数
|
||||
function animateValue(obj, start, end, duration) {
|
||||
let startTimestamp = null;
|
||||
const step = (timestamp) => {
|
||||
if (!startTimestamp) startTimestamp = timestamp;
|
||||
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
|
||||
obj.innerHTML = Math.floor(progress * (end - start) + start);
|
||||
if (progress < 1) {
|
||||
window.requestAnimationFrame(step);
|
||||
} else {
|
||||
obj.innerHTML = end;
|
||||
}
|
||||
};
|
||||
window.requestAnimationFrame(step);
|
||||
}
|
||||
|
||||
async function loadPageViews() {
|
||||
if (!umamiConfig.enable) return;
|
||||
try {
|
||||
const statsData = await fetchUmamiStats(umamiConfig.baseUrl, umamiConfig.shareId, {
|
||||
url: postUrl,
|
||||
timezone: umamiConfig.timezone
|
||||
});
|
||||
|
||||
const pageviews = (statsData.pageviews && statsData.pageviews.value) || statsData.pageviews || 0;
|
||||
const element = document.getElementById('post-pageviews');
|
||||
|
||||
if (element) {
|
||||
// 如果数据来自缓存,直接显示结果,跳过动画
|
||||
if (statsData._fromCache) {
|
||||
element.innerHTML = pageviews;
|
||||
return;
|
||||
}
|
||||
|
||||
const startVal = parseInt(element.textContent) || 0;
|
||||
|
||||
if (startVal !== pageviews) {
|
||||
if (startVal === 0) {
|
||||
animateValue(element, startVal, pageviews, 1000);
|
||||
} else {
|
||||
element.innerHTML = pageviews;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取页面访问量失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', loadPageViews);
|
||||
document.addEventListener('swup:contentReplaced', loadPageViews);
|
||||
</script>
|
||||
|
||||
<style is:global>
|
||||
@keyframes loading-progress {
|
||||
0% {
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
import rss from '@astrojs/rss';
|
||||
import sanitizeHtml from 'sanitize-html';
|
||||
import MarkdownIt from 'markdown-it';
|
||||
import { getCollection } from 'astro:content';
|
||||
import { siteConfig } from '@/config';
|
||||
import { parse as htmlParser } from 'node-html-parser';
|
||||
import { getImage } from 'astro:assets';
|
||||
import type { APIContext, ImageMetadata } from 'astro';
|
||||
import type { RSSFeedItem } from '@astrojs/rss';
|
||||
import { getSortedPosts } from '@/utils/content-utils';
|
||||
import { getImage } from "astro:assets";
|
||||
import { getCollection } from "astro:content";
|
||||
import { siteConfig } from "@/config";
|
||||
import { getSortedPosts } from "@/utils/content-utils";
|
||||
import rss from "@astrojs/rss";
|
||||
import type { RSSFeedItem } from "@astrojs/rss";
|
||||
import type { APIContext, ImageMetadata } from "astro";
|
||||
import MarkdownIt from "markdown-it";
|
||||
import { parse as htmlParser } from "node-html-parser";
|
||||
import sanitizeHtml from "sanitize-html";
|
||||
|
||||
const markdownParser = new MarkdownIt();
|
||||
|
||||
// get dynamic import of images as a map collection
|
||||
const imagesGlob = import.meta.glob<{ default: ImageMetadata }>(
|
||||
'/src/content/**/*.{jpeg,jpg,png,gif,webp}', // include posts and assets
|
||||
"/src/content/**/*.{jpeg,jpg,png,gif,webp}", // include posts and assets
|
||||
);
|
||||
|
||||
export async function GET(context: APIContext) {
|
||||
if (!context.site) {
|
||||
throw Error('site not set');
|
||||
throw Error("site not set");
|
||||
}
|
||||
|
||||
// Use the same ordering as site listing (pinned first, then by published desc)
|
||||
@@ -27,38 +27,40 @@ export async function GET(context: APIContext) {
|
||||
|
||||
for (const post of posts) {
|
||||
// convert markdown to html string
|
||||
const body = markdownParser.render(post.body || '');
|
||||
const body = markdownParser.render(post.body || "");
|
||||
// convert html string to DOM-like structure
|
||||
const html = htmlParser.parse(body);
|
||||
// hold all img tags in variable images
|
||||
const images = html.querySelectorAll('img');
|
||||
const images = html.querySelectorAll("img");
|
||||
|
||||
for (const img of images) {
|
||||
const src = img.getAttribute('src');
|
||||
const src = img.getAttribute("src");
|
||||
if (!src) continue;
|
||||
|
||||
// Handle content-relative images and convert them to built _astro paths
|
||||
if (src.startsWith('./') || src.startsWith('../')) {
|
||||
if (src.startsWith("./") || src.startsWith("../")) {
|
||||
let importPath: string | null = null;
|
||||
|
||||
if (src.startsWith('./')) {
|
||||
if (src.startsWith("./")) {
|
||||
// Path relative to the post file directory
|
||||
const prefixRemoved = src.slice(2);
|
||||
importPath = `/src/content/posts/${prefixRemoved}`;
|
||||
} else {
|
||||
// Path like ../assets/images/xxx -> relative to /src/content/
|
||||
const cleaned = src.replace(/^\.\.\//, '');
|
||||
const cleaned = src.replace(/^\.\.\//, "");
|
||||
importPath = `/src/content/${cleaned}`;
|
||||
}
|
||||
|
||||
const imageMod = await imagesGlob[importPath]?.()?.then((res) => res.default);
|
||||
const imageMod = await imagesGlob[importPath]?.()?.then(
|
||||
(res) => res.default,
|
||||
);
|
||||
if (imageMod) {
|
||||
const optimizedImg = await getImage({ src: imageMod });
|
||||
img.setAttribute('src', new URL(optimizedImg.src, context.site).href);
|
||||
img.setAttribute("src", new URL(optimizedImg.src, context.site).href);
|
||||
}
|
||||
} else if (src.startsWith('/')) {
|
||||
} else if (src.startsWith("/")) {
|
||||
// images starting with `/` are in public dir
|
||||
img.setAttribute('src', new URL(src, context.site).href);
|
||||
img.setAttribute("src", new URL(src, context.site).href);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,14 +71,14 @@ export async function GET(context: APIContext) {
|
||||
link: `/posts/${post.slug}/`,
|
||||
// sanitize the new html string with corrected image paths
|
||||
content: sanitizeHtml(html.toString(), {
|
||||
allowedTags: sanitizeHtml.defaults.allowedTags.concat(['img']),
|
||||
allowedTags: sanitizeHtml.defaults.allowedTags.concat(["img"]),
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
return rss({
|
||||
title: siteConfig.title,
|
||||
description: siteConfig.subtitle || 'No description',
|
||||
description: siteConfig.subtitle || "No description",
|
||||
site: context.site,
|
||||
items: feed,
|
||||
customData: `<language>${siteConfig.lang}</language>`,
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
---
|
||||
import { siteConfig } from "@/config";
|
||||
import type { Sponsor } from "@/types/data";
|
||||
import MainGridLayout from "@layouts/MainGridLayout.astro";
|
||||
import { Icon } from "astro-icon/components";
|
||||
import type { Sponsor } from "@/types/data";
|
||||
import { siteConfig } from "@/config";
|
||||
|
||||
const sponsors = Object.values(import.meta.glob<Sponsor>("@/data/sponsors/*.json", { eager: true, import: "default" }));
|
||||
const sponsors = Object.values(
|
||||
import.meta.glob<Sponsor>("@/data/sponsors/*.json", {
|
||||
eager: true,
|
||||
import: "default",
|
||||
}),
|
||||
);
|
||||
---
|
||||
|
||||
<MainGridLayout title="赞助支持">
|
||||
|
||||
@@ -43,7 +43,7 @@ export function UrlCardComponent(properties, children) {
|
||||
const nTitleText = h(
|
||||
`div#${cardUuid}-title`,
|
||||
{ class: "uc-title-text" },
|
||||
"Loading..."
|
||||
"Loading...",
|
||||
);
|
||||
|
||||
const nScript = h(
|
||||
@@ -97,11 +97,7 @@ export function UrlCardComponent(properties, children) {
|
||||
},
|
||||
[
|
||||
h(`div#${cardUuid}-container`, { class: "uc-container" }, [
|
||||
h("div", { class: "uc-content" }, [
|
||||
nTitle,
|
||||
nTitleText,
|
||||
nDescription,
|
||||
]),
|
||||
h("div", { class: "uc-content" }, [nTitle, nTitleText, nDescription]),
|
||||
nImage,
|
||||
]),
|
||||
nScript,
|
||||
|
||||
@@ -141,3 +141,20 @@
|
||||
.collapsed {
|
||||
height: var(--collapsedHeight);
|
||||
}
|
||||
.shiny-text {
|
||||
animation: shine 5s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes shine {
|
||||
0% {
|
||||
background-position: 100%;
|
||||
}
|
||||
100% {
|
||||
background-position: -100%;
|
||||
}
|
||||
}
|
||||
|
||||
.shiny-text.disabled {
|
||||
animation: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -92,8 +92,6 @@ export type UmamiConfig = {
|
||||
timezone: string;
|
||||
};
|
||||
|
||||
|
||||
|
||||
export type LIGHT_DARK_MODE =
|
||||
| typeof LIGHT_MODE
|
||||
| typeof DARK_MODE
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { getCollection } from "astro:content";
|
||||
|
||||
|
||||
export async function getSortedPosts() {
|
||||
const allBlogPosts = await getCollection("posts", ({ data }) => {
|
||||
return import.meta.env.PROD ? data.draft !== true : true;
|
||||
@@ -27,4 +26,3 @@ export async function getSortedPosts() {
|
||||
|
||||
return sorted;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ export function getHue(): number {
|
||||
return stored ? Number.parseInt(stored) : getDefaultHue();
|
||||
}
|
||||
|
||||
export function setHue(hue: number, save: boolean = true): void {
|
||||
export function setHue(hue: number, save = true): void {
|
||||
if (save) {
|
||||
localStorage.setItem("hue", String(hue));
|
||||
}
|
||||
@@ -56,7 +56,10 @@ export function setBgBlur(blur: number): void {
|
||||
const currentFilter = bgBox.style.filter || "";
|
||||
const hueRotateMatch = currentFilter.match(/hue-rotate\((.*?)deg\)/);
|
||||
const hueRotate = hueRotateMatch ? hueRotateMatch[1] : "0";
|
||||
bgBox.style.setProperty("filter", `blur(${blur}px) hue-rotate(${hueRotate}deg)`);
|
||||
bgBox.style.setProperty(
|
||||
"filter",
|
||||
`blur(${blur}px) hue-rotate(${hueRotate}deg)`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,8 +13,6 @@ export function getPostUrlBySlug(slug: string): string {
|
||||
return url(`/posts/${slug}/`);
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function getDir(path: string): string {
|
||||
const lastSlashIndex = path.lastIndexOf("/");
|
||||
if (lastSlashIndex < 0) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
const defaultTheme = require("tailwindcss/defaultTheme")
|
||||
const defaultTheme = require("tailwindcss/defaultTheme");
|
||||
module.exports = {
|
||||
content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue,mjs}"],
|
||||
darkMode: "class", // allows toggling dark mode manually
|
||||
@@ -11,4 +11,4 @@ module.exports = {
|
||||
},
|
||||
},
|
||||
plugins: [require("@tailwindcss/typography")],
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6,4 +6,3 @@
|
||||
"not_found_handling": "404-page"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user