字体加密

This commit is contained in:
biss committed 2026-07-18 15:33:30 +08:00
1 parent 8c8af844aa
commit ecadaaaaf1
7 files changed
+517 -8

No files matched your search

+4 -1
View File
@@ -12,6 +12,7 @@
- 留言墙:接入 Twikoo 后可在页面中留言。 - 留言墙:接入 Twikoo 后可在页面中留言。
- 全站搜索:通过 Typesense 搜索并筛选时间线、照片、文章和同学公开资料。 - 全站搜索:通过 Typesense 搜索并筛选时间线、照片、文章和同学公开资料。
- PWA:支持添加到主屏幕,并离线访问站点外壳及已浏览的同源内容。 - PWA:支持添加到主屏幕,并离线访问站点外壳及已浏览的同源内容。
- 字体加密:生产构建会随机混淆页面中的汉字,并生成按需裁剪的 WOFF2 字体,降低静态内容被直接复制或抓取的风险。
## 技术栈 ## 技术栈
@@ -38,7 +39,9 @@ npm run preview # 预览构建结果
npm run search:sync # 将公开内容同步到 Typesense npm run search:sync # 将公开内容同步到 Typesense
``` ```
`npm run build` 会在 Astro 构建完成后生成带内容版本号的 Service Worker,并预缓存页面、样式、脚本、应用图标和首页主视觉。照片等大体积资源采用访问后缓存,第三方接口始终走网络。 `npm run build` 会在 Astro 构建完成后加密页面字体,再生成带内容版本号的 Service Worker,并预缓存页面、样式、脚本、加密字体、应用图标和首页主视觉。照片等大体积资源采用访问后缓存,第三方接口始终走网络。
字体加密只作用于 `dist` 中的生产页面,不修改源码,也不会影响本地开发。每次构建默认生成新的随机映射;如需可复现产物,可设置 `FONT_ENCRYPTION_SEED`。`code`、`pre`、表单属性以及脚本动态生成的内容会保留原文,以免影响复制和交互。字体加密只能提高批量采集成本,不能替代访问控制或版权保护。
## Typesense 全站搜索 ## Typesense 全站搜索
+124 -3
View File
@@ -16,9 +16,12 @@
"typescript": "^6.0.3" "typescript": "^6.0.3"
}, },
"devDependencies": { "devDependencies": {
"@openfonts/noto-sans-sc_chinese-simplified": "^1.44.9",
"@types/d3-geo": "^3.1.0", "@types/d3-geo": "^3.1.0",
"@types/node": "^26.1.1", "@types/node": "^26.1.1",
"@types/topojson-client": "^3.1.5", "@types/topojson-client": "^3.1.5",
"parse5": "^8.0.0",
"subset-font": "^2.5.0",
"tsx": "^4.23.1" "tsx": "^4.23.1"
} }
}, },
@@ -1657,6 +1660,13 @@
"@emnapi/runtime": "^1.7.1" "@emnapi/runtime": "^1.7.1"
} }
}, },
"node_modules/@openfonts/noto-sans-sc_chinese-simplified": {
"version": "1.44.9",
"resolved": "https://registry.npmjs.org/@openfonts/noto-sans-sc_chinese-simplified/-/noto-sans-sc_chinese-simplified-1.44.9.tgz",
"integrity": "sha512-yNmtcyVuDWU/5KQnRdD+u45QsGXZlNvpwV9+/cIR8z90iHroDscQuXZTtsNy0CfhPq2pNncJVgzhNq62XLGikQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@oslojs/encoding": { "node_modules/@oslojs/encoding": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz", "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz",
@@ -3109,6 +3119,17 @@
"node": ">=20" "node": ">=20"
} }
}, },
"node_modules/fontverter": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fontverter/-/fontverter-2.0.0.tgz",
"integrity": "sha512-DFVX5hvXuhi1Jven1tbpebYTCT9XYnvx6/Z+HFUPb7ZRMCW+pj2clU9VMhoTPgWKPhAs7JJDSk3CW1jNUvKCZQ==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"wawoff2": "^2.0.0",
"woff2sfnt-sfnt2woff": "^1.0.0"
}
},
"node_modules/fsevents": { "node_modules/fsevents": {
"version": "2.3.3", "version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
@@ -3170,6 +3191,13 @@
"uncrypto": "^0.1.3" "uncrypto": "^0.1.3"
} }
}, },
"node_modules/harfbuzzjs": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/harfbuzzjs/-/harfbuzzjs-0.10.3.tgz",
"integrity": "sha512-GJnLUrgLMadlMYrBGEXwYEimObbysy3prWT4HyPpFQERvgTU/OZ+ReUlEPOum6w4RBtFXzXiCCmECOr4sz3qwQ==",
"dev": true,
"license": "MIT"
},
"node_modules/hast-util-from-html": { "node_modules/hast-util-from-html": {
"version": "2.0.3", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz",
@@ -3188,6 +3216,18 @@
"url": "https://opencollective.com/unified" "url": "https://opencollective.com/unified"
} }
}, },
"node_modules/hast-util-from-html/node_modules/parse5": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
"integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
"license": "MIT",
"dependencies": {
"entities": "^6.0.0"
},
"funding": {
"url": "https://github.com/inikulin/parse5?sponsor=1"
}
},
"node_modules/hast-util-from-parse5": { "node_modules/hast-util-from-parse5": {
"version": "8.0.3", "version": "8.0.3",
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz",
@@ -3654,6 +3694,13 @@
"url": "https://opencollective.com/parcel" "url": "https://opencollective.com/parcel"
} }
}, },
"node_modules/lodash": {
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
"dev": true,
"license": "MIT"
},
"node_modules/lru-cache": { "node_modules/lru-cache": {
"version": "11.5.2", "version": "11.5.2",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz",
@@ -3983,10 +4030,18 @@
"integrity": "sha512-xg1eHpwYL/D/HEdWw2goFZP6vV0FH7W+PZ5rFkGjdIDLtxq7EkzBUeT3m+lndYCt8wKbmofUu1MUdMCXkCk9ZQ==", "integrity": "sha512-xg1eHpwYL/D/HEdWw2goFZP6vV0FH7W+PZ5rFkGjdIDLtxq7EkzBUeT3m+lndYCt8wKbmofUu1MUdMCXkCk9ZQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/pako": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
"dev": true,
"license": "(MIT AND Zlib)"
},
"node_modules/parse5": { "node_modules/parse5": {
"version": "7.3.0", "version": "8.0.0",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz",
"integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"entities": "^6.0.0" "entities": "^6.0.0"
@@ -4410,6 +4465,48 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/subset-font": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/subset-font/-/subset-font-2.5.0.tgz",
"integrity": "sha512-Vsa8ngQ/ohhUj0an7on49y9jLZ2rK5U+T1FzPM4/ZQY0xUy5mLis6BfFtPGzecTjFgYXQlvY7FlsJF4t3R/6Ug==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"fontverter": "^2.0.0",
"harfbuzzjs": "^0.10.3",
"lodash": "^4.17.21",
"p-limit": "^3.1.0"
}
},
"node_modules/subset-font/node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"yocto-queue": "^0.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/subset-font/node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/svgo": { "node_modules/svgo": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.2.tgz", "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.2.tgz",
@@ -5216,6 +5313,20 @@
"integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/wawoff2": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/wawoff2/-/wawoff2-2.0.1.tgz",
"integrity": "sha512-r0CEmvpH63r4T15ebFqeOjGqU4+EgTx4I510NtK35EMciSdcTxCw3Byy3JnBonz7iyIFZ0AbVo0bbFpEVuhCYA==",
"dev": true,
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"woff2_compress.js": "bin/woff2_compress.js",
"woff2_decompress.js": "bin/woff2_decompress.js"
}
},
"node_modules/web-namespaces": { "node_modules/web-namespaces": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz",
@@ -5226,6 +5337,16 @@
"url": "https://github.com/sponsors/wooorm" "url": "https://github.com/sponsors/wooorm"
} }
}, },
"node_modules/woff2sfnt-sfnt2woff": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/woff2sfnt-sfnt2woff/-/woff2sfnt-sfnt2woff-1.0.0.tgz",
"integrity": "sha512-edK4COc1c1EpRfMqCZO1xJOvdUtM5dbVb9iz97rScvnTevqEB3GllnLWCmMVp1MfQBdF1DFg/11I0rSyAdS4qQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"pako": "^1.0.7"
}
},
"node_modules/wrap-ansi": { "node_modules/wrap-ansi": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+4 -1
View File
@@ -5,7 +5,7 @@
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "astro dev", "dev": "astro dev",
"build": "astro build && node scripts/build-pwa.mjs", "build": "astro build && node scripts/encrypt-font.mjs && node scripts/build-pwa.mjs",
"preview": "astro preview", "preview": "astro preview",
"search:key": "node --env-file-if-exists=.env --env-file-if-exists=.env.local scripts/create-typesense-search-key.mjs", "search:key": "node --env-file-if-exists=.env --env-file-if-exists=.env.local scripts/create-typesense-search-key.mjs",
"search:sync": "node --env-file-if-exists=.env --env-file-if-exists=.env.local --import tsx scripts/sync-typesense.ts" "search:sync": "node --env-file-if-exists=.env --env-file-if-exists=.env.local --import tsx scripts/sync-typesense.ts"
@@ -19,9 +19,12 @@
"typescript": "^6.0.3" "typescript": "^6.0.3"
}, },
"devDependencies": { "devDependencies": {
"@openfonts/noto-sans-sc_chinese-simplified": "^1.44.9",
"@types/d3-geo": "^3.1.0", "@types/d3-geo": "^3.1.0",
"@types/node": "^26.1.1", "@types/node": "^26.1.1",
"@types/topojson-client": "^3.1.5", "@types/topojson-client": "^3.1.5",
"parse5": "^8.0.0",
"subset-font": "^2.5.0",
"tsx": "^4.23.1" "tsx": "^4.23.1"
} }
} }
Loaded 3 of 7 files, more files were not shown because too many files have changed in this diff. Show more