update at 2026-02-09 16:09:44

This commit is contained in:
douboer
2026-02-09 16:09:44 +08:00
parent ffb7367d3a
commit 917f210dae
20 changed files with 790 additions and 184 deletions

View File

@@ -36,7 +36,14 @@ function run() {
const wrapped = wrapTextByChars('123456', 2)
assert(wrapped === '12\n34\n56', 'wrapTextByChars 结果不符合预期')
const fontFile = findFirstFontFile(path.join(__dirname, '..', 'frontend', 'public', 'fonts'))
const fontRootCandidates = [
path.join(__dirname, '..', 'fonts'),
path.join(__dirname, '..', 'frontend', 'public', 'fonts'),
]
const fontRoot = fontRootCandidates.find((dir) => fs.existsSync(dir))
assert(fontRoot, '未找到字体目录fonts 或 frontend/public/fonts')
const fontFile = findFirstFontFile(fontRoot)
assert(fontFile, '未找到可用字体文件')
const buffer = fs.readFileSync(fontFile)

View File

@@ -8,8 +8,12 @@ set -e # 遇到错误立即退出
# ===== 配置区域 =====
SERVER="user@fonts.biboer.cn" # 请替换为你的 SSH 用户名
REMOTE_DIR="/home/gavin/font2svg"
LOCAL_FONTS_DIR="frontend/public/fonts"
LOCAL_FONTS_JSON="frontend/public/fonts.json"
REMOTE_MP_ASSETS_DIR="$REMOTE_DIR/miniprogram/assets"
LOCAL_FONTS_DIR="fonts"
LOCAL_WEB_FONTS_JSON="frontend/public/fonts.json"
LOCAL_WEB_DEFAULT_JSON="frontend/public/default.json"
LOCAL_MP_FONTS_JSON="miniprogram/assets/fonts.json"
LOCAL_MP_DEFAULT_JSON="miniprogram/assets/default.json"
# 颜色输出
RED='\033[0;31m'
@@ -38,8 +42,13 @@ check_files() {
exit 1
fi
if [ ! -f "$LOCAL_FONTS_JSON" ]; then
log_error "fonts.json 文件不存在: $LOCAL_FONTS_JSON"
if [ ! -f "$LOCAL_WEB_FONTS_JSON" ]; then
log_error "Web fonts.json 文件不存在: $LOCAL_WEB_FONTS_JSON"
exit 1
fi
if [ ! -f "$LOCAL_MP_FONTS_JSON" ]; then
log_error "小程序 fonts.json 文件不存在: $LOCAL_MP_FONTS_JSON"
exit 1
fi
@@ -49,7 +58,7 @@ check_files() {
create_remote_dirs() {
log_info "创建远程目录..."
ssh $SERVER "mkdir -p $REMOTE_DIR/fonts"
ssh $SERVER "mkdir -p $REMOTE_DIR/fonts $REMOTE_MP_ASSETS_DIR"
}
upload_fonts() {
@@ -65,34 +74,55 @@ upload_fonts() {
log_info "字体文件上传完成"
}
upload_fonts_json() {
log_info "上传 fonts.json..."
scp "$LOCAL_FONTS_JSON" "$SERVER:$REMOTE_DIR/"
log_info "fonts.json 上传完成"
upload_web_config() {
log_info "上传 Web 配置..."
scp "$LOCAL_WEB_FONTS_JSON" "$SERVER:$REMOTE_DIR/fonts.json"
if [ -f "$LOCAL_WEB_DEFAULT_JSON" ]; then
scp "$LOCAL_WEB_DEFAULT_JSON" "$SERVER:$REMOTE_DIR/default.json"
fi
log_info "Web 配置上传完成"
}
upload_miniprogram_config() {
log_info "上传小程序配置..."
scp "$LOCAL_MP_FONTS_JSON" "$SERVER:$REMOTE_MP_ASSETS_DIR/fonts.json"
if [ -f "$LOCAL_MP_DEFAULT_JSON" ]; then
scp "$LOCAL_MP_DEFAULT_JSON" "$SERVER:$REMOTE_MP_ASSETS_DIR/default.json"
else
log_warn "未找到小程序 default.json已跳过: $LOCAL_MP_DEFAULT_JSON"
fi
log_info "小程序配置上传完成"
}
set_permissions() {
log_info "设置文件权限..."
ssh $SERVER "chmod -R 755 $REMOTE_DIR"
ssh $SERVER "chmod -R 755 $REMOTE_DIR/fonts $REMOTE_MP_ASSETS_DIR"
log_info "权限设置完成"
}
verify_deployment() {
log_info "验证部署结果..."
# 检查 fonts.json
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "https://fonts.biboer.cn/fonts.json")
# 检查小程序 fonts.json
MP_HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "https://fonts.biboer.cn/miniprogram/assets/fonts.json")
if [ "$HTTP_CODE" = "200" ]; then
log_info "fonts.json 可访问 ✓"
if [ "$MP_HTTP_CODE" = "200" ]; then
log_info "小程序 fonts.json 可访问 ✓"
else
log_error "fonts.json 访问失败 (HTTP $HTTP_CODE)"
log_error "小程序 fonts.json 访问失败 (HTTP $MP_HTTP_CODE)"
log_warn "请检查 Cloudflare DNS 配置和 Nginx 配置"
exit 1
fi
WEB_HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "https://fonts.biboer.cn/fonts.json")
if [ "$WEB_HTTP_CODE" = "200" ]; then
log_info "Web fonts.json 可访问 ✓"
else
log_warn "Web fonts.json 不可访问 (HTTP $WEB_HTTP_CODE)"
fi
# 检查 CORS 头
CORS_HEADER=$(curl -s -I "https://fonts.biboer.cn/fonts.json" | grep -i "access-control-allow-origin")
CORS_HEADER=$(curl -s -I "https://fonts.biboer.cn/miniprogram/assets/fonts.json" | grep -i "access-control-allow-origin")
if [ -n "$CORS_HEADER" ]; then
log_info "CORS 配置正确 ✓"
@@ -123,11 +153,12 @@ show_summary() {
echo ""
echo "2. 测试字体加载(在小程序开发者工具控制台):"
echo " wx.request({"
echo " url: 'https://fonts.biboer.cn/fonts.json',"
echo " url: 'https://fonts.biboer.cn/miniprogram/assets/fonts.json',"
echo " success: (res) => console.log(res.data)"
echo " })"
echo ""
echo "3. 验证 CDN 缓存状态:"
echo " curl -I https://fonts.biboer.cn/miniprogram/assets/fonts.json | grep cf-cache-status"
echo " curl -I https://fonts.biboer.cn/fonts.json | grep cf-cache-status"
echo ""
}
@@ -151,7 +182,8 @@ main() {
check_files
create_remote_dirs
upload_fonts
upload_fonts_json
upload_web_config
upload_miniprogram_config
set_permissions
# 可选:重启 Nginx需要 sudo 权限)

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python3
"""
生成字体清单文件
扫描 frontend/public/fonts/ 目录下的所有字体文件,同时生成:
扫描 fonts/ 目录下的所有字体文件,同时生成:
1. frontend/public/fonts.json
2. miniprogram/assets/fonts.json
3. miniprogram/assets/fonts.js
@@ -11,7 +11,7 @@ import os
import json
from pathlib import Path
def scan_fonts(font_dir='frontend/public/fonts'):
def scan_fonts(font_dir='fonts'):
"""扫描字体目录,返回字体信息列表"""
fonts = []
font_dir_path = Path(font_dir)
@@ -34,19 +34,43 @@ def scan_fonts(font_dir='frontend/public/fonts'):
relative_path = font_file.relative_to(font_dir_path).as_posix()
# 生成字体信息
# 生成基础信息id 在后续统一按序号回填
font_info = {
'id': f"{category_name}/{font_file.stem}",
'id': '',
'name': font_file.stem,
'filename': font_file.name,
'category': category_name,
'path': f"/fonts/{relative_path}",
'relativePath': relative_path,
}
fonts.append(font_info)
# 统一排序后分配 4 位数字 id0001、0002...
fonts = sorted(fonts, key=lambda x: (x['category'], x['name'], x['filename']))
for index, font in enumerate(fonts, start=1):
font['id'] = f"{index:04d}"
return fonts
def build_manifest(fonts, path_prefix):
"""根据路径前缀构建对外清单"""
prefix = f"/{str(path_prefix or '').strip('/')}"
if prefix == '/':
prefix = ''
manifest = []
for font in fonts:
manifest.append({
'id': font['id'],
'name': font['name'],
'filename': font['filename'],
'category': font['category'],
'path': f"{prefix}/{font['relativePath']}",
})
return manifest
def write_fonts_json(fonts, output_file):
"""写入字体清单 JSON 文件"""
os.makedirs(os.path.dirname(output_file), exist_ok=True)
@@ -66,15 +90,19 @@ def write_fonts_js(fonts, output_file):
def main():
"""主函数"""
# 扫描字体(唯一来源:frontend/public/fonts
fonts = scan_fonts('frontend/public/fonts')
# 扫描字体(唯一来源:仓库根目录 fonts/
fonts = scan_fonts('fonts')
print(f"找到 {len(fonts)} 个字体文件")
# 同步写入 Web 与小程序清单
write_fonts_json(fonts, 'frontend/public/fonts.json')
write_fonts_json(fonts, 'miniprogram/assets/fonts.json')
write_fonts_js(fonts, 'miniprogram/assets/fonts.js')
# Web 清单:统一指向根目录 fonts
web_fonts = build_manifest(fonts, '/fonts')
write_fonts_json(web_fonts, 'frontend/public/fonts.json')
# 小程序清单:同样指向根目录 fonts与 web 共用一份字体目录)
miniprogram_fonts = build_manifest(fonts, '/fonts')
write_fonts_json(miniprogram_fonts, 'miniprogram/assets/fonts.json')
write_fonts_js(miniprogram_fonts, 'miniprogram/assets/fonts.js')
# 统计信息
categories = {}

View File

@@ -3,7 +3,7 @@
"""
Font2SVG - fonts.json 生成脚本
扫描 frontend/public/fonts/ 目录,生成小程序所需的 fonts.json
扫描 fonts/ 目录,生成字体清单
URL 格式https://fonts.biboer.cn/fonts/{category}/{fontname}.ttf
"""
@@ -14,7 +14,7 @@ from urllib.parse import quote
# 配置
BASE_URL = "https://fonts.biboer.cn/fonts"
FONTS_DIR = Path(__file__).parent.parent / "frontend" / "public" / "fonts"
FONTS_DIR = Path(__file__).parent.parent / "fonts"
OUTPUT_FILE = Path(__file__).parent.parent / "frontend" / "public" / "fonts.json"
def scan_fonts(fonts_dir: Path) -> list:
@@ -51,9 +51,9 @@ def scan_fonts(fonts_dir: Path) -> list:
encoded_filename = quote(font_file.name)
url = f"{BASE_URL}/{encoded_category}/{encoded_filename}"
# 创建字体信息对象
# 创建字体信息对象id 在后续统一按序号回填)
font_info = {
"id": f"{category}/{font_name}",
"id": "",
"name": font_name,
"category": category,
"path": url,
@@ -71,7 +71,10 @@ def sort_fonts(fonts: list) -> list:
1. 按分类排序
2. 同分类内按名称排序
"""
return sorted(fonts, key=lambda x: (x["category"], x["name"]))
sorted_fonts = sorted(fonts, key=lambda x: (x["category"], x["name"]))
for index, font in enumerate(sorted_fonts, start=1):
font["id"] = f"{index:04d}"
return sorted_fonts
def save_fonts_json(fonts: list, output_file: Path):
"""