mirror of
https://github.com/StepanovPlaton/AboutMe.git
synced 2026-07-28 19:35:51 +04:00
Fix preloader
This commit is contained in:
@@ -178,7 +178,6 @@ export default defineConfig({
|
|||||||
tagName: "span",
|
tagName: "span",
|
||||||
properties: {
|
properties: {
|
||||||
className: ["anchor-icon"],
|
className: ["anchor-icon"],
|
||||||
"data-pagefind-ignore": true,
|
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
|
|||||||
17
package.json
17
package.json
@@ -10,7 +10,8 @@
|
|||||||
"format": "biome format --write ./src",
|
"format": "biome format --write ./src",
|
||||||
"check": "astro check",
|
"check": "astro check",
|
||||||
"dev": "astro dev",
|
"dev": "astro dev",
|
||||||
"build": "node scripts/build-with-pagefind.cjs",
|
"build": "node scripts/copy-iconify.cjs && astro build",
|
||||||
|
"copy-iconify": "node scripts/copy-iconify.cjs",
|
||||||
"preview": "astro preview",
|
"preview": "astro preview",
|
||||||
"astro": "astro",
|
"astro": "astro",
|
||||||
"new-post": "node scripts/new-post.js"
|
"new-post": "node scripts/new-post.js"
|
||||||
@@ -32,7 +33,18 @@
|
|||||||
"@iconify-json/fa6-brands": "^1.2.6",
|
"@iconify-json/fa6-brands": "^1.2.6",
|
||||||
"@iconify-json/fa6-regular": "^1.2.4",
|
"@iconify-json/fa6-regular": "^1.2.4",
|
||||||
"@iconify-json/fa6-solid": "^1.2.4",
|
"@iconify-json/fa6-solid": "^1.2.4",
|
||||||
|
"@iconify-json/devicon": "^1.2.5",
|
||||||
|
"@iconify-json/game-icons": "^1.2.3",
|
||||||
|
"@iconify-json/hugeicons": "^1.2.18",
|
||||||
|
"@iconify-json/iconoir": "^1.2.10",
|
||||||
|
"@iconify-json/logos": "^1.2.10",
|
||||||
|
"@iconify-json/material-icon-theme": "^1.2.21",
|
||||||
"@iconify-json/material-symbols": "^1.2.53",
|
"@iconify-json/material-symbols": "^1.2.53",
|
||||||
|
"@iconify-json/mdi": "^1.2.3",
|
||||||
|
"@iconify-json/mingcute": "^1.2.5",
|
||||||
|
"@iconify-json/skill-icons": "^1.2.3",
|
||||||
|
"@iconify-json/vscode-icons": "^1.2.40",
|
||||||
|
"@iconify/utils": "^2.3.0",
|
||||||
"@iconify/svelte": "^5.2.1",
|
"@iconify/svelte": "^5.2.1",
|
||||||
"@swup/astro": "^1.7.0",
|
"@swup/astro": "^1.7.0",
|
||||||
"@tailwindcss/typography": "^0.5.19",
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
@@ -53,8 +65,8 @@
|
|||||||
"marked": "^17.0.1",
|
"marked": "^17.0.1",
|
||||||
"mdast-util-to-string": "^4.0.0",
|
"mdast-util-to-string": "^4.0.0",
|
||||||
"node-html-parser": "^7.0.2",
|
"node-html-parser": "^7.0.2",
|
||||||
|
"iconify-icon": "1.0.7",
|
||||||
"overlayscrollbars": "^2.14.0",
|
"overlayscrollbars": "^2.14.0",
|
||||||
"pagefind": "^1.4.0",
|
|
||||||
"photoswipe": "^5.4.4",
|
"photoswipe": "^5.4.4",
|
||||||
"reading-time": "^1.5.0",
|
"reading-time": "^1.5.0",
|
||||||
"rehype-autolink-headings": "^7.1.0",
|
"rehype-autolink-headings": "^7.1.0",
|
||||||
@@ -78,7 +90,6 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/ts-plugin": "^1.10.6",
|
"@astrojs/ts-plugin": "^1.10.6",
|
||||||
"@biomejs/biome": "2.3.13",
|
"@biomejs/biome": "2.3.13",
|
||||||
"@iconify-json/mdi": "^1.2.3",
|
|
||||||
"@rollup/plugin-yaml": "^4.1.2",
|
"@rollup/plugin-yaml": "^4.1.2",
|
||||||
"@types/hast": "^3.0.4",
|
"@types/hast": "^3.0.4",
|
||||||
"@types/markdown-it": "^14.1.2",
|
"@types/markdown-it": "^14.1.2",
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
exclude_selectors:
|
|
||||||
- "span.katex"
|
|
||||||
- "span.katex-display"
|
|
||||||
- "[data-pagefind-ignore]"
|
|
||||||
- ".search-panel"
|
|
||||||
- "#search-panel"
|
|
||||||
173
pnpm-lock.yaml
generated
173
pnpm-lock.yaml
generated
@@ -47,6 +47,9 @@ importers:
|
|||||||
'@fontsource/roboto':
|
'@fontsource/roboto':
|
||||||
specifier: ^5.2.9
|
specifier: ^5.2.9
|
||||||
version: 5.2.9
|
version: 5.2.9
|
||||||
|
'@iconify-json/devicon':
|
||||||
|
specifier: ^1.2.5
|
||||||
|
version: 1.2.62
|
||||||
'@iconify-json/fa6-brands':
|
'@iconify-json/fa6-brands':
|
||||||
specifier: ^1.2.6
|
specifier: ^1.2.6
|
||||||
version: 1.2.6
|
version: 1.2.6
|
||||||
@@ -56,12 +59,42 @@ importers:
|
|||||||
'@iconify-json/fa6-solid':
|
'@iconify-json/fa6-solid':
|
||||||
specifier: ^1.2.4
|
specifier: ^1.2.4
|
||||||
version: 1.2.4
|
version: 1.2.4
|
||||||
|
'@iconify-json/game-icons':
|
||||||
|
specifier: ^1.2.3
|
||||||
|
version: 1.2.4
|
||||||
|
'@iconify-json/hugeicons':
|
||||||
|
specifier: ^1.2.18
|
||||||
|
version: 1.2.28
|
||||||
|
'@iconify-json/iconoir':
|
||||||
|
specifier: ^1.2.10
|
||||||
|
version: 1.2.11
|
||||||
|
'@iconify-json/logos':
|
||||||
|
specifier: ^1.2.10
|
||||||
|
version: 1.2.11
|
||||||
|
'@iconify-json/material-icon-theme':
|
||||||
|
specifier: ^1.2.21
|
||||||
|
version: 1.2.64
|
||||||
'@iconify-json/material-symbols':
|
'@iconify-json/material-symbols':
|
||||||
specifier: ^1.2.53
|
specifier: ^1.2.53
|
||||||
version: 1.2.53
|
version: 1.2.53
|
||||||
|
'@iconify-json/mdi':
|
||||||
|
specifier: ^1.2.3
|
||||||
|
version: 1.2.3
|
||||||
|
'@iconify-json/mingcute':
|
||||||
|
specifier: ^1.2.5
|
||||||
|
version: 1.2.7
|
||||||
|
'@iconify-json/skill-icons':
|
||||||
|
specifier: ^1.2.3
|
||||||
|
version: 1.2.4
|
||||||
|
'@iconify-json/vscode-icons':
|
||||||
|
specifier: ^1.2.40
|
||||||
|
version: 1.2.50
|
||||||
'@iconify/svelte':
|
'@iconify/svelte':
|
||||||
specifier: ^5.2.1
|
specifier: ^5.2.1
|
||||||
version: 5.2.1(svelte@5.49.1)
|
version: 5.2.1(svelte@5.49.1)
|
||||||
|
'@iconify/utils':
|
||||||
|
specifier: ^2.3.0
|
||||||
|
version: 2.3.0
|
||||||
'@swup/astro':
|
'@swup/astro':
|
||||||
specifier: ^1.7.0
|
specifier: ^1.7.0
|
||||||
version: 1.7.0
|
version: 1.7.0
|
||||||
@@ -101,6 +134,9 @@ importers:
|
|||||||
hastscript:
|
hastscript:
|
||||||
specifier: ^9.0.1
|
specifier: ^9.0.1
|
||||||
version: 9.0.1
|
version: 9.0.1
|
||||||
|
iconify-icon:
|
||||||
|
specifier: 1.0.7
|
||||||
|
version: 1.0.7
|
||||||
js-yaml:
|
js-yaml:
|
||||||
specifier: ^4.1.1
|
specifier: ^4.1.1
|
||||||
version: 4.1.1
|
version: 4.1.1
|
||||||
@@ -122,9 +158,6 @@ importers:
|
|||||||
overlayscrollbars:
|
overlayscrollbars:
|
||||||
specifier: ^2.14.0
|
specifier: ^2.14.0
|
||||||
version: 2.14.0
|
version: 2.14.0
|
||||||
pagefind:
|
|
||||||
specifier: ^1.4.0
|
|
||||||
version: 1.4.0
|
|
||||||
photoswipe:
|
photoswipe:
|
||||||
specifier: ^5.4.4
|
specifier: ^5.4.4
|
||||||
version: 5.4.4
|
version: 5.4.4
|
||||||
@@ -189,9 +222,6 @@ importers:
|
|||||||
'@biomejs/biome':
|
'@biomejs/biome':
|
||||||
specifier: 2.3.13
|
specifier: 2.3.13
|
||||||
version: 2.3.13
|
version: 2.3.13
|
||||||
'@iconify-json/mdi':
|
|
||||||
specifier: ^1.2.3
|
|
||||||
version: 1.2.3
|
|
||||||
'@rollup/plugin-yaml':
|
'@rollup/plugin-yaml':
|
||||||
specifier: ^4.1.2
|
specifier: ^4.1.2
|
||||||
version: 4.1.2(rollup@2.79.2)
|
version: 4.1.2(rollup@2.79.2)
|
||||||
@@ -1323,6 +1353,9 @@ packages:
|
|||||||
'@fontsource/roboto@5.2.9':
|
'@fontsource/roboto@5.2.9':
|
||||||
resolution: {integrity: sha512-ZTkyHiPk74B/aj8BZWbsxD5Yu+Lq+nR64eV4wirlrac2qXR7jYk2h6JlLYuOuoruTkGQWNw2fMuKNavw7/rg0w==}
|
resolution: {integrity: sha512-ZTkyHiPk74B/aj8BZWbsxD5Yu+Lq+nR64eV4wirlrac2qXR7jYk2h6JlLYuOuoruTkGQWNw2fMuKNavw7/rg0w==}
|
||||||
|
|
||||||
|
'@iconify-json/devicon@1.2.62':
|
||||||
|
resolution: {integrity: sha512-X0o0+fOJL2t5JTbDCGLRzrmvf8Pv5q8dr86+fW+F/VJ9qvXTtny6lqGIwjE9AY4VTLm3i8f/N+VtRheSW6OkEg==}
|
||||||
|
|
||||||
'@iconify-json/fa6-brands@1.2.6':
|
'@iconify-json/fa6-brands@1.2.6':
|
||||||
resolution: {integrity: sha512-twL3X4KWcxAhbc1vz/mIDsVr+CAItk1/EIfxKUVQtpv6O4eydk5KNYqTZWdvJNHGInUgd6vKg21aWfVgb5DXEg==}
|
resolution: {integrity: sha512-twL3X4KWcxAhbc1vz/mIDsVr+CAItk1/EIfxKUVQtpv6O4eydk5KNYqTZWdvJNHGInUgd6vKg21aWfVgb5DXEg==}
|
||||||
|
|
||||||
@@ -1332,12 +1365,36 @@ packages:
|
|||||||
'@iconify-json/fa6-solid@1.2.4':
|
'@iconify-json/fa6-solid@1.2.4':
|
||||||
resolution: {integrity: sha512-LmDNNdJVyvF5mPm1yxWvL8KjCc/E8LzoqnF1LNTVpyY2ZJRUlGOWuPIThdbuFBF2IovgttkIyumhyqfmlHdwKg==}
|
resolution: {integrity: sha512-LmDNNdJVyvF5mPm1yxWvL8KjCc/E8LzoqnF1LNTVpyY2ZJRUlGOWuPIThdbuFBF2IovgttkIyumhyqfmlHdwKg==}
|
||||||
|
|
||||||
|
'@iconify-json/game-icons@1.2.4':
|
||||||
|
resolution: {integrity: sha512-/HDDZxowXgDJcOEwPspUCq5RuDdl25OyZKdtxqqiPJQNTrWIym7r4StLzIVs77DyNzOWWhH5wDqwYR3WHeDfkg==}
|
||||||
|
|
||||||
|
'@iconify-json/hugeicons@1.2.28':
|
||||||
|
resolution: {integrity: sha512-974r0jTel8JBjJhoEAnUEtEhNMmPek2WegAbdlpQaQp1cIJfcxl3fM8/bfPceMKtvbN8vBokaQqHeDgikGRl5w==}
|
||||||
|
|
||||||
|
'@iconify-json/iconoir@1.2.11':
|
||||||
|
resolution: {integrity: sha512-clBrCsZPkmdksYOkufVp7aoAU1j1hFQPrLUooWWmoYIMvKskUHQ+IDnwV7agTR+tGYHbud7OP2SRfYEpnqFDNw==}
|
||||||
|
|
||||||
|
'@iconify-json/logos@1.2.11':
|
||||||
|
resolution: {integrity: sha512-fOo4pGEatuyuCFNL+cwquYMa2Im0oJHRHV7lt/Qqs5Ode/lPImHCQcfTtPzZj7qYMPb/h8YHN3TG54uEowrjNQ==}
|
||||||
|
|
||||||
|
'@iconify-json/material-icon-theme@1.2.64':
|
||||||
|
resolution: {integrity: sha512-YUTQ7IQ919XwcSz7qKDixj5+63PD8lDgimtRtQwo5clcLZAwf9SyzeUOTLTPR17plPNo0xjlgDi4UcMXfz2xFQ==}
|
||||||
|
|
||||||
'@iconify-json/material-symbols@1.2.53':
|
'@iconify-json/material-symbols@1.2.53':
|
||||||
resolution: {integrity: sha512-2jXBKFdNzL9zy6chnJqubykL9WZno7rEP6/isSzpp6fKJJMXXhRtVkaGw1Clle0RlXGWzVkd/eiYUH8f9/ILrQ==}
|
resolution: {integrity: sha512-2jXBKFdNzL9zy6chnJqubykL9WZno7rEP6/isSzpp6fKJJMXXhRtVkaGw1Clle0RlXGWzVkd/eiYUH8f9/ILrQ==}
|
||||||
|
|
||||||
'@iconify-json/mdi@1.2.3':
|
'@iconify-json/mdi@1.2.3':
|
||||||
resolution: {integrity: sha512-O3cLwbDOK7NNDf2ihaQOH5F9JglnulNDFV7WprU2dSoZu3h3cWH//h74uQAB87brHmvFVxIOkuBX2sZSzYhScg==}
|
resolution: {integrity: sha512-O3cLwbDOK7NNDf2ihaQOH5F9JglnulNDFV7WprU2dSoZu3h3cWH//h74uQAB87brHmvFVxIOkuBX2sZSzYhScg==}
|
||||||
|
|
||||||
|
'@iconify-json/mingcute@1.2.7':
|
||||||
|
resolution: {integrity: sha512-bp4z6F53KAQp99aSL7qPCHL7HWUNGMNKIhfo/dx9pwVHiad/WusUbTOFXEZfpA44syJPzSOxa3O6Pwiq7qZz1g==}
|
||||||
|
|
||||||
|
'@iconify-json/skill-icons@1.2.4':
|
||||||
|
resolution: {integrity: sha512-S6iRKHGlGCb/zfx3Isv1TBe5PunbDE5FEwJcaXji60+yRZMrcFFtYEI1xivKqaGKXyVZ508yjGDItsehQdJmSg==}
|
||||||
|
|
||||||
|
'@iconify-json/vscode-icons@1.2.50':
|
||||||
|
resolution: {integrity: sha512-XqG9nO1m+IiY8/RvT5BJjM/eG3CDRXBGRRPqR/MAcVi734yZ0Pa+jqObshZfnpUeIsuDKNn9C/7ZW00ART6kog==}
|
||||||
|
|
||||||
'@iconify/svelte@5.2.1':
|
'@iconify/svelte@5.2.1':
|
||||||
resolution: {integrity: sha512-zHmsIPmnIhGd5gc95bNN5FL+GifwMZv7M2rlZEpa7IXYGFJm/XGHdWf6PWQa6OBoC+R69WyiPO9NAj5wjfjbow==}
|
resolution: {integrity: sha512-zHmsIPmnIhGd5gc95bNN5FL+GifwMZv7M2rlZEpa7IXYGFJm/XGHdWf6PWQa6OBoC+R69WyiPO9NAj5wjfjbow==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -1632,36 +1689,6 @@ packages:
|
|||||||
'@oslojs/encoding@1.1.0':
|
'@oslojs/encoding@1.1.0':
|
||||||
resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==}
|
resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==}
|
||||||
|
|
||||||
'@pagefind/darwin-arm64@1.4.0':
|
|
||||||
resolution: {integrity: sha512-2vMqkbv3lbx1Awea90gTaBsvpzgRs7MuSgKDxW0m9oV1GPZCZbZBJg/qL83GIUEN2BFlY46dtUZi54pwH+/pTQ==}
|
|
||||||
cpu: [arm64]
|
|
||||||
os: [darwin]
|
|
||||||
|
|
||||||
'@pagefind/darwin-x64@1.4.0':
|
|
||||||
resolution: {integrity: sha512-e7JPIS6L9/cJfow+/IAqknsGqEPjJnVXGjpGm25bnq+NPdoD3c/7fAwr1OXkG4Ocjx6ZGSCijXEV4ryMcH2E3A==}
|
|
||||||
cpu: [x64]
|
|
||||||
os: [darwin]
|
|
||||||
|
|
||||||
'@pagefind/freebsd-x64@1.4.0':
|
|
||||||
resolution: {integrity: sha512-WcJVypXSZ+9HpiqZjFXMUobfFfZZ6NzIYtkhQ9eOhZrQpeY5uQFqNWLCk7w9RkMUwBv1HAMDW3YJQl/8OqsV0Q==}
|
|
||||||
cpu: [x64]
|
|
||||||
os: [freebsd]
|
|
||||||
|
|
||||||
'@pagefind/linux-arm64@1.4.0':
|
|
||||||
resolution: {integrity: sha512-PIt8dkqt4W06KGmQjONw7EZbhDF+uXI7i0XtRLN1vjCUxM9vGPdtJc2mUyVPevjomrGz5M86M8bqTr6cgDp1Uw==}
|
|
||||||
cpu: [arm64]
|
|
||||||
os: [linux]
|
|
||||||
|
|
||||||
'@pagefind/linux-x64@1.4.0':
|
|
||||||
resolution: {integrity: sha512-z4oddcWwQ0UHrTHR8psLnVlz6USGJ/eOlDPTDYZ4cI8TK8PgwRUPQZp9D2iJPNIPcS6Qx/E4TebjuGJOyK8Mmg==}
|
|
||||||
cpu: [x64]
|
|
||||||
os: [linux]
|
|
||||||
|
|
||||||
'@pagefind/windows-x64@1.4.0':
|
|
||||||
resolution: {integrity: sha512-NkT+YAdgS2FPCn8mIA9bQhiBs+xmniMGq1LFPDhcFn0+2yIUEiIG06t7bsZlhdjknEQRTSdT7YitP6fC5qwP0g==}
|
|
||||||
cpu: [x64]
|
|
||||||
os: [win32]
|
|
||||||
|
|
||||||
'@pkgjs/parseargs@0.11.0':
|
'@pkgjs/parseargs@0.11.0':
|
||||||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
@@ -3342,6 +3369,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
|
resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
|
||||||
engines: {node: '>= 14'}
|
engines: {node: '>= 14'}
|
||||||
|
|
||||||
|
iconify-icon@1.0.7:
|
||||||
|
resolution: {integrity: sha512-MxaO3Jhf3f5ymPWGHR9x74f90TNKcq1D+B2iGucGhVtqAgbC9EtM06kKiTGH2CKELNnexckwhrA3/+OpT4HKFw==}
|
||||||
|
|
||||||
iconv-lite@0.6.3:
|
iconv-lite@0.6.3:
|
||||||
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -4135,10 +4165,6 @@ packages:
|
|||||||
package-manager-detector@1.6.0:
|
package-manager-detector@1.6.0:
|
||||||
resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==}
|
resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==}
|
||||||
|
|
||||||
pagefind@1.4.0:
|
|
||||||
resolution: {integrity: sha512-z2kY1mQlL4J8q5EIsQkLzQjilovKzfNVhX8De6oyE6uHpfFtyBaqUpcl/XzJC/4fjD8vBDyh1zolimIcVrCn9g==}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
pako@0.2.9:
|
pako@0.2.9:
|
||||||
resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==}
|
resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==}
|
||||||
|
|
||||||
@@ -6867,6 +6893,10 @@ snapshots:
|
|||||||
|
|
||||||
'@fontsource/roboto@5.2.9': {}
|
'@fontsource/roboto@5.2.9': {}
|
||||||
|
|
||||||
|
'@iconify-json/devicon@1.2.62':
|
||||||
|
dependencies:
|
||||||
|
'@iconify/types': 2.0.0
|
||||||
|
|
||||||
'@iconify-json/fa6-brands@1.2.6':
|
'@iconify-json/fa6-brands@1.2.6':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@iconify/types': 2.0.0
|
'@iconify/types': 2.0.0
|
||||||
@@ -6879,6 +6909,26 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@iconify/types': 2.0.0
|
'@iconify/types': 2.0.0
|
||||||
|
|
||||||
|
'@iconify-json/game-icons@1.2.4':
|
||||||
|
dependencies:
|
||||||
|
'@iconify/types': 2.0.0
|
||||||
|
|
||||||
|
'@iconify-json/hugeicons@1.2.28':
|
||||||
|
dependencies:
|
||||||
|
'@iconify/types': 2.0.0
|
||||||
|
|
||||||
|
'@iconify-json/iconoir@1.2.11':
|
||||||
|
dependencies:
|
||||||
|
'@iconify/types': 2.0.0
|
||||||
|
|
||||||
|
'@iconify-json/logos@1.2.11':
|
||||||
|
dependencies:
|
||||||
|
'@iconify/types': 2.0.0
|
||||||
|
|
||||||
|
'@iconify-json/material-icon-theme@1.2.64':
|
||||||
|
dependencies:
|
||||||
|
'@iconify/types': 2.0.0
|
||||||
|
|
||||||
'@iconify-json/material-symbols@1.2.53':
|
'@iconify-json/material-symbols@1.2.53':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@iconify/types': 2.0.0
|
'@iconify/types': 2.0.0
|
||||||
@@ -6887,6 +6937,18 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@iconify/types': 2.0.0
|
'@iconify/types': 2.0.0
|
||||||
|
|
||||||
|
'@iconify-json/mingcute@1.2.7':
|
||||||
|
dependencies:
|
||||||
|
'@iconify/types': 2.0.0
|
||||||
|
|
||||||
|
'@iconify-json/skill-icons@1.2.4':
|
||||||
|
dependencies:
|
||||||
|
'@iconify/types': 2.0.0
|
||||||
|
|
||||||
|
'@iconify-json/vscode-icons@1.2.50':
|
||||||
|
dependencies:
|
||||||
|
'@iconify/types': 2.0.0
|
||||||
|
|
||||||
'@iconify/svelte@5.2.1(svelte@5.49.1)':
|
'@iconify/svelte@5.2.1(svelte@5.49.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@iconify/types': 2.0.0
|
'@iconify/types': 2.0.0
|
||||||
@@ -7149,24 +7211,6 @@ snapshots:
|
|||||||
|
|
||||||
'@oslojs/encoding@1.1.0': {}
|
'@oslojs/encoding@1.1.0': {}
|
||||||
|
|
||||||
'@pagefind/darwin-arm64@1.4.0':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@pagefind/darwin-x64@1.4.0':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@pagefind/freebsd-x64@1.4.0':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@pagefind/linux-arm64@1.4.0':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@pagefind/linux-x64@1.4.0':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@pagefind/windows-x64@1.4.0':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@pkgjs/parseargs@0.11.0':
|
'@pkgjs/parseargs@0.11.0':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@@ -9155,6 +9199,10 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
iconify-icon@1.0.7:
|
||||||
|
dependencies:
|
||||||
|
'@iconify/types': 2.0.0
|
||||||
|
|
||||||
iconv-lite@0.6.3:
|
iconv-lite@0.6.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer: 2.1.2
|
safer-buffer: 2.1.2
|
||||||
@@ -10153,15 +10201,6 @@ snapshots:
|
|||||||
|
|
||||||
package-manager-detector@1.6.0: {}
|
package-manager-detector@1.6.0: {}
|
||||||
|
|
||||||
pagefind@1.4.0:
|
|
||||||
optionalDependencies:
|
|
||||||
'@pagefind/darwin-arm64': 1.4.0
|
|
||||||
'@pagefind/darwin-x64': 1.4.0
|
|
||||||
'@pagefind/freebsd-x64': 1.4.0
|
|
||||||
'@pagefind/linux-arm64': 1.4.0
|
|
||||||
'@pagefind/linux-x64': 1.4.0
|
|
||||||
'@pagefind/windows-x64': 1.4.0
|
|
||||||
|
|
||||||
pako@0.2.9: {}
|
pako@0.2.9: {}
|
||||||
|
|
||||||
parent-module@1.0.1:
|
parent-module@1.0.1:
|
||||||
|
|||||||
12
public/assets/iconify/iconify-icon.min.js
vendored
Normal file
12
public/assets/iconify/iconify-icon.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1,83 +0,0 @@
|
|||||||
/* This is a script to build the site with Pagefind */
|
|
||||||
|
|
||||||
const { execSync } = require('child_process');
|
|
||||||
const { existsSync } = require('fs');
|
|
||||||
const { join } = require('path');
|
|
||||||
|
|
||||||
// Detect the platform
|
|
||||||
function detectPlatform() {
|
|
||||||
// Check environment variables
|
|
||||||
if (process.env.VERCEL) {
|
|
||||||
return 'vercel';
|
|
||||||
}
|
|
||||||
if (process.env.CF_PAGES) {
|
|
||||||
return 'cloudflare';
|
|
||||||
}
|
|
||||||
if (process.env.NETLIFY) {
|
|
||||||
return 'netlify';
|
|
||||||
}
|
|
||||||
if (process.env.GITHUB_ACTIONS) {
|
|
||||||
return 'github';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if specific directories exist
|
|
||||||
if (existsSync('.vercel')) {
|
|
||||||
return 'vercel';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default to standard dist directory
|
|
||||||
return 'default';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Pagefind output directory
|
|
||||||
function getPagefindOutputDir(platform) {
|
|
||||||
const outputDirs = {
|
|
||||||
vercel: '.vercel/output/static',
|
|
||||||
cloudflare: 'dist',
|
|
||||||
netlify: 'dist',
|
|
||||||
github: 'dist',
|
|
||||||
default: 'dist'
|
|
||||||
};
|
|
||||||
|
|
||||||
return outputDirs[platform] || 'dist';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Main function
|
|
||||||
function main() {
|
|
||||||
const platform = detectPlatform();
|
|
||||||
const outputDir = getPagefindOutputDir(platform);
|
|
||||||
|
|
||||||
console.log(`🚀 Detected deployment platform: ${platform}`);
|
|
||||||
console.log(`📁 Pagefind output directory: ${outputDir}`);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Run Astro build
|
|
||||||
console.log('🔨 Running Astro build...');
|
|
||||||
execSync(`npx astro build`.trim(), {
|
|
||||||
stdio: 'inherit',
|
|
||||||
cwd: process.cwd() // Ensure in the correct directory
|
|
||||||
});
|
|
||||||
|
|
||||||
// Check if output directory exists
|
|
||||||
if (!existsSync(outputDir)) {
|
|
||||||
console.error(`❌ Output directory does not exist: ${outputDir}`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run Pagefind
|
|
||||||
console.log(`🔍 Running Pagefind search index generation...`);
|
|
||||||
execSync(`npx pagefind --site ${outputDir}`, {
|
|
||||||
stdio: 'inherit',
|
|
||||||
cwd: process.cwd() // Ensure in the correct directory
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('✅ Build completed!');
|
|
||||||
console.log(`📊 Search index generated at: ${outputDir}/pagefind/`);
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('❌ Build failed:', error.message);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
main();
|
|
||||||
9
scripts/copy-iconify.cjs
Normal file
9
scripts/copy-iconify.cjs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
const { copyFileSync, mkdirSync } = require("fs");
|
||||||
|
const { dirname, join } = require("path");
|
||||||
|
|
||||||
|
const src = join(__dirname, "../node_modules/iconify-icon/dist/iconify-icon.min.js");
|
||||||
|
const dest = join(__dirname, "../public/assets/iconify/iconify-icon.min.js");
|
||||||
|
|
||||||
|
mkdirSync(dirname(dest), { recursive: true });
|
||||||
|
copyFileSync(src, dest);
|
||||||
|
console.log(`Copied iconify-icon.min.js to ${dest}`);
|
||||||
@@ -1,29 +1,45 @@
|
|||||||
---
|
---
|
||||||
// 全局Iconify加载器组件
|
import { url } from "@utils/url";
|
||||||
// 在页面头部加载,确保图标库尽早可用
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
preloadIcons?: string[]; // 需要预加载的图标列表
|
preloadIcons?: string[];
|
||||||
timeout?: number; // 加载超时时间
|
|
||||||
retryCount?: number; // 重试次数
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { preloadIcons = [], timeout = 10000, retryCount = 3 } = Astro.props;
|
const { preloadIcons = [] } = Astro.props;
|
||||||
|
const iconifyScriptUrl = url("/assets/iconify/iconify-icon.min.js");
|
||||||
---
|
---
|
||||||
|
|
||||||
<!-- Iconify图标库加载器 -->
|
<div
|
||||||
<script define:vars={{ preloadIcons, timeout, retryCount }}>
|
id="iconify-loader-config"
|
||||||
// 全局图标加载逻辑
|
data-script-url={iconifyScriptUrl}
|
||||||
(function() {
|
data-preload-icons={JSON.stringify(preloadIcons)}
|
||||||
'use strict';
|
hidden
|
||||||
|
aria-hidden="true"
|
||||||
|
></div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
registerSvelteIconifyCollections,
|
||||||
|
registerWebComponentIconifyCollections,
|
||||||
|
} from "@/utils/iconify-offline";
|
||||||
|
|
||||||
|
const LOAD_TIMEOUT_MS = 3000;
|
||||||
|
const RETRY_COUNT = 1;
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
// 避免重复加载
|
|
||||||
if (window.__iconifyLoaderInitialized) {
|
if (window.__iconifyLoaderInitialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
window.__iconifyLoaderInitialized = true;
|
window.__iconifyLoaderInitialized = true;
|
||||||
|
|
||||||
// 图标加载器类
|
registerSvelteIconifyCollections();
|
||||||
|
|
||||||
|
const configEl = document.getElementById("iconify-loader-config");
|
||||||
|
const iconifyScriptUrl = configEl?.dataset.scriptUrl ?? "/assets/iconify/iconify-icon.min.js";
|
||||||
|
const preloadIcons = JSON.parse(configEl?.dataset.preloadIcons ?? "[]");
|
||||||
|
|
||||||
class IconifyLoader {
|
class IconifyLoader {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.isLoaded = false;
|
this.isLoaded = false;
|
||||||
@@ -34,7 +50,10 @@ const { preloadIcons = [], timeout = 10000, retryCount = 3 } = Astro.props;
|
|||||||
}
|
}
|
||||||
|
|
||||||
async load(options = {}) {
|
async load(options = {}) {
|
||||||
const { timeout: loadTimeout = timeout, retryCount: maxRetries = retryCount } = options;
|
const {
|
||||||
|
timeout: loadTimeout = LOAD_TIMEOUT_MS,
|
||||||
|
retryCount: maxRetries = RETRY_COUNT,
|
||||||
|
} = options;
|
||||||
|
|
||||||
if (this.isLoaded) {
|
if (this.isLoaded) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
@@ -53,61 +72,74 @@ const { preloadIcons = [], timeout = 10000, retryCount = 3 } = Astro.props;
|
|||||||
this.notifyObservers();
|
this.notifyObservers();
|
||||||
await this.processPreloadQueue();
|
await this.processPreloadQueue();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to load Iconify:', error);
|
console.error("Failed to load Iconify:", error);
|
||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadWithRetry(timeout, retryCount) {
|
async loadWithRetry(timeoutMs, maxRetries) {
|
||||||
for (let attempt = 1; attempt <= retryCount; attempt++) {
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
||||||
try {
|
try {
|
||||||
await this.loadScript(timeout);
|
await this.loadScript(timeoutMs);
|
||||||
return;
|
return;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(`Iconify load attempt ${attempt} failed:`, error);
|
console.warn(`Iconify load attempt ${attempt} failed:`, error);
|
||||||
if (attempt === retryCount) {
|
if (attempt === maxRetries) {
|
||||||
throw new Error(`Failed to load Iconify after ${retryCount} attempts`);
|
throw new Error(
|
||||||
|
`Failed to load Iconify after ${maxRetries} attempts`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadScript(timeout) {
|
loadScript(timeoutMs) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// 检查是否已经存在
|
|
||||||
if (this.isIconifyReady()) {
|
if (this.isIconifyReady()) {
|
||||||
|
registerWebComponentIconifyCollections();
|
||||||
resolve();
|
resolve();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const existingScript = document.querySelector('script[src*="iconify-icon"]');
|
const existingScript = document.querySelector(
|
||||||
|
'script[src*="iconify-icon"]',
|
||||||
|
);
|
||||||
if (existingScript) {
|
if (existingScript) {
|
||||||
this.waitForIconifyReady().then(resolve).catch(reject);
|
this.waitForIconifyReady()
|
||||||
|
.then(() => {
|
||||||
|
registerWebComponentIconifyCollections();
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
.catch(reject);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const script = document.createElement('script');
|
const script = document.createElement("script");
|
||||||
script.src = 'https://code.iconify.design/iconify-icon/1.0.7/iconify-icon.min.js';
|
script.src = iconifyScriptUrl;
|
||||||
script.async = true;
|
script.async = true;
|
||||||
script.crossOrigin = 'anonymous';
|
|
||||||
|
|
||||||
const timeoutId = setTimeout(() => {
|
const timeoutId = setTimeout(() => {
|
||||||
script.remove();
|
script.remove();
|
||||||
reject(new Error('Script load timeout'));
|
reject(new Error("Script load timeout"));
|
||||||
}, timeout);
|
}, timeoutMs);
|
||||||
|
|
||||||
script.onload = () => {
|
script.onload = () => {
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
this.waitForIconifyReady().then(resolve).catch(reject);
|
this.waitForIconifyReady()
|
||||||
|
.then(() => {
|
||||||
|
registerWebComponentIconifyCollections();
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
.catch(reject);
|
||||||
};
|
};
|
||||||
|
|
||||||
script.onerror = () => {
|
script.onerror = () => {
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
script.remove();
|
script.remove();
|
||||||
reject(new Error('Script load error'));
|
reject(new Error("Script load error"));
|
||||||
};
|
};
|
||||||
|
|
||||||
document.head.appendChild(script);
|
document.head.appendChild(script);
|
||||||
@@ -125,7 +157,7 @@ const { preloadIcons = [], timeout = 10000, retryCount = 3 } = Astro.props;
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Date.now() - startTime > maxWait) {
|
if (Date.now() - startTime > maxWait) {
|
||||||
reject(new Error('Iconify initialization timeout'));
|
reject(new Error("Iconify initialization timeout"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +169,11 @@ const { preloadIcons = [], timeout = 10000, retryCount = 3 } = Astro.props;
|
|||||||
}
|
}
|
||||||
|
|
||||||
isIconifyReady() {
|
isIconifyReady() {
|
||||||
return typeof window !== 'undefined' && 'customElements' in window && customElements.get('iconify-icon') !== undefined;
|
return (
|
||||||
|
typeof window !== "undefined" &&
|
||||||
|
"customElements" in window &&
|
||||||
|
customElements.get("iconify-icon") !== undefined
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoad(callback) {
|
onLoad(callback) {
|
||||||
@@ -149,11 +185,11 @@ const { preloadIcons = [], timeout = 10000, retryCount = 3 } = Astro.props;
|
|||||||
}
|
}
|
||||||
|
|
||||||
notifyObservers() {
|
notifyObservers() {
|
||||||
this.observers.forEach(callback => {
|
this.observers.forEach((callback) => {
|
||||||
try {
|
try {
|
||||||
callback();
|
callback();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error in icon load observer:', error);
|
console.error("Error in icon load observer:", error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.observers.clear();
|
this.observers.clear();
|
||||||
@@ -161,7 +197,7 @@ const { preloadIcons = [], timeout = 10000, retryCount = 3 } = Astro.props;
|
|||||||
|
|
||||||
addToPreloadQueue(icons) {
|
addToPreloadQueue(icons) {
|
||||||
if (Array.isArray(icons)) {
|
if (Array.isArray(icons)) {
|
||||||
icons.forEach(icon => this.preloadQueue.add(icon));
|
icons.forEach((icon) => this.preloadQueue.add(icon));
|
||||||
} else {
|
} else {
|
||||||
this.preloadQueue.add(icons);
|
this.preloadQueue.add(icons);
|
||||||
}
|
}
|
||||||
@@ -172,88 +208,34 @@ const { preloadIcons = [], timeout = 10000, retryCount = 3 } = Astro.props;
|
|||||||
}
|
}
|
||||||
|
|
||||||
async processPreloadQueue() {
|
async processPreloadQueue() {
|
||||||
if (this.preloadQueue.size === 0) return;
|
|
||||||
|
|
||||||
const iconsToLoad = Array.from(this.preloadQueue);
|
|
||||||
this.preloadQueue.clear();
|
this.preloadQueue.clear();
|
||||||
|
|
||||||
await this.preloadIcons(iconsToLoad);
|
|
||||||
}
|
|
||||||
|
|
||||||
async preloadIcons(icons) {
|
|
||||||
if (!this.isLoaded || icons.length === 0) return;
|
|
||||||
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
let loadedCount = 0;
|
|
||||||
const totalIcons = icons.length;
|
|
||||||
const tempElements = [];
|
|
||||||
|
|
||||||
const cleanup = () => {
|
|
||||||
tempElements.forEach(el => {
|
|
||||||
if (el.parentNode) {
|
|
||||||
el.parentNode.removeChild(el);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const checkComplete = () => {
|
|
||||||
loadedCount++;
|
|
||||||
if (loadedCount >= totalIcons) {
|
|
||||||
cleanup();
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
icons.forEach(icon => {
|
|
||||||
const tempIcon = document.createElement('iconify-icon');
|
|
||||||
tempIcon.setAttribute('icon', icon);
|
|
||||||
tempIcon.style.cssText = 'position:absolute;top:-9999px;left:-9999px;width:1px;height:1px;opacity:0;pointer-events:none;';
|
|
||||||
|
|
||||||
tempIcon.addEventListener('load', checkComplete);
|
|
||||||
tempIcon.addEventListener('error', checkComplete);
|
|
||||||
|
|
||||||
tempElements.push(tempIcon);
|
|
||||||
document.body.appendChild(tempIcon);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 设置超时清理
|
|
||||||
setTimeout(() => {
|
|
||||||
cleanup();
|
|
||||||
resolve();
|
|
||||||
}, 3000);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建全局实例
|
|
||||||
window.__iconifyLoader = new IconifyLoader();
|
window.__iconifyLoader = new IconifyLoader();
|
||||||
|
|
||||||
// 立即开始加载
|
window.__iconifyLoader.load().catch((error) => {
|
||||||
window.__iconifyLoader.load().catch(error => {
|
console.error("Failed to initialize Iconify:", error);
|
||||||
console.error('Failed to initialize Iconify:', error);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 如果有预加载图标,添加到队列
|
if (preloadIcons.length > 0) {
|
||||||
if (preloadIcons && preloadIcons.length > 0) {
|
|
||||||
window.__iconifyLoader.addToPreloadQueue(preloadIcons);
|
window.__iconifyLoader.addToPreloadQueue(preloadIcons);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导出便捷函数到全局
|
|
||||||
window.loadIconify = () => window.__iconifyLoader.load();
|
window.loadIconify = () => window.__iconifyLoader.load();
|
||||||
window.preloadIcons = (icons) => window.__iconifyLoader.addToPreloadQueue(icons);
|
window.preloadIcons = (icons) =>
|
||||||
window.onIconifyReady = (callback) => window.__iconifyLoader.onLoad(callback);
|
window.__iconifyLoader.addToPreloadQueue(icons);
|
||||||
|
window.onIconifyReady = (callback) =>
|
||||||
|
window.__iconifyLoader.onLoad(callback);
|
||||||
|
|
||||||
// 页面可见性变化时重新检查
|
document.addEventListener("visibilitychange", () => {
|
||||||
document.addEventListener('visibilitychange', () => {
|
|
||||||
if (!document.hidden && !window.__iconifyLoader.isLoaded) {
|
if (!document.hidden && !window.__iconifyLoader.isLoaded) {
|
||||||
window.__iconifyLoader.load().catch(console.error);
|
window.__iconifyLoader.load().catch(console.error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- 为不支持JavaScript的情况提供备用方案 -->
|
|
||||||
<noscript>
|
<noscript>
|
||||||
<style>
|
<style>
|
||||||
iconify-icon {
|
iconify-icon {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ interface Props {
|
|||||||
const className = Astro.props.class;
|
const className = Astro.props.class;
|
||||||
---
|
---
|
||||||
|
|
||||||
<div data-pagefind-body class={`prose dark:prose-invert prose-base max-w-none! custom-md ${className}`}>
|
<div class={`prose dark:prose-invert prose-base max-w-none! custom-md ${className}`}>
|
||||||
<!--<div class="prose dark:prose-invert max-w-none custom-md">-->
|
<!--<div class="prose dark:prose-invert max-w-none custom-md">-->
|
||||||
<!--<div class="max-w-none custom-md">-->
|
<!--<div class="max-w-none custom-md">-->
|
||||||
<slot/>
|
<slot/>
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import { url } from "@utils/url";
|
|||||||
import { getNavbarTransparentModeForWallpaperMode, getDefaultWallpaperMode } from "@utils/wallpaper";
|
import { getNavbarTransparentModeForWallpaperMode, getDefaultWallpaperMode } from "@utils/wallpaper";
|
||||||
import NavLinks from "@components/navbar/navLinks.astro";
|
import NavLinks from "@components/navbar/navLinks.astro";
|
||||||
import NavMenu from "@components/navbar/navMenu.svelte";
|
import NavMenu from "@components/navbar/navMenu.svelte";
|
||||||
import Search from "@components/navbar/search.svelte";
|
|
||||||
import Translator from "@components/navbar/translator.svelte";
|
import Translator from "@components/navbar/translator.svelte";
|
||||||
import DisplaySettings from "@components/navbar/displaySettings.svelte";
|
import DisplaySettings from "@components/navbar/displaySettings.svelte";
|
||||||
import LightDarkSwitch from "@components/navbar/lightDarkSwitch.svelte";
|
import LightDarkSwitch from "@components/navbar/lightDarkSwitch.svelte";
|
||||||
@@ -51,7 +50,6 @@ let links: NavbarLink[] = navbarConfig.links.map(
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center navbar-buttons" id="navbar-buttons">
|
<div class="flex items-center navbar-buttons" id="navbar-buttons">
|
||||||
<!-- <Search client:load></Search> -->
|
|
||||||
<Translator client:load></Translator>
|
<Translator client:load></Translator>
|
||||||
<!-- <DisplaySettings client:load></DisplaySettings> -->
|
<!-- <DisplaySettings client:load></DisplaySettings> -->
|
||||||
<LightDarkSwitch client:load></LightDarkSwitch>
|
<LightDarkSwitch client:load></LightDarkSwitch>
|
||||||
@@ -134,60 +132,3 @@ if (document.readyState === 'loading') {
|
|||||||
initSemifullScrollDetection();
|
initSemifullScrollDetection();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{import.meta.env.PROD && <script is:inline define:vars={{scriptUrl: url('/pagefind/pagefind.js')}}>
|
|
||||||
async function loadPagefind() {
|
|
||||||
try {
|
|
||||||
const response = await fetch(scriptUrl, { method: 'HEAD' });
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`Pagefind script not found: ${response.status}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const pagefind = await import(scriptUrl);
|
|
||||||
|
|
||||||
await pagefind.options({
|
|
||||||
excerptLength: 20
|
|
||||||
});
|
|
||||||
|
|
||||||
window.pagefind = pagefind;
|
|
||||||
|
|
||||||
document.dispatchEvent(new CustomEvent('pagefindready'));
|
|
||||||
console.log('Pagefind loaded and initialized successfully, event dispatched.');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to load Pagefind:', error);
|
|
||||||
window.pagefind = {
|
|
||||||
search: () => Promise.resolve({ results: [] }),
|
|
||||||
options: () => Promise.resolve(),
|
|
||||||
};
|
|
||||||
document.dispatchEvent(new CustomEvent('pagefindloaderror'));
|
|
||||||
console.log('Pagefind load error, event dispatched.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', loadPagefind);
|
|
||||||
} else {
|
|
||||||
loadPagefind();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Переинициализация Pagefind после навигации Swup
|
|
||||||
if (typeof window !== 'undefined' && window.swup) {
|
|
||||||
window.swup.hooks.on('page:view', () => {
|
|
||||||
// Переинициализируем Pagefind после навигации, если он еще не загружен
|
|
||||||
if (!window.pagefind || typeof window.pagefind.search !== 'function') {
|
|
||||||
loadPagefind();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (typeof window !== 'undefined') {
|
|
||||||
// Если Swup еще не загружен, ждем события
|
|
||||||
document.addEventListener('swup:enable', () => {
|
|
||||||
if (window.swup) {
|
|
||||||
window.swup.hooks.on('page:view', () => {
|
|
||||||
if (!window.pagefind || typeof window.pagefind.search !== 'function') {
|
|
||||||
loadPagefind();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>}
|
|
||||||
@@ -1,285 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { onMount, onDestroy } from "svelte";
|
|
||||||
import Icon from "@iconify/svelte";
|
|
||||||
|
|
||||||
import type { SearchResult } from "@/global";
|
|
||||||
import { url } from "@utils/url";
|
|
||||||
import { navigateToPage } from "@utils/navigation";
|
|
||||||
import { onClickOutside } from "@utils/widget";
|
|
||||||
import { i18n } from "@i18n/translation";
|
|
||||||
import I18nKey from "@i18n/i18nKey";
|
|
||||||
import DropdownPanel from "@/components/common/DropdownPanel.svelte";
|
|
||||||
|
|
||||||
|
|
||||||
let keywordDesktop = $state("");
|
|
||||||
let keywordMobile = $state("");
|
|
||||||
let result: SearchResult[] = $state([]);
|
|
||||||
let isSearching = $state(false);
|
|
||||||
let pagefindLoaded = false;
|
|
||||||
let initialized = $state(false);
|
|
||||||
let isDesktopSearchExpanded = $state(false);
|
|
||||||
let debounceTimer: NodeJS.Timeout;
|
|
||||||
|
|
||||||
const fakeResult: SearchResult[] = [
|
|
||||||
{
|
|
||||||
url: url("/"),
|
|
||||||
meta: {
|
|
||||||
title: "This Is a Fake Search Result",
|
|
||||||
},
|
|
||||||
excerpt:
|
|
||||||
"Because the search cannot work in the <mark>dev</mark> environment.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: url("/"),
|
|
||||||
meta: {
|
|
||||||
title: "If You Want to Test the Search",
|
|
||||||
},
|
|
||||||
excerpt: "Try running <mark>npm build && npm preview</mark> instead.",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const togglePanel = () => {
|
|
||||||
const panel = document.getElementById("search-panel");
|
|
||||||
panel?.classList.toggle("float-panel-closed");
|
|
||||||
};
|
|
||||||
|
|
||||||
const toggleDesktopSearch = () => {
|
|
||||||
isDesktopSearchExpanded = !isDesktopSearchExpanded;
|
|
||||||
if (isDesktopSearchExpanded) {
|
|
||||||
setTimeout(() => {
|
|
||||||
const input = document.getElementById("search-input-desktop") as HTMLInputElement;
|
|
||||||
input?.focus();
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const collapseDesktopSearch = () => {
|
|
||||||
if (!keywordDesktop) {
|
|
||||||
isDesktopSearchExpanded = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleBlur = () => {
|
|
||||||
// 延迟处理以允许搜索结果的点击事件先于折叠逻辑执行
|
|
||||||
setTimeout(() => {
|
|
||||||
isDesktopSearchExpanded = false;
|
|
||||||
// 仅隐藏面板并折叠,保留搜索关键词和结果以便下次展开时查看
|
|
||||||
setPanelVisibility(false, true);
|
|
||||||
}, 200);
|
|
||||||
};
|
|
||||||
|
|
||||||
const setPanelVisibility = (show: boolean, isDesktop: boolean): void => {
|
|
||||||
const panel = document.getElementById("search-panel");
|
|
||||||
if (!panel || !isDesktop) return;
|
|
||||||
if (show) {
|
|
||||||
panel.classList.remove("float-panel-closed");
|
|
||||||
} else {
|
|
||||||
panel.classList.add("float-panel-closed");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const closeSearchPanel = (): void => {
|
|
||||||
const panel = document.getElementById("search-panel");
|
|
||||||
if (panel) {
|
|
||||||
panel.classList.add("float-panel-closed");
|
|
||||||
}
|
|
||||||
// 清空搜索关键词和结果
|
|
||||||
keywordDesktop = "";
|
|
||||||
keywordMobile = "";
|
|
||||||
result = [];
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleResultClick = (event: Event, url: string): void => {
|
|
||||||
event.preventDefault();
|
|
||||||
closeSearchPanel();
|
|
||||||
navigateToPage(url);
|
|
||||||
};
|
|
||||||
|
|
||||||
const search = async (keyword: string, isDesktop: boolean): Promise<void> => {
|
|
||||||
if (!keyword) {
|
|
||||||
setPanelVisibility(false, isDesktop);
|
|
||||||
result = [];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!initialized) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
isSearching = true;
|
|
||||||
try {
|
|
||||||
let searchResults: SearchResult[] = [];
|
|
||||||
if (import.meta.env.PROD && pagefindLoaded && window.pagefind) {
|
|
||||||
const response = await window.pagefind.search(keyword);
|
|
||||||
searchResults = await Promise.all(
|
|
||||||
response.results.map((item) => item.data()),
|
|
||||||
);
|
|
||||||
} else if (import.meta.env.DEV) {
|
|
||||||
searchResults = fakeResult;
|
|
||||||
} else {
|
|
||||||
searchResults = [];
|
|
||||||
console.error("Pagefind is not available in production environment.");
|
|
||||||
}
|
|
||||||
result = searchResults;
|
|
||||||
setPanelVisibility(result.length > 0, isDesktop);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Search error:", error);
|
|
||||||
result = [];
|
|
||||||
setPanelVisibility(false, isDesktop);
|
|
||||||
} finally {
|
|
||||||
isSearching = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleClickOutside = (event: MouseEvent) => {
|
|
||||||
const panel = document.getElementById("search-panel");
|
|
||||||
if (!panel || panel.classList.contains("float-panel-closed")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
onClickOutside(event, "search-panel", ["search-switch", "search-bar"], () => {
|
|
||||||
const panel = document.getElementById("search-panel");
|
|
||||||
panel?.classList.add("float-panel-closed");
|
|
||||||
isDesktopSearchExpanded = false;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
document.addEventListener("click", handleClickOutside);
|
|
||||||
const initializeSearch = () => {
|
|
||||||
initialized = true;
|
|
||||||
pagefindLoaded =
|
|
||||||
typeof window !== "undefined" &&
|
|
||||||
!!window.pagefind &&
|
|
||||||
typeof window.pagefind.search === "function";
|
|
||||||
console.log("Pagefind status on init:", pagefindLoaded);
|
|
||||||
};
|
|
||||||
if (import.meta.env.DEV) {
|
|
||||||
console.log(
|
|
||||||
"Pagefind is not available in development mode. Using mock data.",
|
|
||||||
);
|
|
||||||
initializeSearch();
|
|
||||||
} else {
|
|
||||||
document.addEventListener("pagefindready", () => {
|
|
||||||
console.log("Pagefind ready event received.");
|
|
||||||
initializeSearch();
|
|
||||||
});
|
|
||||||
document.addEventListener("pagefindloaderror", () => {
|
|
||||||
console.warn(
|
|
||||||
"Pagefind load error event received. Search functionality will be limited.",
|
|
||||||
);
|
|
||||||
initializeSearch(); // Initialize with pagefindLoaded as false
|
|
||||||
});
|
|
||||||
// Fallback in case events are not caught or pagefind is already loaded by the time this script runs
|
|
||||||
setTimeout(() => {
|
|
||||||
if (!initialized) {
|
|
||||||
console.log("Fallback: Initializing search after timeout.");
|
|
||||||
initializeSearch();
|
|
||||||
}
|
|
||||||
}, 2000); // Adjust timeout as needed
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$effect(() => {
|
|
||||||
if (initialized) {
|
|
||||||
const keyword = keywordDesktop || keywordMobile;
|
|
||||||
const isDesktop = !!keywordDesktop || isDesktopSearchExpanded;
|
|
||||||
|
|
||||||
clearTimeout(debounceTimer);
|
|
||||||
if (keyword) {
|
|
||||||
debounceTimer = setTimeout(() => {
|
|
||||||
search(keyword, isDesktop);
|
|
||||||
}, 300);
|
|
||||||
} else {
|
|
||||||
result = [];
|
|
||||||
setPanelVisibility(false, isDesktop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$effect(() => {
|
|
||||||
if (typeof document !== 'undefined') {
|
|
||||||
const navbar = document.getElementById('navbar');
|
|
||||||
if (isDesktopSearchExpanded) {
|
|
||||||
navbar?.classList.add('is-searching');
|
|
||||||
} else {
|
|
||||||
navbar?.classList.remove('is-searching');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
onDestroy(() => {
|
|
||||||
if (typeof document !== 'undefined') {
|
|
||||||
document.removeEventListener("click", handleClickOutside);
|
|
||||||
const navbar = document.getElementById('navbar');
|
|
||||||
navbar?.classList.remove('is-searching');
|
|
||||||
}
|
|
||||||
clearTimeout(debounceTimer);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- search bar for desktop view (collapsed by default) -->
|
|
||||||
<div
|
|
||||||
id="search-bar"
|
|
||||||
class="hidden lg:flex transition-all items-center h-11 rounded-lg
|
|
||||||
{isDesktopSearchExpanded ? 'bg-black/4 hover:bg-black/6 focus-within:bg-black/6 dark:bg-white/5 dark:hover:bg-white/10 dark:focus-within:bg-white/10' : 'btn-plain scale-animation active:scale-90'}
|
|
||||||
{isDesktopSearchExpanded ? 'w-48' : 'w-11'}"
|
|
||||||
role="button"
|
|
||||||
tabindex="0"
|
|
||||||
aria-label="Search"
|
|
||||||
onmouseenter={() => {if (!isDesktopSearchExpanded) toggleDesktopSearch()}}
|
|
||||||
onmouseleave={collapseDesktopSearch}
|
|
||||||
>
|
|
||||||
<Icon icon="material-symbols:search" class="absolute text-[1.25rem] pointer-events-none {isDesktopSearchExpanded ? 'ml-3' : 'left-1/2 -translate-x-1/2'} transition my-auto {isDesktopSearchExpanded ? 'text-black/30 dark:text-white/30' : ''}"></Icon>
|
|
||||||
<input id="search-input-desktop" placeholder="{i18n(I18nKey.search)}" bind:value={keywordDesktop}
|
|
||||||
onfocus={() => {if (!isDesktopSearchExpanded) toggleDesktopSearch(); search(keywordDesktop, true)}}
|
|
||||||
onblur={handleBlur}
|
|
||||||
class="transition-all pl-10 text-sm bg-transparent outline-0
|
|
||||||
h-full {isDesktopSearchExpanded ? 'w-36' : 'w-0'} text-black/50 dark:text-white/50"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- toggle btn for phone/tablet view -->
|
|
||||||
<button onclick={togglePanel} aria-label="Search Panel" id="search-switch"
|
|
||||||
class="btn-plain scale-animation lg:hidden! rounded-lg w-11 h-11 active:scale-90">
|
|
||||||
<Icon icon="material-symbols:search" class="text-[1.25rem]"></Icon>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- search panel -->
|
|
||||||
<DropdownPanel
|
|
||||||
id="search-panel"
|
|
||||||
class="float-panel-closed absolute md:w-120 top-20 left-4 md:left-[unset] right-4 z-50 search-panel"
|
|
||||||
>
|
|
||||||
<!-- search bar inside panel for phone/tablet -->
|
|
||||||
<div id="search-bar-inside" class="flex relative lg:hidden transition-all items-center h-11 rounded-xl
|
|
||||||
bg-black/4 hover:bg-black/6 focus-within:bg-black/6
|
|
||||||
dark:bg-white/5 dark:hover:bg-white/10 dark:focus-within:bg-white/10
|
|
||||||
">
|
|
||||||
<Icon icon="material-symbols:search" class="absolute text-[1.25rem] pointer-events-none ml-3 transition my-auto text-black/30 dark:text-white/30"></Icon>
|
|
||||||
<input placeholder="Search" bind:value={keywordMobile}
|
|
||||||
class="pl-10 absolute inset-0 text-sm bg-transparent outline-0
|
|
||||||
focus:w-60 text-black/50 dark:text-white/50"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<!-- search results -->
|
|
||||||
{#each result as item}
|
|
||||||
<a href={item.url}
|
|
||||||
onclick={(e) => handleResultClick(e, item.url)}
|
|
||||||
class="transition first-of-type:mt-2 lg:first-of-type:mt-0 group block
|
|
||||||
rounded-xl text-lg px-3 py-2 hover:bg-(--btn-plain-bg-hover) active:bg-(--btn-plain-bg-active)">
|
|
||||||
<div class="transition text-90 inline-flex font-bold group-hover:text-(--primary)">
|
|
||||||
{item.meta.title}<Icon icon="fa6-solid:chevron-right" class="transition text-[0.75rem] translate-x-1 my-auto text-(--primary)"></Icon>
|
|
||||||
</div>
|
|
||||||
<div class="transition text-sm text-50">
|
|
||||||
{@html item.excerpt}
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
{/each}
|
|
||||||
</DropdownPanel>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
input:focus {
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
:global(.search-panel) {
|
|
||||||
max-height: calc(100vh - 100px);
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
37
src/global.d.ts
vendored
37
src/global.d.ts
vendored
@@ -14,13 +14,6 @@ declare global {
|
|||||||
__iconifyLoader: {
|
__iconifyLoader: {
|
||||||
load: () => Promise<void>;
|
load: () => Promise<void>;
|
||||||
};
|
};
|
||||||
pagefind: {
|
|
||||||
search: (query: string) => Promise<{
|
|
||||||
results: Array<{
|
|
||||||
data: () => Promise<SearchResult>;
|
|
||||||
}>;
|
|
||||||
}>;
|
|
||||||
};
|
|
||||||
translate?: {
|
translate?: {
|
||||||
service: {
|
service: {
|
||||||
use: (service: string) => void;
|
use: (service: string) => void;
|
||||||
@@ -51,32 +44,4 @@ declare global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export {};
|
||||||
interface SearchResult {
|
|
||||||
url: string;
|
|
||||||
meta: {
|
|
||||||
title: string;
|
|
||||||
};
|
|
||||||
excerpt: string;
|
|
||||||
content?: string;
|
|
||||||
word_count?: number;
|
|
||||||
filters?: Record<string, unknown>;
|
|
||||||
anchors?: Array<{
|
|
||||||
element: string;
|
|
||||||
id: string;
|
|
||||||
text: string;
|
|
||||||
location: number;
|
|
||||||
}>;
|
|
||||||
weighted_locations?: Array<{
|
|
||||||
weight: number;
|
|
||||||
balanced_score: number;
|
|
||||||
location: number;
|
|
||||||
}>;
|
|
||||||
locations?: number[];
|
|
||||||
raw_content?: string;
|
|
||||||
raw_url?: string;
|
|
||||||
sub_results?: SearchResult[];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export { SearchResult };
|
|
||||||
|
|||||||
@@ -127,7 +127,6 @@ const umamiScripts = umamiConfig.scripts || ""; // 获取Umami scripts配置
|
|||||||
<!-- Resource Preconnect -->
|
<!-- Resource Preconnect -->
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link rel="preconnect" href="https://code.iconify.design">
|
|
||||||
<!-- Font Loader -->
|
<!-- Font Loader -->
|
||||||
<FontLoader />
|
<FontLoader />
|
||||||
<!-- title -->
|
<!-- title -->
|
||||||
@@ -481,26 +480,19 @@ loadAndInitTranslate();
|
|||||||
// Initialize particle effects
|
// Initialize particle effects
|
||||||
setupParticleEffects();
|
setupParticleEffects();
|
||||||
|
|
||||||
// Remove is-loading class and trigger initial-animation after page load
|
function hideLoadingOverlay() {
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
window.addEventListener('load', () => {
|
|
||||||
const overlay = document.getElementById('loading-overlay');
|
const overlay = document.getElementById('loading-overlay');
|
||||||
const enableBanner = document.body.classList.contains('enable-banner');
|
const enableBanner = document.body.classList.contains('enable-banner');
|
||||||
// 触发 LoadingOverlay 淡出
|
|
||||||
if (overlay) {
|
if (overlay) {
|
||||||
overlay.classList.add('fade-out');
|
overlay.classList.add('fade-out');
|
||||||
}
|
}
|
||||||
// 等待 LoadingOverlay 淡出(600ms)
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (overlay) {
|
if (overlay) {
|
||||||
overlay.style.display = 'none';
|
overlay.style.display = 'none';
|
||||||
}
|
}
|
||||||
if (enableBanner) {
|
if (enableBanner) {
|
||||||
// banner 开始恢复过渡:添加 banner-restoring 类(解除 CSS 中的 height: 0)
|
|
||||||
document.documentElement.classList.add('banner-restoring');
|
document.documentElement.classList.add('banner-restoring');
|
||||||
// 等待 banner 恢复过渡完成(600ms)
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// 触发各容器淡入动画
|
|
||||||
document.documentElement.classList.remove('is-loading');
|
document.documentElement.classList.remove('is-loading');
|
||||||
document.documentElement.classList.add('show-initial-animation');
|
document.documentElement.classList.add('show-initial-animation');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -509,7 +501,6 @@ if (typeof window !== 'undefined') {
|
|||||||
}, 1200);
|
}, 1200);
|
||||||
}, 600);
|
}, 600);
|
||||||
} else {
|
} else {
|
||||||
// 非 banner 模式,直接触发淡入
|
|
||||||
document.documentElement.classList.remove('is-loading');
|
document.documentElement.classList.remove('is-loading');
|
||||||
document.documentElement.classList.add('show-initial-animation');
|
document.documentElement.classList.add('show-initial-animation');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -517,6 +508,13 @@ if (typeof window !== 'undefined') {
|
|||||||
}, 1200);
|
}, 1200);
|
||||||
}
|
}
|
||||||
}, 600);
|
}, 600);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', hideLoadingOverlay);
|
||||||
|
} else {
|
||||||
|
hideLoadingOverlay();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -153,9 +153,6 @@ const jsonLd = {
|
|||||||
<!-- title -->
|
<!-- title -->
|
||||||
<div class="relative onload-animation-up">
|
<div class="relative onload-animation-up">
|
||||||
<div
|
<div
|
||||||
data-pagefind-body
|
|
||||||
data-pagefind-weight="10"
|
|
||||||
data-pagefind-meta="title"
|
|
||||||
class="transition w-full block font-bold mb-3
|
class="transition w-full block font-bold mb-3
|
||||||
text-3xl md:text-[2.25rem]/[2.75rem]
|
text-3xl md:text-[2.25rem]/[2.75rem]
|
||||||
text-black/90 dark:text-white/90
|
text-black/90 dark:text-white/90
|
||||||
|
|||||||
78
src/utils/iconify-offline.ts
Normal file
78
src/utils/iconify-offline.ts
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import { addCollection } from "@iconify/svelte/dist/functions.js";
|
||||||
|
import type { IconifyJSON } from "@iconify/types";
|
||||||
|
import devicon from "@iconify-json/devicon/icons.json";
|
||||||
|
import gameIcons from "@iconify-json/game-icons/icons.json";
|
||||||
|
import hugeicons from "@iconify-json/hugeicons/icons.json";
|
||||||
|
import iconoir from "@iconify-json/iconoir/icons.json";
|
||||||
|
import logos from "@iconify-json/logos/icons.json";
|
||||||
|
import materialIconTheme from "@iconify-json/material-icon-theme/icons.json";
|
||||||
|
import materialSymbols from "@iconify-json/material-symbols/icons.json";
|
||||||
|
import mdi from "@iconify-json/mdi/icons.json";
|
||||||
|
import mingcute from "@iconify-json/mingcute/icons.json";
|
||||||
|
import skillIcons from "@iconify-json/skill-icons/icons.json";
|
||||||
|
import vscodeIcons from "@iconify-json/vscode-icons/icons.json";
|
||||||
|
|
||||||
|
const collections: IconifyJSON[] = [
|
||||||
|
materialSymbols,
|
||||||
|
logos,
|
||||||
|
devicon,
|
||||||
|
hugeicons,
|
||||||
|
mingcute,
|
||||||
|
mdi,
|
||||||
|
skillIcons,
|
||||||
|
vscodeIcons,
|
||||||
|
materialIconTheme,
|
||||||
|
gameIcons,
|
||||||
|
iconoir,
|
||||||
|
];
|
||||||
|
|
||||||
|
let svelteRegistered = false;
|
||||||
|
let webComponentRegistered = false;
|
||||||
|
|
||||||
|
function addCollectionsToWebComponent(): void {
|
||||||
|
if (typeof window === "undefined" || webComponentRegistered) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const IconifyIcon = customElements.get("iconify-icon") as
|
||||||
|
| (CustomElementConstructor & {
|
||||||
|
addCollection?: (data: IconifyJSON, provider?: string) => boolean;
|
||||||
|
disableCache?: (storage: string) => void;
|
||||||
|
})
|
||||||
|
| undefined;
|
||||||
|
|
||||||
|
if (!IconifyIcon?.addCollection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IconifyIcon.disableCache?.("all");
|
||||||
|
|
||||||
|
for (const collection of collections) {
|
||||||
|
IconifyIcon.addCollection(collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
webComponentRegistered = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Register offline collections for @iconify/svelte (navbar, player, etc.). */
|
||||||
|
export function registerSvelteIconifyCollections(): void {
|
||||||
|
if (svelteRegistered) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
svelteRegistered = true;
|
||||||
|
|
||||||
|
for (const collection of collections) {
|
||||||
|
addCollection(collection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Register offline collections for iconify-icon web component (icon.astro). */
|
||||||
|
export function registerWebComponentIconifyCollections(): void {
|
||||||
|
addCollectionsToWebComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Register all offline icon sets (Svelte + web component when available). */
|
||||||
|
export function registerIconifyCollections(): void {
|
||||||
|
registerSvelteIconifyCollections();
|
||||||
|
registerWebComponentIconifyCollections();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user