Fix PWA shortcut icon on Windows
Allow unauthenticated access to favicon and manifest, generate favicon.ico, and add multi-size manifest icons. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -38,4 +38,8 @@ node_modules/
|
||||
.vitepress/cache/
|
||||
.vitepress/public/
|
||||
server/auth.config.json
|
||||
assets/site/favicon.ico
|
||||
assets/site/favicon.png
|
||||
assets/site/icon-192.png
|
||||
assets/site/icon-512.png
|
||||
|
||||
|
||||
@@ -26,16 +26,20 @@ export default defineConfig({
|
||||
cleanUrls: true,
|
||||
ignoreDeadLinks: true,
|
||||
head: [
|
||||
['link', { rel: 'icon', href: '/favicon.ico', sizes: 'any' }],
|
||||
['link', { rel: 'shortcut icon', href: '/favicon.ico' }],
|
||||
['link', { rel: 'icon', href: '/favicon.svg', type: 'image/svg+xml' }],
|
||||
['link', { rel: 'icon', href: '/favicon.png', type: 'image/png', sizes: '512x512' }],
|
||||
['link', { rel: 'apple-touch-icon', href: '/apple-touch-icon.png', sizes: '180x180' }],
|
||||
['link', { rel: 'manifest', href: '/site.webmanifest' }],
|
||||
['meta', { name: 'theme-color', content: '#0f3460' }],
|
||||
['meta', { name: 'msapplication-TileColor', content: '#0f3460' }],
|
||||
['meta', { name: 'msapplication-TileImage', content: '/apple-touch-icon.png' }],
|
||||
['meta', { name: 'apple-mobile-web-app-title', content: '道德经' }],
|
||||
['meta', { name: 'application-name', content: 'DAO DE JING' }],
|
||||
['meta', { name: 'application-name', content: '道德经' }],
|
||||
],
|
||||
themeConfig: {
|
||||
logo: { src: '/favicon.png', width: 24, height: 24 },
|
||||
logo: { src: '/favicon.ico', width: 24, height: 24 },
|
||||
nav: [
|
||||
{ text: '首页', link: '/' },
|
||||
{ text: '五行', link: '/金、木、水、火、土 - 五行/' },
|
||||
|
||||
BIN
Binary file not shown.
@@ -3,20 +3,33 @@
|
||||
"short_name": "道德经",
|
||||
"description": "传统文化典籍资料库",
|
||||
"start_url": "/",
|
||||
"scope": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#1a1a2e",
|
||||
"theme_color": "#0f3460",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/apple-touch-icon.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
"src": "/favicon.ico",
|
||||
"sizes": "48x48",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "/favicon.png",
|
||||
"src": "/icon-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/icon-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/icon-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Generated
+1586
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,8 @@
|
||||
"serve": "npm run build && npm run start"
|
||||
},
|
||||
"devDependencies": {
|
||||
"sharp": "^0.33.5",
|
||||
"to-ico": "^1.1.5",
|
||||
"vitepress": "^1.6.3"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import sharp from 'sharp'
|
||||
import toIco from 'to-ico'
|
||||
|
||||
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
||||
const siteDir = path.join(root, 'assets', 'site')
|
||||
const sourcePng = path.join(siteDir, 'apple-touch-icon.png')
|
||||
|
||||
if (!fs.existsSync(sourcePng)) {
|
||||
console.warn('[generate-icons] 跳过:未找到 apple-touch-icon.png')
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
async function resizePng(size) {
|
||||
return sharp(sourcePng).resize(size, size).png().toBuffer()
|
||||
}
|
||||
|
||||
const icoSizes = [16, 32, 48, 64, 128, 256]
|
||||
const icoBuffers = await Promise.all(icoSizes.map((size) => resizePng(size)))
|
||||
const icoBuffer = await toIco(icoBuffers)
|
||||
|
||||
fs.writeFileSync(path.join(siteDir, 'favicon.ico'), icoBuffer)
|
||||
fs.writeFileSync(path.join(siteDir, 'icon-192.png'), await resizePng(192))
|
||||
fs.writeFileSync(path.join(siteDir, 'icon-512.png'), await resizePng(512))
|
||||
fs.writeFileSync(path.join(siteDir, 'favicon.png'), await resizePng(512))
|
||||
|
||||
console.log('[generate-icons] 已生成 favicon.ico、icon-192.png、icon-512.png')
|
||||
@@ -28,14 +28,21 @@ function resetPublicDir() {
|
||||
}
|
||||
|
||||
resetPublicDir()
|
||||
await import('./generate-icons.mjs')
|
||||
copyDir(path.join(root, 'assets'), path.join(publicDir, 'assets'))
|
||||
copyDir(path.join(root, 'images'), path.join(publicDir, 'images'))
|
||||
|
||||
const siteDir = path.join(root, 'assets', 'site')
|
||||
if (fs.existsSync(siteDir)) {
|
||||
const skipInPublicRoot = new Set(['apple-touch-icon.png'])
|
||||
for (const file of fs.readdirSync(siteDir)) {
|
||||
if (skipInPublicRoot.has(file)) continue
|
||||
fs.copyFileSync(path.join(siteDir, file), path.join(publicDir, file))
|
||||
}
|
||||
fs.copyFileSync(
|
||||
path.join(siteDir, 'icon-512.png'),
|
||||
path.join(publicDir, 'apple-touch-icon.png'),
|
||||
)
|
||||
}
|
||||
|
||||
console.log('[prepare-public] assets、images 与站点图标已同步到 .vitepress/public')
|
||||
|
||||
@@ -89,11 +89,33 @@ function isAuthenticated(req) {
|
||||
return Boolean(req.session?.user)
|
||||
}
|
||||
|
||||
const PUBLIC_PATHS = new Set([
|
||||
'/favicon.ico',
|
||||
'/favicon.png',
|
||||
'/favicon.svg',
|
||||
'/apple-touch-icon.png',
|
||||
'/icon-192.png',
|
||||
'/icon-512.png',
|
||||
'/site.webmanifest',
|
||||
'/vp-icons.css',
|
||||
'/hashmap.json',
|
||||
])
|
||||
|
||||
function isPublicPath(reqPath) {
|
||||
if (PUBLIC_PATHS.has(reqPath)) return true
|
||||
if (reqPath.startsWith('/assets/')) return true
|
||||
return false
|
||||
}
|
||||
|
||||
function authGuard(req, res, next) {
|
||||
if (req.path === '/login' || req.path.startsWith('/api/login')) {
|
||||
return next()
|
||||
}
|
||||
|
||||
if (isPublicPath(req.path)) {
|
||||
return next()
|
||||
}
|
||||
|
||||
if (isAuthenticated(req)) {
|
||||
return next()
|
||||
}
|
||||
|
||||
@@ -5,10 +5,14 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="theme-color" content="#0f3460" />
|
||||
<meta name="apple-mobile-web-app-title" content="道德经" />
|
||||
<link rel="icon" href="/favicon.ico" sizes="any" />
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
||||
<link rel="icon" href="/favicon.png" type="image/png" sizes="512x512" />
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
<meta name="msapplication-TileColor" content="#0f3460" />
|
||||
<meta name="msapplication-TileImage" content="/apple-touch-icon.png" />
|
||||
<title>登录 · DAO DE JING</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; }
|
||||
|
||||
Reference in New Issue
Block a user