| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
feat(ui): 题头图——删 12 个渐变,加树木照片 - 删除 12 个渐变预设题头图(用户觉得丑)。 - 新增 tree(树木, picsum 绿树森林)。 - 花木/古画感:现有 mist(雾山青绿, 古画水墨感)/fall(瀑布森林, 绿植)/fjord/peak/coast/tree。 - 古画真迹因 wikimedia 连接超时/unsplash 反爬无法稳定下载,用雾山青绿作水墨感代表。 | 1 个月前 | |
chore(清理文件): 删掉一条冗余的 Prism 装配路径(10 个文件 / 77 KB)+ 一份重复图标 ## 这一轮清的是什么 owner 让"清理冗余文件"。先把口径说清楚:**两条同时成立**才算冗余 —— ① 没人按任何写法引用过;② 与保留下来的那份**逐字节相同**,或**功能完全重合**。 (1) public/icons/mark.svg:与设计母版 design/logo/shuyonote-mark.svg 逐字节相同 (sha256 5D64933A…),而 manifest.webmanifest 与 index.html 列出的每一份图标里都没有它 (「关于」对话框早就改成内联 SVG,理由写在 AboutDialog.tsx 里)⇒ 删。 ⚠️ 同类里 signed-plugin-alt.zip 与 signed-plugin.zip 也逐字节相同,但那是**有意**的 (同一份包被两把不同密钥各签一次,tests/fixtures/README.md 写着理由)⇒ 不删。 (2)**代码块高亮本来有两条并行的装配路径** —— 这才是这一轮的大件: · A:index.html 里 10 行 <script src="prism/prism-*.js"> + public/prism/ 下 10 份 vendored 组件(**77 KB**,而且是**阻塞式** script); · B:src/editor/prismSetup.ts(Editor.tsx 启动时 import):prismjs 核心 + 16 个组件 + window.Prism ??= Prism —— 它自己的注释就写着 "independent of the index.html plain <script> loading"。 两条路做的事**完全重合** ⇒ A 是纯冗余。判据不是读注释,是**真 Chromium 里量**:把 A 整条去掉后 重新加载,window.Prism 照旧能 highlight json / rust / sql / go / markdown (token 都出来了)、页面零 JS 报错 ⇒ A 删除(10 个文件 + 10 行 script,public/prism/ 整目录 git rm)。 ⚠️ **记一笔我自己的弯路**(也写进了 CHANGELOG 与判据头注):这条链我先按"文件在、没人加载 ⇒ 漏接线" 判过一次(甚至把 prism-json.js 补回了 index.html),是运行期探针把它否掉的 —— **同一个能力有两条路时, "某条路上少一环"未必是漏,往往是那条路本身就该消失**。第一版门禁还把方向写反了 ("vendored ⇒ 必须被 index.html 加载"),那等于**逼着**冗余的那条路继续存在。 ## 防复发:新门禁 check-prism-components(contract 组) - **R1(判红)唯一路径**:public/prism/ 下不许再有 vendored 组件、index.html 里不许再有 <script src="prism/…">。要加语法就改 prismSetup.ts 的 import。 - **R2(只报告)静态对账**:语言选择器(CodeBlockToolbar.tsx 的 LANGS)列了、而 prismSetup.ts 没有显式 import 的语言 —— 今天 18 种里 2 种(markdown / yaml); 运行期实测 markdown 可用、静态看不到它从哪来,所以只摆出来、**不下结论**。 - 自测 scripts/check-prism-components.test.mjs 8 条,含**两条变异实测**:往 index.html 里塞回 一行 script ⇒ 立刻红;删掉某条 import ⇒ 从报告里消失。判据正则也吃过一次教训(说明文字里的 <script src="prism/prism-*.js"> 是**注释**,得先剥注释、并把组件名限成 [a-z0-9-]+)。 ## 读数 - node scripts/test-report.mjs(contract + smoke + sync + plugin):**33 条门禁全绿** (vitest **2380 passed / 12 skipped / 0 failed**、smoke-web 363/363、tsc 0); - **真 Chromium 运行期探针**(dev server + 本机 Edge):去掉 A 之后 scriptCount=0, Prism.highlight 对 json / rust / sql / go / markdown **都出 token**,页面零报错; - 体积:public/prism/ 删掉 **77 KB**(10 个文件),index.html 少 10 行阻塞 script; - 门禁条数 49 → **50**(docs/TESTING.md 的「机器事实」块与 tests/baseline.json 同步改)。 ## ⚠️ 仍然没做 / 要 owner 拍板的 1. **R2 那份静态对账**(markdown / yaml):补 Prism 组件(进包体积)还是把选择器收窄,是口径问题。 2. **本机工作区的构建残留**(都不入库):src-tauri/target **24.6 GB**、spikes/yrs-interop/target、 dist/ dist-web/ tmp/ .smoke-tmp/ —— 全是可再生成的。要不要清、清哪些等一句话: 清 target 会让下一次 cargo 全量重编,所以没有自作主张。 | 25 天前 | |
fix(security): 收紧 CSP script-src 去掉 unsafe-inline(启动脚本外置) - 启动诊断 + SW 自愈内联脚本移到 public/boot-scripts.js(同步 <script src>,时序不变) - 双端 CSP 的 script-src 由 'self' 'unsafe-inline' 收紧为 'self',彻底阻止内联脚本 XSS(sanitizer 之外的纵深防御) - style-src 保留 unsafe-inline(splash 内联样式) | 1 个月前 | |
fix(安卓): WebView 80 上应用根本起不来 —— 打包目标钉 chrome80 + 补十项 polyfill;并交出件5 真机读数 owner 2026-09-25「低端机已插入」的延续。件5(**整条解锁**的真机读数)必须重出安卓包才作数 —— 而**重出之后那台机器上应用起不来**。本笔先把两个真缺陷堵掉,再把读数交出来。 ## 一、先证实手上那个包是**作废口径**(不靠时间戳猜) 旧 shuyonote-signed.apk(9/24 17:09 构建)里的 lib/arm64-v8a/libshuyonote_lib.so **含 两次 KDF 与 应用级那条、不含 一遍 KDF**(字节扫,命令记在交接文档 §6); 而删掉应用级加密的提交在 **9/24 19:07** ⇒ 拿它量只会得到作废口径。**先证伪,再重出。** ## 二、两个真缺陷(都在 Android 侧,都不在加密那条链上) | # | 症状 | 根因 | 修法 | |---|---|---|---| | ① | Uncaught SyntaxError: Unexpected token '='(**整页挂**,连启动页都到不了) | 产物含 ??= ×135 / ||= ×518 / &&= ×88(逻辑赋值,**Chrome 85+**),而 vite.config.ts **没设 build.target** ⇒ 走 Vite 8 的现代默认;该机系统 WebView 停 **Chromium 80** | vite.config.ts 加 **build.target: "chrome80"**(与"目前能实测到的最老设备"对齐)+ 把取舍写进注释 | | ② | Object.hasOwn is not a function | 同一处版本差:WebView 80 缺一串**运行时 API**,而**应用自己的代码一处都没用**(全是依赖在用)⇒ 只能补 | public/es-polyfills.js 补十项:Object.hasOwn(93) / replaceAll(85) / Array·String.at(92) / findLast·findLastIndex(97) / crypto.randomUUID(92) / **structuredClone(98,降级)** / Element·DocumentFragment.replaceChildren(86) / reportError(95) / **Intl.Segmenter(87,降级)** | ⚠️ **这就是"声称支持"与"真能跑"的差**:minSdk = 24(Android 7),而这台 WebView 80 的 Android 9 **在修之前连启动页都到不了**(SyntaxError 是整页挂,不是某功能降级)。修完之后一路走通: 新建页面 → 设置 → 安全 → 开启加密 → 重启锁定 → 解锁。 **判据:scripts/es-polyfills.test.mjs 从 4 条扩到 15 条。** 新增那组**先把原生实现删掉**、装出 "WebView 80"的处境再逐条钉语义(本机跑它是空操作 ⇒ "本机正常"完全不能说明它对): structuredClone 的循环引用、crypto.randomUUID 的 v4 版本位/变体位 + 50 个不重复、 replaceAll 的 $& 展开与非全局正则抛错、Object.hasOwn 不吃原型链、 **reportError 真的派发 error 事件**(承重:只测"同步不抛"是不够的——**把错误吞掉也能过**)。 ⚠️ 如实钉住两处**降级**:structuredClone 不支持 transfer/原型保留;Intl.Segmenter 按码点切、不按字素簇。 ## 三、件5 读数(真机 release,一次成功解锁) | 机器 / 构建 | **整条解锁** | 其中:钥匙袋 KDF(微基准) | 其余(解盒子 + 开库) | |---|---|---|---| | **Xiaomi MIX 2 · Android 9 · WebView 80(release)** | **742 ms** | 468–476 ms | ≈ 270 ms | 日志行:[unlock] 整条解锁 742 ms(一遍 KDF:钥匙袋那条;+解盒子 +开库) ⇒ **推算值(≈0.75–0.9 s)被实测取代**(这次推算相当准),且**「一遍 KDF」的口径在真机上确认**。 怎么驱动 UI:这台机器 adb shell input tap **是能用的**(与华为那台的记录相反),但最终走 **WebView 的 CDP 口**(adb forward tcp:9222 localabstract:webview_devtools_remote_<pid> + Runtime.evaluate)——按 DOM 点比按坐标稳得多;锁定靠**重启**拿到。 ⚠️ **顺带发现一处 UI 疑问(待查,不阻塞读数)**:「安全」页里**没有「立即锁定」按钮** (加密已开启、主口令已设),本次锁定是靠重启。是条件写窄了还是刻意如此,另开一片核。 ## 四、当轮读数 - vitest 全量 **2259 passed / 12 skipped(0 failed)**,220 文件过(script/es-polyfills.test.mjs 15/15)。 - npx tsc --noEmit **0**;vite build ✓;产物 ??= **0** / ||= **0** (剩 2 处 &&= 在 **Prism 的 operator 正则字面量**里,无害)。 - check-web-commands(Rust 255 / web 247 / 契约 257)/check-panel-layout **40/0**/ check-doc-links(141 篇 / 871 条)/check-doc-facts(46 条门禁)/check-doc-content-access(562 处)全绿。 - 本笔**不动 Rust**、不动 wire/schema;安卓包由本机配方出(docs/TESTING.md §474–525 + Perl5LIB), **未提交任何产物**(dist/、gen/android、APK 都是生成物)。 | 25 天前 | |
pwa(web): 子路径 /app/ 下 PWA 可安装 + 离线可用 - manifest: id/start_url/scope 与图标改为相对 './'(原先绑定域名根,/app/ 下会解析到营销站); 新增 192/512 PNG 及全出血蓝底 maskable 图标(复用 Tauri 品牌 mark 生成)。 - sw.js: 缓存/匹配/prune 全部改为相对 self.location(原先 fetch('/')/caches.match('/') 在子路径取错对象), 缓存版本 v3→v4;导航优先网络、回退缓存 shell;离线对 /app/ 与整页 URL 均可用。 - main.tsx: SW 注册 .register('./sw.js')(原先 '/sw.js' 在 /app/ 下 404,永不注册)。 - index.html: apple-touch-icon 改用 PNG(iOS 对 SVG 支持差)。 | 1 个月前 | |
fix(mobile): 手机上"导出/保存"与"打开 PDF"两处整个不可用(真机复验抓到) ① 保存到用户选的位置一律失败(真机:设置 → 空间 → 导出 ⇒ 红字 Read-only file system (os error 30),并在 Downloads 留下一个 0 字节文件)。 根因:Android 的**保存**对话框(ACTION_CREATE_DOCUMENT)和打开对话框一样只给 content:// URI,而五个导出命令都把它当路径用 —— Path::new("content://…") 是个相对路径(第一段 content:),相对进程 CWD;Android 上 CWD 是 /,只读。 新增 src-tauri/src/save_target.rs(picked_file 的写侧孪生兄弟):桌面直接写路径 (**逐字节不变**,路由判据有单测),URI 目标先写缓存中转文件、写完再整份流式拷进 URI (zip 需要 Write + Seek,而 content:// 只能顺序写;中转文件还能保证失败时不在 用户文件里留半个包)。受影响入口:导出空间 / 导出备份 / 下载附件 / 导出 HTML / 导出模板 / 导出标注副本(备份导不出去属数据安全问题)。 ② 打开任何 PDF 都失败(真机:这份 PDF 没能打开:Promise.withResolvers is not a function)。 根因:设备系统 WebView 停在 **Chrome 114**,而 pdfjs-dist 4.8 需要 Promise.withResolvers(119+)与 AbortSignal.any(116+);legacy 构建救不了 (同样调用这两个 API)。新增 public/es-polyfills.js(index.html 里同步先加载) + public/pdfjs-worker-shim.mjs(worker 是另一个 JS 上下文,页面上的 polyfill 到不了它, 必须由垫片在 worker 内先补、**再动态** import 真 worker——这个顺序就是垫片存在的全部理由)。 验收(都在本机跑过,不必等一轮 CI): - scripts/check-pdf-reload.mjs 扩到 8 条:新增"删掉两个 API"的**因果对照** —— 不带补齐层必须**复现真机原话**(Promise.withResolvers is not a function), 带补齐层必须能打开同一份 3 页 PDF,且控制台不许出现 Setting up fake worker。 - scripts/check-pdfjs-worker-shim.mjs(新,已接进 CI):探针模块在**自身模块体里** 断言两个 API 已就位;把垫片里两条 import 调换 ⇒ 该断言变红(变异自证已做)。 - scripts/es-polyfills.test.mjs(新,vitest 6 条):语义(resolve/reject 接通、 AbortSignal.any 的 reason 传染与空数组)、幂等、**绝不覆盖原生实现**; 把安装那行改成 no-op ⇒ 4 条变红。 - cargo check --lib --tests 通过;pnpm build(含全部静态门禁 + vite build)通过; tsc --noEmit 无输出。 另外(如实记):本提交补上了 1fcb57a 里被误并入的那一半——那次提交带进了 attachments.rs 对 crate::save_target 的调用,却没带 lib.rs 的 mod save_target; 与模块文件本身,所以 1fcb57a 单独 checkout 是**编不过**的。历史不重写,从这里接上。 | 1 个月前 | |
pwa(web): 子路径 /app/ 下 PWA 可安装 + 离线可用 - manifest: id/start_url/scope 与图标改为相对 './'(原先绑定域名根,/app/ 下会解析到营销站); 新增 192/512 PNG 及全出血蓝底 maskable 图标(复用 Tauri 品牌 mark 生成)。 - sw.js: 缓存/匹配/prune 全部改为相对 self.location(原先 fetch('/')/caches.match('/') 在子路径取错对象), 缓存版本 v3→v4;导航优先网络、回退缓存 shell;离线对 /app/ 与整页 URL 均可用。 - main.tsx: SW 注册 .register('./sw.js')(原先 '/sw.js' 在 /app/ 下 404,永不注册)。 - index.html: apple-touch-icon 改用 PNG(iOS 对 SVG 支持差)。 | 1 个月前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 1 个月前 | ||
| 25 天前 | ||
| 1 个月前 | ||
| 25 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 |