update at 2026-02-08 18:28:39
This commit is contained in:
60
scripts/check-miniprogram-core-test.js
Executable file
60
scripts/check-miniprogram-core-test.js
Executable file
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
const { wrapTextByChars } = require('../miniprogram/utils/core/text-layout')
|
||||
const { generateSvgFromFont } = require('../miniprogram/utils/core/svg-builder')
|
||||
const opentype = require('../frontend/node_modules/opentype.js/dist/opentype.js')
|
||||
|
||||
function findFirstFontFile(rootDir) {
|
||||
const entries = fs.readdirSync(rootDir, { withFileTypes: true })
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(rootDir, entry.name)
|
||||
if (entry.isDirectory()) {
|
||||
const nested = findFirstFontFile(fullPath)
|
||||
if (nested) return nested
|
||||
continue
|
||||
}
|
||||
|
||||
if (/\.(ttf|otf)$/i.test(entry.name)) {
|
||||
return fullPath
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function assert(condition, message) {
|
||||
if (!condition) {
|
||||
throw new Error(message)
|
||||
}
|
||||
}
|
||||
|
||||
function run() {
|
||||
console.log('开始执行小程序核心模块测试...')
|
||||
|
||||
const wrapped = wrapTextByChars('123456', 2)
|
||||
assert(wrapped === '12\n34\n56', 'wrapTextByChars 结果不符合预期')
|
||||
|
||||
const fontFile = findFirstFontFile(path.join(__dirname, '..', 'frontend', 'public', 'fonts'))
|
||||
assert(fontFile, '未找到可用字体文件')
|
||||
|
||||
const buffer = fs.readFileSync(fontFile)
|
||||
const font = opentype.parse(buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength))
|
||||
|
||||
const result = generateSvgFromFont({
|
||||
text: '星程字体转换',
|
||||
font,
|
||||
fontSize: 120,
|
||||
fillColor: '#000000',
|
||||
letterSpacing: 0,
|
||||
})
|
||||
|
||||
assert(typeof result.svg === 'string' && result.svg.includes('<svg'), 'SVG 内容无效')
|
||||
assert(result.svg.includes('<path'), 'SVG 未生成路径')
|
||||
assert(result.width > 0 && result.height > 0, 'SVG 尺寸计算无效')
|
||||
|
||||
console.log('小程序核心模块测试通过。')
|
||||
}
|
||||
|
||||
run()
|
||||
65
scripts/check-miniprogram-lint.js
Executable file
65
scripts/check-miniprogram-lint.js
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
const ROOT = path.join(__dirname, '..', 'miniprogram')
|
||||
const TARGET_EXTENSIONS = new Set(['.js', '.json', '.wxml', '.wxss'])
|
||||
|
||||
function walk(dir, files = []) {
|
||||
const entries = fs.readdirSync(dir, { withFileTypes: true })
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(dir, entry.name)
|
||||
if (fullPath.includes(`${path.sep}workers${path.sep}svg-generator${path.sep}vendor${path.sep}`)) {
|
||||
continue
|
||||
}
|
||||
if (fullPath.includes(`${path.sep}i18n${path.sep}`)) {
|
||||
continue
|
||||
}
|
||||
if (fullPath.endsWith('.miniapp.json')) {
|
||||
continue
|
||||
}
|
||||
if (entry.isDirectory()) {
|
||||
walk(fullPath, files)
|
||||
continue
|
||||
}
|
||||
const ext = path.extname(entry.name)
|
||||
if (TARGET_EXTENSIONS.has(ext)) {
|
||||
files.push(fullPath)
|
||||
}
|
||||
}
|
||||
return files
|
||||
}
|
||||
|
||||
function main() {
|
||||
console.log('开始执行小程序代码规范检查...')
|
||||
|
||||
const files = walk(ROOT)
|
||||
const violations = []
|
||||
|
||||
for (const file of files) {
|
||||
const content = fs.readFileSync(file, 'utf8')
|
||||
const lines = content.split(/\r?\n/)
|
||||
for (let i = 0; i < lines.length; i += 1) {
|
||||
const line = lines[i]
|
||||
if (/\t/.test(line)) {
|
||||
violations.push(`${file}:${i + 1} 使用了 Tab 缩进`)
|
||||
}
|
||||
if (/\s+$/.test(line)) {
|
||||
violations.push(`${file}:${i + 1} 存在行尾空格`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (violations.length > 0) {
|
||||
console.error('发现代码规范问题:')
|
||||
for (const violation of violations) {
|
||||
console.error(`- ${violation}`)
|
||||
}
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log('小程序代码规范检查通过。')
|
||||
}
|
||||
|
||||
main()
|
||||
112
scripts/deploy-assets.sh
Executable file
112
scripts/deploy-assets.sh
Executable file
@@ -0,0 +1,112 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Font2SVG 静态资源部署脚本
|
||||
# 用于将图标和 logo 上传到 fonts.biboer.cn 服务器
|
||||
|
||||
set -e # 遇到错误立即退出
|
||||
|
||||
# ===== 配置区域 =====
|
||||
SERVER="gavin@fonts.biboer.cn"
|
||||
REMOTE_DIR="/home/gavin/font2svg"
|
||||
LOCAL_ASSETS_DIR="assets"
|
||||
|
||||
# 颜色输出
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
# ===== 函数定义 =====
|
||||
log_info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
check_files() {
|
||||
log_info "检查本地文件..."
|
||||
|
||||
if [ ! -d "$LOCAL_ASSETS_DIR/icons" ]; then
|
||||
log_error "图标目录不存在: $LOCAL_ASSETS_DIR/icons"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SVG_COUNT=$(find "$LOCAL_ASSETS_DIR/icons" -name "*.svg" | wc -l | tr -d ' ')
|
||||
PNG_COUNT=$(find "$LOCAL_ASSETS_DIR/icons" -name "*.png" | wc -l | tr -d ' ')
|
||||
log_info "发现 $SVG_COUNT 个 SVG 图标, $PNG_COUNT 个 PNG 图标"
|
||||
}
|
||||
|
||||
create_remote_dirs() {
|
||||
log_info "创建远程目录..."
|
||||
ssh $SERVER "mkdir -p $REMOTE_DIR/assets/icons"
|
||||
}
|
||||
|
||||
upload_assets() {
|
||||
log_info "上传静态资源到 $SERVER..."
|
||||
|
||||
# 上传图标(SVG 和 PNG)
|
||||
rsync -avz --progress \
|
||||
--include="*.svg" \
|
||||
--include="*.png" \
|
||||
--include="*/" \
|
||||
--exclude="*" \
|
||||
"$LOCAL_ASSETS_DIR/" "$SERVER:$REMOTE_DIR/assets/"
|
||||
|
||||
log_info "静态资源上传完成"
|
||||
}
|
||||
|
||||
set_permissions() {
|
||||
log_info "设置文件权限..."
|
||||
ssh $SERVER "chmod -R 755 $REMOTE_DIR/assets"
|
||||
log_info "权限设置完成"
|
||||
}
|
||||
|
||||
verify_deployment() {
|
||||
log_info "验证部署..."
|
||||
|
||||
# 检查目录是否存在
|
||||
if ssh $SERVER "[ -d $REMOTE_DIR/assets/icons ]"; then
|
||||
log_info "✓ assets/icons 目录存在"
|
||||
else
|
||||
log_error "✗ assets/icons 目录不存在"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 统计远程文件数量
|
||||
REMOTE_SVG_COUNT=$(ssh $SERVER "find $REMOTE_DIR/assets/icons -name '*.svg' | wc -l" | tr -d ' ')
|
||||
REMOTE_PNG_COUNT=$(ssh $SERVER "find $REMOTE_DIR/assets/icons -name '*.png' | wc -l" | tr -d ' ')
|
||||
log_info "远程服务器上有 $REMOTE_SVG_COUNT 个 SVG, $REMOTE_PNG_COUNT 个 PNG"
|
||||
}
|
||||
|
||||
show_urls() {
|
||||
log_info "=========================================="
|
||||
log_info "部署完成!资源 URL 示例:"
|
||||
log_info " Logo: https://fonts.biboer.cn/assets/webicon.png"
|
||||
log_info " 图标: https://fonts.biboer.cn/assets/icons/[图标名].svg"
|
||||
log_info "=========================================="
|
||||
}
|
||||
|
||||
# ===== 主流程 =====
|
||||
main() {
|
||||
log_info "开始部署 Font2SVG 静态资源..."
|
||||
echo ""
|
||||
|
||||
check_files
|
||||
create_remote_dirs
|
||||
upload_assets
|
||||
set_permissions
|
||||
verify_deployment
|
||||
|
||||
echo ""
|
||||
show_urls
|
||||
log_info "部署完成!"
|
||||
}
|
||||
|
||||
# 运行主流程
|
||||
main
|
||||
170
scripts/deploy-fonts.sh
Executable file
170
scripts/deploy-fonts.sh
Executable file
@@ -0,0 +1,170 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Font2SVG 字体资源部署脚本
|
||||
# 用于将字体文件上传到 fonts.biboer.cn 服务器
|
||||
|
||||
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"
|
||||
|
||||
# 颜色输出
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# ===== 函数定义 =====
|
||||
log_info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
check_files() {
|
||||
log_info "检查本地文件..."
|
||||
|
||||
if [ ! -d "$LOCAL_FONTS_DIR" ]; then
|
||||
log_error "字体目录不存在: $LOCAL_FONTS_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$LOCAL_FONTS_JSON" ]; then
|
||||
log_error "fonts.json 文件不存在: $LOCAL_FONTS_JSON"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
FONT_COUNT=$(find "$LOCAL_FONTS_DIR" -name "*.ttf" -o -name "*.otf" | wc -l)
|
||||
log_info "发现 $FONT_COUNT 个字体文件"
|
||||
}
|
||||
|
||||
create_remote_dirs() {
|
||||
log_info "创建远程目录..."
|
||||
ssh $SERVER "mkdir -p $REMOTE_DIR/fonts"
|
||||
}
|
||||
|
||||
upload_fonts() {
|
||||
log_info "上传字体文件到 $SERVER..."
|
||||
log_warn "这可能需要几分钟,取决于字体文件大小..."
|
||||
|
||||
# 使用 rsync 进行增量上传(只上传修改过的文件)
|
||||
rsync -avz --progress \
|
||||
--exclude=".DS_Store" \
|
||||
--exclude="Thumbs.db" \
|
||||
"$LOCAL_FONTS_DIR/" "$SERVER:$REMOTE_DIR/fonts/"
|
||||
|
||||
log_info "字体文件上传完成"
|
||||
}
|
||||
|
||||
upload_fonts_json() {
|
||||
log_info "上传 fonts.json..."
|
||||
scp "$LOCAL_FONTS_JSON" "$SERVER:$REMOTE_DIR/"
|
||||
log_info "fonts.json 上传完成"
|
||||
}
|
||||
|
||||
set_permissions() {
|
||||
log_info "设置文件权限..."
|
||||
ssh $SERVER "chmod -R 755 $REMOTE_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")
|
||||
|
||||
if [ "$HTTP_CODE" = "200" ]; then
|
||||
log_info "fonts.json 可访问 ✓"
|
||||
else
|
||||
log_error "fonts.json 访问失败 (HTTP $HTTP_CODE)"
|
||||
log_warn "请检查 Cloudflare DNS 配置和 Nginx 配置"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查 CORS 头
|
||||
CORS_HEADER=$(curl -s -I "https://fonts.biboer.cn/fonts.json" | grep -i "access-control-allow-origin")
|
||||
|
||||
if [ -n "$CORS_HEADER" ]; then
|
||||
log_info "CORS 配置正确 ✓"
|
||||
else
|
||||
log_warn "未检测到 CORS 头,请检查 Nginx 配置"
|
||||
fi
|
||||
}
|
||||
|
||||
restart_nginx() {
|
||||
log_info "重启 Nginx..."
|
||||
ssh $SERVER "sudo systemctl restart nginx" || {
|
||||
log_warn "Nginx 重启失败,可能需要手动执行"
|
||||
return 1
|
||||
}
|
||||
log_info "Nginx 重启成功"
|
||||
}
|
||||
|
||||
show_summary() {
|
||||
echo ""
|
||||
echo "======================================="
|
||||
log_info "部署完成!"
|
||||
echo "======================================="
|
||||
echo ""
|
||||
echo "下一步操作:"
|
||||
echo "1. 在小程序后台配置域名:"
|
||||
echo " https://mp.weixin.qq.com/ → 开发 → 服务器域名"
|
||||
echo " 添加 downloadFile 合法域名: https://fonts.biboer.cn"
|
||||
echo ""
|
||||
echo "2. 测试字体加载(在小程序开发者工具控制台):"
|
||||
echo " wx.request({"
|
||||
echo " url: 'https://fonts.biboer.cn/fonts.json',"
|
||||
echo " success: (res) => console.log(res.data)"
|
||||
echo " })"
|
||||
echo ""
|
||||
echo "3. 验证 CDN 缓存状态:"
|
||||
echo " curl -I https://fonts.biboer.cn/fonts.json | grep cf-cache-status"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# ===== 主流程 =====
|
||||
main() {
|
||||
echo ""
|
||||
echo "========================================="
|
||||
echo " Font2SVG 字体资源部署脚本"
|
||||
echo " 目标服务器: fonts.biboer.cn"
|
||||
echo "========================================="
|
||||
echo ""
|
||||
|
||||
# 检查是否在项目根目录
|
||||
if [ ! -f "package.json" ]; then
|
||||
log_error "请在项目根目录执行此脚本"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 执行部署步骤
|
||||
check_files
|
||||
create_remote_dirs
|
||||
upload_fonts
|
||||
upload_fonts_json
|
||||
set_permissions
|
||||
|
||||
# 可选:重启 Nginx(需要 sudo 权限)
|
||||
read -p "是否重启 Nginx?(y/N) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
restart_nginx
|
||||
fi
|
||||
|
||||
# 验证部署
|
||||
verify_deployment
|
||||
show_summary
|
||||
}
|
||||
|
||||
# 执行主函数
|
||||
main "$@"
|
||||
56
scripts/deploy-icons.sh
Normal file
56
scripts/deploy-icons.sh
Normal file
@@ -0,0 +1,56 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 部署图标到 CDN (fonts.biboer.cn)
|
||||
# 使用方法: ./deploy-icons.sh
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ICONS_DIR="$SCRIPT_DIR/frontend/src/assets/icons"
|
||||
REMOTE_USER="root"
|
||||
REMOTE_HOST="fonts.biboer.cn"
|
||||
REMOTE_PATH="/var/www/fonts"
|
||||
ICONS_REMOTE_PATH="$REMOTE_PATH/icons"
|
||||
|
||||
echo "🚀 开始部署图标到 CDN..."
|
||||
echo "源目录: $ICONS_DIR"
|
||||
echo "目标: $REMOTE_HOST:$ICONS_REMOTE_PATH"
|
||||
echo ""
|
||||
|
||||
# 检查源目录
|
||||
if [ ! -d "$ICONS_DIR" ]; then
|
||||
echo "❌ 错误: 图标目录不存在 $ICONS_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 统计文件数量
|
||||
ICON_COUNT=$(find "$ICONS_DIR" -type f \( -name "*.svg" -o -name "*.png" \) | wc -l)
|
||||
echo "📦 找到 $ICON_COUNT 个图标文件"
|
||||
echo ""
|
||||
|
||||
# 创建远程目录
|
||||
echo "📁 创建远程目录..."
|
||||
ssh "$REMOTE_USER@$REMOTE_HOST" "mkdir -p $ICONS_REMOTE_PATH"
|
||||
|
||||
# 上传图标文件(SVG 和 PNG)
|
||||
echo "📤 上传图标文件..."
|
||||
rsync -avz --progress \
|
||||
--include="*.svg" \
|
||||
--include="*.png" \
|
||||
--exclude="*" \
|
||||
"$ICONS_DIR/" \
|
||||
"$REMOTE_USER@$REMOTE_HOST:$ICONS_REMOTE_PATH/"
|
||||
|
||||
# 设置权限
|
||||
echo "🔐 设置文件权限..."
|
||||
ssh "$REMOTE_USER@$REMOTE_HOST" "chmod -R 644 $ICONS_REMOTE_PATH/*"
|
||||
|
||||
echo ""
|
||||
echo "✅ 部署完成!"
|
||||
echo ""
|
||||
echo "📝 图标访问地址示例:"
|
||||
echo " https://fonts.biboer.cn/icons/webicon.png"
|
||||
echo " https://fonts.biboer.cn/icons/font-icon.svg"
|
||||
echo ""
|
||||
echo "🔗 测试访问:"
|
||||
curl -I "https://fonts.biboer.cn/icons/webicon.png" 2>/dev/null | head -n 1 || echo "⚠️ 无法访问,请检查服务器配置"
|
||||
@@ -1,7 +1,10 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
生成字体清单 JSON 文件
|
||||
扫描 frontend/public/fonts/ 目录下的所有字体文件,生成 frontend/public/fonts.json
|
||||
生成字体清单文件
|
||||
扫描 frontend/public/fonts/ 目录下的所有字体文件,同时生成:
|
||||
1. frontend/public/fonts.json
|
||||
2. miniprogram/assets/fonts.json
|
||||
3. miniprogram/assets/fonts.js
|
||||
"""
|
||||
|
||||
import os
|
||||
@@ -44,6 +47,23 @@ def scan_fonts(font_dir='frontend/public/fonts'):
|
||||
|
||||
return fonts
|
||||
|
||||
def write_fonts_json(fonts, output_file):
|
||||
"""写入字体清单 JSON 文件"""
|
||||
os.makedirs(os.path.dirname(output_file), exist_ok=True)
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(fonts, f, ensure_ascii=False, indent=2)
|
||||
print(f"字体清单已保存到: {output_file}")
|
||||
|
||||
|
||||
def write_fonts_js(fonts, output_file):
|
||||
"""写入小程序可 require 的 JS 清单文件"""
|
||||
os.makedirs(os.path.dirname(output_file), exist_ok=True)
|
||||
content = "module.exports = " + json.dumps(fonts, ensure_ascii=False, indent=2) + "\n"
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
print(f"字体清单已保存到: {output_file}")
|
||||
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
# 扫描字体(唯一来源:frontend/public/fonts)
|
||||
@@ -51,14 +71,10 @@ def main():
|
||||
|
||||
print(f"找到 {len(fonts)} 个字体文件")
|
||||
|
||||
# 保存到 JSON 文件
|
||||
output_file = 'frontend/public/fonts.json'
|
||||
os.makedirs(os.path.dirname(output_file), exist_ok=True)
|
||||
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(fonts, f, ensure_ascii=False, indent=2)
|
||||
|
||||
print(f"字体清单已保存到: {output_file}")
|
||||
# 同步写入 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')
|
||||
|
||||
# 统计信息
|
||||
categories = {}
|
||||
|
||||
160
scripts/generate-fonts-json.py
Executable file
160
scripts/generate-fonts-json.py
Executable file
@@ -0,0 +1,160 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Font2SVG - fonts.json 生成脚本
|
||||
扫描 frontend/public/fonts/ 目录,生成小程序所需的 fonts.json
|
||||
URL 格式:https://fonts.biboer.cn/fonts/{category}/{fontname}.ttf
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
from pathlib import Path
|
||||
from urllib.parse import quote
|
||||
|
||||
# 配置
|
||||
BASE_URL = "https://fonts.biboer.cn/fonts"
|
||||
FONTS_DIR = Path(__file__).parent.parent / "frontend" / "public" / "fonts"
|
||||
OUTPUT_FILE = Path(__file__).parent.parent / "frontend" / "public" / "fonts.json"
|
||||
|
||||
def scan_fonts(fonts_dir: Path) -> list:
|
||||
"""
|
||||
扫描字体目录,生成字体列表
|
||||
|
||||
Args:
|
||||
fonts_dir: 字体根目录
|
||||
|
||||
Returns:
|
||||
字体信息列表
|
||||
"""
|
||||
fonts = []
|
||||
|
||||
# 遍历所有分类目录
|
||||
for category_dir in fonts_dir.iterdir():
|
||||
if not category_dir.is_dir():
|
||||
continue
|
||||
|
||||
category = category_dir.name
|
||||
|
||||
# 跳过隐藏目录
|
||||
if category.startswith('.'):
|
||||
continue
|
||||
|
||||
# 遍历分类下的所有字体文件
|
||||
for font_file in category_dir.glob("*.ttf"):
|
||||
# 获取文件信息
|
||||
font_name = font_file.stem # 不含扩展名的文件名
|
||||
file_size = font_file.stat().st_size
|
||||
|
||||
# 构建 URL(需要编码中文路径)
|
||||
encoded_category = quote(category)
|
||||
encoded_filename = quote(font_file.name)
|
||||
url = f"{BASE_URL}/{encoded_category}/{encoded_filename}"
|
||||
|
||||
# 创建字体信息对象
|
||||
font_info = {
|
||||
"id": f"{category}/{font_name}",
|
||||
"name": font_name,
|
||||
"category": category,
|
||||
"path": url,
|
||||
"size": file_size
|
||||
}
|
||||
|
||||
fonts.append(font_info)
|
||||
print(f"✓ {category}/{font_name} ({file_size} bytes)")
|
||||
|
||||
return fonts
|
||||
|
||||
def sort_fonts(fonts: list) -> list:
|
||||
"""
|
||||
对字体列表排序
|
||||
1. 按分类排序
|
||||
2. 同分类内按名称排序
|
||||
"""
|
||||
return sorted(fonts, key=lambda x: (x["category"], x["name"]))
|
||||
|
||||
def save_fonts_json(fonts: list, output_file: Path):
|
||||
"""
|
||||
保存 fonts.json
|
||||
"""
|
||||
# 确保输出目录存在
|
||||
output_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# 写入 JSON
|
||||
with output_file.open("w", encoding="utf-8") as f:
|
||||
json.dump(fonts, f, ensure_ascii=False, indent=2)
|
||||
|
||||
print(f"\n✓ fonts.json 已保存到: {output_file}")
|
||||
print(f"✓ 共 {len(fonts)} 个字体")
|
||||
|
||||
def print_summary(fonts: list):
|
||||
"""
|
||||
打印统计信息
|
||||
"""
|
||||
# 按分类统计
|
||||
categories = {}
|
||||
total_size = 0
|
||||
|
||||
for font in fonts:
|
||||
category = font["category"]
|
||||
size = font["size"]
|
||||
|
||||
if category not in categories:
|
||||
categories[category] = {"count": 0, "size": 0}
|
||||
|
||||
categories[category]["count"] += 1
|
||||
categories[category]["size"] += size
|
||||
total_size += size
|
||||
|
||||
print("\n" + "="*50)
|
||||
print("字体统计信息")
|
||||
print("="*50)
|
||||
|
||||
for category, stats in sorted(categories.items()):
|
||||
size_mb = stats["size"] / 1024 / 1024
|
||||
print(f"{category:20s} {stats['count']:3d} 个字体 {size_mb:8.2f} MB")
|
||||
|
||||
print("-"*50)
|
||||
total_mb = total_size / 1024 / 1024
|
||||
print(f"{'总计':20s} {len(fonts):3d} 个字体 {total_mb:8.2f} MB")
|
||||
print("="*50)
|
||||
|
||||
def main():
|
||||
print("="*50)
|
||||
print("Font2SVG - fonts.json 生成工具")
|
||||
print("目标域名: fonts.biboer.cn")
|
||||
print("="*50)
|
||||
print()
|
||||
|
||||
# 检查字体目录是否存在
|
||||
if not FONTS_DIR.exists():
|
||||
print(f"❌ 错误:字体目录不存在: {FONTS_DIR}")
|
||||
return
|
||||
|
||||
print(f"扫描目录: {FONTS_DIR}")
|
||||
print()
|
||||
|
||||
# 扫描字体
|
||||
fonts = scan_fonts(FONTS_DIR)
|
||||
|
||||
if not fonts:
|
||||
print("❌ 未找到任何字体文件")
|
||||
return
|
||||
|
||||
# 排序
|
||||
fonts = sort_fonts(fonts)
|
||||
|
||||
# 保存
|
||||
save_fonts_json(fonts, OUTPUT_FILE)
|
||||
|
||||
# 统计信息
|
||||
print_summary(fonts)
|
||||
|
||||
print()
|
||||
print("下一步操作:")
|
||||
print("1. 检查生成的 fonts.json 内容")
|
||||
print("2. 运行部署脚本: bash scripts/deploy-fonts.sh")
|
||||
print("3. 验证访问: curl https://fonts.biboer.cn/fonts.json")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user