47 Commits

Author SHA1 Message Date
崮生(子虚)
d16aa46227 feat: 离线裁剪统计 + 企业服务板块 + SDK文档独立页(/docs) + 示例改用observeFont 2026-08-06 08:57:48 +08:00
崮生(子虚)
09f434bbcf feat: 离线裁剪页面 + 增量预览 + DEV预览页 + tempUploads统计 + SDK缓存破坏 + UI优化
- 新增离线裁剪页面 /offline-subset(纯浏览器端字体裁剪)
- SDK subsetProvider 抽象,离线页面注入本地裁剪 provider
- 预览用增量裁剪(SDK自动去重),下载用全量裁剪
- 拖放区域支持点击和拖拽选择字体文件
- 新增 DEV 预览页 /__dev(仅 dev 模式路由可达)
- FontDebugPreview 从首页提取为独立页面
- tempUploads 统计字段(全链路+持久化)
- webfont-sdk.js 构建时戳缓存破坏
- 首页导航栏新增离线裁剪入口
- UploadSection 离线裁剪入口合并到游客上传卡片
- SDK 文档代码示例补充 HTML 用法
- 导航栏窄屏换行适配
2026-08-03 15:18:01 +08:00
崮生(子虚)
5a7c6a9913 fix: LLRT readdir 不兼容 withFileTypes 导致临时字体清理失效
根因:LLRT 的 fs.readdir 返回字符串数组而非 Dirent 对象,
entry.isFile() 抛 TypeError 被 catch 静默吞掉,
导致 evictIfNeeded 和 temp_cleaner 从未执行(线上堆积 108 个文件 992M)。

修复:
- node.ts: readdir 改为先拿文件名再 stat 判断
- temp_cleaner.ts: catch 块加日志不再静默吞错误

同时包含:
- font-config.json homepage 链接修复(删除 3 个 404,修正 2 个)
- FontDetail 字符预览改为可实时编辑
- 添加 scripts/bench.mjs 压测脚本
2026-08-01 08:03:33 +08:00
崮生(子虚)
98c3c5a6e2 fix: 路由切换后滚动到顶部
详情页→列表→另一个详情页时滚动位置保留在前一页的偏移,
用 router.afterEach 统一处理,每次导航回到顶部。
2026-07-31 00:06:05 +08:00
崮生(子虚)
3e3e8899d5 fix: 修复字体详情页字体未应用——@font-face 替代 link stylesheet
根因:API 返回二进制 woff2 字体文件,但前端用 <link rel="stylesheet">
引用它,浏览器无法将 woff2 二进制作为 CSS 解析,导致字体完全未加载。

修复:
- 用 watchEffect + document.createElement('style') 动态注入 @font-face
  声明,通过 src: url(...) 引用 API 返回的 woff2 二进制
- 修正 usageCode 示例代码,展示正确的 @font-face 用法
- 添加 SSG/SSR 守卫(typeof document === 'undefined' 跳过)

验证:document.fonts.check() 返回 true,字体 status 为 loaded
2026-07-31 00:03:33 +08:00
崮生(子虚)
6421e7d059 fix: extractCodePoints 增加 glyph 轮廓验证 + 删除冗余正文预览卡片
- font_meta.ts: extractCodePoints 新增 createGlyphValidator,对 TrueType 字体
  检查 loca 表确认 glyph 有真实轮廓数据(非空),CFF 字体保持原逻辑
- lint 同步去掉 bodyTitle/bodyText(FontDetail 已移除正文预览卡片)
- FontDetail.vue: 删除正文预览区块(与大标题预览功能重叠),移除对应 computed
- allPreviewText 只合并 previewText + charsetPreview
2026-07-30 23:50:27 +08:00
崮生(子虚)
afbd4db77c fix: 字体加载合并所有预览文字(previewText+bodyTitle+bodyText+charsetPreview)
之前 <link> 只加载 previewText 的字符子集,导致 bodyTitle/bodyText/charsetPreview
区域显示 fallback serif 而非实际字体。现在 allPreviewText 合并所有预览文字请求子集。
2026-07-30 23:43:08 +08:00
崮生(子虚)
7638ce7e2d fix: 移除 FontDetail fallback 默认值 + lint 检查缺失字段 + 使用 CodeBlock 组件
- FontDetail.vue: 移除 DEFAULT_PREVIEW 等硬编码 fallback,config 缺字段时不渲染对应区块(避免显示字体不支持的字符)
- lint-font-config.ts: 新增检查 font/ 目录下所有字体是否都在 config 中有完整配置(previewText/bodyTitle/bodyText/charsetPreview 四个必填字段)
- FontDetail.vue: 使用方法代码块从 <pre><code> 改为 CodeBlock 组件(语法高亮)
2026-07-30 23:37:18 +08:00
崮生(子虚)
a095cd0590 feat: 详情页全面接入 font-config + 防闪烁
- font-config.json: 新增 bodyTitle/bodyText/charsetPreview 字段
  为每个字体配置通过 lint 检查的专属文案
- FontDetail.vue: 正文/字符预览使用 config 字段替代写死文案
  大标题/正文/字符预览加 v-if=meta 守卫,消除 hydrate 闪烁
  h1 标题使用 displayName
- lint-font-config.ts: 扩展检查范围至所有文本字段
- FontUserConfig 类型同步更新(后端+前端)
2026-07-30 23:30:40 +08:00
崮生(子虚)
9397e10aad feat: 字体列表/详情页接入 font-config 配置 + lint 脚本
前端:
- FontList.vue: 卡片使用 router-link 跳转;
  展示 displayName/description/previewText/tags;
  底部添加字体投稿联系文案
- FontDetail.vue: 预览文字使用 config.previewText 替代写死文案

工具:
- scripts/lint-font-config.ts: 检查 previewText 字符是否被字体支持
- package.json: 添加 lint:font-config 脚本
2026-07-30 23:23:30 +08:00
崮生(子虚)
23728ba02b refactor: 回退内存闸门为固定并发(保留分组调度) + 前端改进
后端:
- subset_queue.ts: 移除基于内存的门控(LLRT GC 不释放 RSS),
  回退到固定并发模型,保留分组调度优化(相同字体批处理重用缓存)
- config.ts: 恢复 subsetConcurrency / subsetQueueTimeoutSeconds,
  移除 subsetMemSoftLimitMB
- routes/subset.ts, app.ts, routes/config.ts: 同步恢复
- api.ts, README: 同步更新

前端:
- FontSelector.vue: 下拉项和触发器标记临时字体(橙色徽章)
- CodeBlock.vue: 新增轻量代码块组件,内置 CSS/HTML/JS 分词高亮(0依赖)
- Home.vue: 集成 CodeBlock 替换原始 <pre> 代码块
2026-07-30 23:11:54 +08:00
崮生(子虚)
7403414439 feat: 用内存水位闸门替代固定并发限制
- subset_queue: 新增 withMemoryGate,基于 RSS 决定排队/执行
- getRssMB: Node 用 process.memoryUsage(),LLRT 用 /proc/self/statm
- 请求完成后主动 __gc() 加速内存回收
- config: SUBSET_MEM_SOFT_LIMIT_MB=600 替代 SUBSET_CONCURRENCY=4
- 小请求可高并发(内存够),大请求自动排队(防 OOM)
2026-07-30 22:51:37 +08:00
崮生(子虚)
65ba984972 feat: 字体子集化并发队列控制(服务端+客户端)
后端:
- subset_queue.ts: Semaphore 并发控制器,排队超时返回 503
- subset.ts: fontSubset 调用包裹在 withConcurrencyLimit 中
- config.ts: 新增 SUBSET_CONCURRENCY 环境变量(默认 2)
- routes/config.ts: 暴露 subsetConcurrency 到配置 API

前端:
- api.ts: ServerConfig 新增 subsetConcurrency 字段
- webfont-sdk.js: 客户端并发池(默认 4),setMaxConcurrent API
  通过 document.fonts.load 精确追踪字体加载完成释放槽位
2026-07-30 21:33:45 +08:00
崮生(子虚)
abd75985b7 feat: 临时字体保留时限改为秒为单位(TEMP_RETENTION_SECONDS)
- TEMP_RETENTION_HOURS → TEMP_RETENTION_SECONDS,默认 10800(3小时)
- 前端显示自适应:秒/分钟/小时
- README docker-compose 示例同步更新
2026-07-30 21:24:38 +08:00
崮生(子虚)
19b14f58ea feat: 字体元数据三层架构 + 临时字体保留机制 + 列表页覆盖率排序
- font_meta.ts: cmap 解析覆盖率 + name 表提取字体信息(版权/作者/许可) + 人工配置(font-config.json)
- 三层缓存: 进程内存 → .meta.json 磁盘 → font-config.json stat mtime 热更新
- 临时字体保留机制: TEMP_RETENTION_HOURS(默认3h), 超时未使用自动删除
- 列表页: 覆盖率标签 + 按字符集覆盖率排序
- 详情页: 标签/开源链接/简介 + 字体信息面板(设计师/版权/许可)
- 首页: 红色警告提示切勿上传非商用字体 + 显示保留时限
- SSG noindex bug 修复
2026-07-30 21:19:09 +08:00
崮生(子虚)
5b82dec19a fix: 首页 header 窄屏适配,按钮文字不换行
- header 外层 flex-wrap: wrap,窄屏时标题与按钮组自动换行
- 按钮组 flex-wrap: nowrap + flex-shrink: 0,保持在一行
- 所有按钮/链接 white-space: nowrap + flex-shrink: 0,文字不折行
2026-07-30 20:33:32 +08:00
崮生(子虚)
cdffd4cb57 feat: 字体列表页 + 详情页 SSG + LazyTrigger 懒加载组件
- FontList.vue: 字体列表页,卡片网格布局,支持拼音搜索,点击进入详情
- FontDetail.vue: 字体详情页,SSG 模板 + 服务端占位符替换
- LazyTrigger.vue: 可复用懒触发组件,IntersectionObserver 进入视口回调
- 首页添加字体列表入口,FontDetail 返回列表
- placeholders.ts: 前后端共享的占位符常量
- 后端 font_detail.ts: 读取 SSG 模板并替换占位符
2026-07-30 20:32:42 +08:00
崮生(子虚)
d064e9bc8f fix: 进度条方向 + 宽度
- 进度条缺少 width:100%,导致 absolute 元素宽度为 0 不可见
- keyframes 改为 scaleX(0→1),从空到满增长(符合进度直觉)
2026-07-30 19:53:57 +08:00
崮生(子虚)
3af1a19dce fix: StatsPanel 卡片不显示 — IntersectionObserver 死锁
根因: v-if=data 和 ref=rootRef 在同一元素,data 为 null 时
元素不存在 → observer 无法 observe → data 永远不会加载。

修复: initialLoad() 在 onMounted 时立即调用,不依赖 observer。
IntersectionObserver 仅负责后续轮询的暂停/恢复。

同时修复 formatUptime 中文分支的秒数计算 bug。
2026-07-30 17:33:20 +08:00
崮生(子虚)
8273508c79 feat: StatsPanel 视口内才轮询 + 底部进度条动画
- IntersectionObserver + document.visibilityState 双条件控制轮询
- 卡片底部进度条 (scaleX 动画),每次刷新数据后重启动画
- 避免不可见时浪费请求
- bump version to 1.11.1
2026-07-30 17:26:24 +08:00
崮生(子虚)
13787dfd22 refactor: 重命名 Skill 为 chinese-web-font,聚焦中文字体应用
- skills/chinese-web-typography.md → skills/chinese-web-font.md
- 移除路线图(不写规划)
- 移除英文 README 中不存在的 Typography Presets 表格
- 统一文案:Typography Skill → Chinese Font Skill

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 09:14:04 +08:00
崮生(子虚)
b4a7a820eb feat: AI Typography Skill 系统 + 中英双语 i18n + Before/After Demo
- 新增 skills/chinese-web-typography.md 作为提供给 AI agent 的排版智能文件
- 重写 README.md(中文默认),新增 README.en.md(英文版),互相引用
- 新增 TypographyDemo.vue 前后对比组件,展示中文字体效果差异
- 新增 src/i18n.ts 轻量国际化方案,所有组件文案支持中英切换
- 后端 /api/fonts 返回 temporary 字段标识临时字体
- 升级至 v1.8.0

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 22:41:47 +08:00
崮生(子虚)
76ac23ad5d fix build 2026-04-30 21:03:57 +08:00
崮生(子虚)
53d170dc90 feat: 前端迁移至 Vue3 + TS,后端构建迁移至 tsdown
- 前端从 SolidJS 迁移到 Vue3 Composition API(<script setup lang="ts">)
- 后端构建从 tsup 迁移到 tsdown,动态 import 改为静态以支持单文件输出
- FontSelector 添加 defineProps 修复下拉无选项问题
- StatsPanel 添加"服务状态"标题

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 20:46:30 +08:00
崮生(子虚)
68df9db2da fix: 修复 StatsPanel 中 flex-wrap 属性的 JSX 语法错误
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 19:37:57 +08:00
崮生(子虚)
c18dc44e72 chore: 升级至 v1.7.0,新增内存缓存与运行时统计
- 新增通用 LruCache 类,支持按条目数/字节容量两种淘汰策略
- 字体裁剪结果 LRU 内存缓存(默认 10MB,X-Cache 响应头标识命中)
- 新增 GET /api/stats 运行时统计接口
- 前端统计面板(10s 轮询,页面不可见时暂停)
- API handler 拆分到 routes/ 目录,提取 shared.ts 共享模块

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 19:34:30 +08:00
崮生(子虚)
bd3189b459 优化性能 2026-04-11 17:53:57 +08:00
崮生(子虚)
97f4d72e6a fix: 修复 OTF→TTF 转换字体在浏览器中渲染空白的问题
根因:optimizettf 中 maxPoints/maxContours 只在 TypedArray 格式(_xArr)
的字形分支中统计,OTF→TTF 转换的字形使用对象 contours 格式,
导致 maxp 表中这两个值为 0,浏览器据此跳过渲染。

同时包含 OTF 解析路径的多项性能优化和清理冗余测试文件。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 20:46:48 +08:00
崮生(子虚)
18e60fe940 优化性能 2026-04-09 16:47:41 +08:00
崮生(子虚)
55aa492ce0 新增 ttf 随机选择和提示 2026-04-09 12:02:37 +08:00
崮生(子虚)
e2cc7c1144 feat: 前端格式选择器组件,服务端支持能力透传
- 新增 FontSelector.tsx 独立组件,字体和输出格式并排选择
- /api/config 新增 supportedOutTypes 字段(LLRT 仅 ttf)
- 前端加载配置后自动适配可用格式

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 11:56:10 +08:00
崮生(子虚)
820fc71166 feat: 新增 woff2 输出格式支持,默认使用 woff2
- 后端支持 outType URL 参数(woff2/ttf),Node.js 默认 woff2,LLRT 默认 ttf
- woff2 wasm 延迟初始化,仅首次请求时加载(~8ms)
- SDK 三个入口函数支持 outType 选项,默认 woff2
- 前端 CSS、下载、使用说明适配 woff2
- 基准测试新增 woff2 测试(耗时、体积、压缩率)
- 构建脚本自动复制 woff2.wasm 到 dist 目录

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 11:48:07 +08:00
崮生(子虚)
6d34a5e53a feat: 标语随机使用字体展示,调整字号和位置
标语移至标题下方,每次加载随机选取字体列表中的一个字体渲染,
悬停显示字体名称,字号调至 24px。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 11:34:02 +08:00
崮生(子虚)
4acb1c1e5d docs: 添加品牌标语
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 10:47:48 +08:00
崮生(子虚)
2f7ce0cb72 feat: SDK 多模式架构 + 首页输入事件驱动
- 重构 webfont-sdk.js 为核心增量引擎 + 多触发器架构
- 支持 loadFont(轮询)、observeFont(MutationObserver)、loadText(手动传文本)三种模式
- 三种模式共享 loadedChars,按 fontName|family 自动去重增量加载
- loadFont interval 可从外部配置
- 首页改用 loadText 模式,输入即时触发字体加载
- textarea 高度根据文本行数动态变化

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 10:41:53 +08:00
崮生(子虚)
b902b4e1cc 增强安全性,重构代码 2026-04-08 22:05:17 +08:00
崮生(子虚)
3163e99534 重构上传组件为独立文件,移除 txikijs 依赖,调整布局顺序
- 提取 UploadSection 为 src/UploadSection.tsx,复用 FileUploader 组件和 useUpload hook
- 移除 @txikijs/types 包及所有相关配置引用
- 布局顺序调整:选择字体 → 预览 → CSS代码 → 上传 → 原理/SDK文档

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 20:55:53 +08:00
崮生(子虚)
9da270733d v1.2.0: 增量字体加载 SDK,优化预览体验
- 新增 webfont-sdk.js,支持按需增量加载字体片段,无闪烁
- 预览使用 SDK 增量加载,输入时不再重新加载已有字体
- SDK 根据元素类型(input/textarea vs 其他)正确获取文本
- SDK 支持重复调用同一选择器时自动清理旧状态
- 页面说明区分基础用法和进阶用法,提供 SDK 下载链接
- URL 改为完整域名(location.origin),方便用户直接复制使用
- 预览文本框字体大小调至 32px
- API Key 输入框改为 text 类型消除密码警告
- SEO 优化:添加 description meta,优化 title

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 20:48:23 +08:00
崮生(子虚)
e0f34c36b6 修复上传功能和服务器健壮性问题
- 修复 multipart 解析器:endDelimiter 提前检查导致循环退出
- 修复 Node.js v24 兼容:改为先读取 body 再构造 Request
- 修复 HTTP keep-alive 死锁:按 Content-Length 精确读取 body
- 修复服务器崩溃:connectionHandle 加 try-catch,单连接错误不影响全局
- 修复 URL 写死:webfont.shenzilong.com 改为 localhost
- 复制按钮加"已复制/复制失败"反馈提示
- TEMP_MAX_FILES 改为环境变量可配置
- dev 环境默认启用临时上传和管理员上传
- CSS 代码默认展示,使用技巧不再折叠

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:11:55 +08:00
崮生(子虚)
7fceccfe4d 重构前端UI,新增字体上传/下载/模糊匹配功能
- 前端UI重构:字体选择器、文本预览、CSS输出+复制、下载字体、上传区域
- 后端新增API:/api/fonts(列出字体)、/api/config(公开配置)、/api/upload(上传字体)
- 字体查找支持模糊匹配(精确 > 前缀 > 包含)
- 上传功能分两种模式:临时上传(ENV开关,FIFO上限10个)和管理员上传(API Key认证)
- 新增multipart解析器、配置模块、文件系统抽象(writeFile/readdir/mkdir/unlink)
- 后端启动时等待运行时初始化完成,确保接口可用
- dev-all.ts后端启用tsx watch模式自动重载

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 16:18:46 +08:00
zixu
c6372ea8c3 typo 2024-08-29 09:44:00 +08:00
zixu
6b49d15eae typo 2024-08-29 09:39:37 +08:00
zixu
c6567b8948 前端界面添加防抖 2024-08-29 09:38:47 +08:00
zixu
a1b5502891 支持使用 tjs 运行 2024-08-19 18:10:09 +08:00
zixu
a44f978ef5 改善前端页面 2024-08-18 17:46:13 +08:00
zixu
cae3bad5a9 更新文档 2024-08-18 16:29:18 +08:00
zixu
6b896d768e init 2024-08-18 15:14:50 +08:00