@ggboy123/dsh-paper-reader 1.4.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/README.md +34 -100
  2. package/dist/babeldoc-install.js +6 -2
  3. package/dist/formulas.js +87 -14
  4. package/dist/host.js +107 -3
  5. package/dist/translate-config.js +4 -1
  6. package/dist/translate-selection.js +772 -0
  7. package/lib/client.js +70 -0
  8. package/package.json +1 -1
  9. package/reader/index.html +1016 -42
  10. package/reader/vendor/KaTeX_AMS-Regular.woff2 +0 -0
  11. package/reader/vendor/KaTeX_Caligraphic-Bold.woff2 +0 -0
  12. package/reader/vendor/KaTeX_Caligraphic-Regular.woff2 +0 -0
  13. package/reader/vendor/KaTeX_Fraktur-Bold.woff2 +0 -0
  14. package/reader/vendor/KaTeX_Fraktur-Regular.woff2 +0 -0
  15. package/reader/vendor/KaTeX_Main-Bold.woff2 +0 -0
  16. package/reader/vendor/KaTeX_Main-BoldItalic.woff2 +0 -0
  17. package/reader/vendor/KaTeX_Main-Italic.woff2 +0 -0
  18. package/reader/vendor/KaTeX_Main-Regular.woff2 +0 -0
  19. package/reader/vendor/KaTeX_Math-BoldItalic.woff2 +0 -0
  20. package/reader/vendor/KaTeX_Math-Italic.woff2 +0 -0
  21. package/reader/vendor/KaTeX_SansSerif-Bold.woff2 +0 -0
  22. package/reader/vendor/KaTeX_SansSerif-Italic.woff2 +0 -0
  23. package/reader/vendor/KaTeX_SansSerif-Regular.woff2 +0 -0
  24. package/reader/vendor/KaTeX_Script-Regular.woff2 +0 -0
  25. package/reader/vendor/KaTeX_Size1-Regular.woff2 +0 -0
  26. package/reader/vendor/KaTeX_Size2-Regular.woff2 +0 -0
  27. package/reader/vendor/KaTeX_Size3-Regular.woff2 +0 -0
  28. package/reader/vendor/KaTeX_Size4-Regular.woff2 +0 -0
  29. package/reader/vendor/KaTeX_Typewriter-Regular.woff2 +0 -0
  30. package/reader/vendor/katex.LICENSE +21 -0
  31. package/reader/vendor/katex.NOTICE.md +26 -0
  32. package/reader/vendor/katex.min.css +1 -0
  33. package/reader/vendor/katex.min.js +1 -0
package/lib/client.js CHANGED
@@ -39,6 +39,22 @@ function clearFailureText(err, t) {
39
39
  }
40
40
  }
41
41
 
42
+ /**
43
+ * 分屏「同步滚动」偏好 —— **纯函数**(文件顶层:Node 里执行本文件即可取用,测试 harness 追加导出)。
44
+ * 与 `reader/index.html` 里的同键读写必须保持同一套编码,所以两边都只认 `'1'` / `'0'`。
45
+ *
46
+ * 键为什么长这样(`dpr.syncScroll`:无 topic/name、也不带 `dpr.variant.` 前缀):
47
+ * ① 用户明确要求**全局**(所有论文共用一个值,不按篇记);
48
+ * ② `migrateLsKeys`(改名搬家)只搬 `dpr.variant.` / `dpr.sessionN.` 两个前缀 ⇒ 这个键既不会被搬
49
+ * 也不会被删,论文/专题改名**不可能**让偏好丢失(全局键本来就没有「跟着某篇走」的身份)。
50
+ * 反例:若塞进 `dpr.variant.<topic>/<name>`(按篇),改名搬家会搬它,而「全局」语义就破了。
51
+ * ③ 缺省 = 开:与改造前「分屏两列被 rAF 强行同步」的既有行为一致(老用户升级后观感不变)。
52
+ */
53
+ const DPR_SYNC_SCROLL_KEY = 'dpr.syncScroll'
54
+ /** 只认显式的 '0' 为关;缺失 / 脏值 / 隐私模式都算开(与 reader 的 readSyncPref 逐字同义)。 */
55
+ function dprSyncScrollFromRaw(raw) { return raw !== '0' }
56
+ function dprSyncScrollRaw(on) { return on ? '1' : '0' }
57
+
42
58
  window.__ModuleLoader__.load({
43
59
  // 必须等于 npm 包名:浏览器端 loader 按包名期待注册(改名时漏改这里 →
44
60
  // "loaded without registering" 整页插件加载失败,实测)
@@ -86,6 +102,13 @@ window.__ModuleLoader__.load({
86
102
  setMineruWhyLocal: '本地模式需要你自己跑一个 MinerU 服务(127.0.0.1:8000),适合有显卡、论文不外传的场景。',
87
103
  setMineruWhyCloud: '云端模式只要一个 mineru.net token,无需本地显卡;论文会上传到 mineru.net 解析。',
88
104
  setMineruOffHint: '当前为「关闭」:转录走本地 pdf.js——有文本层的普通 PDF 完全够用;扫描版(没有文本层)与公式引用才需要 MinerU(选本地或云端)。',
105
+ // 分屏「同步滚动」(模式 B 的全局偏好):与阅读器分屏控件旁的那个开关是**同一个值**
106
+ // (键 dpr.syncScroll,见文件顶层的纯函数),任一处改动另一处立即跟着变。
107
+ setSyncScrollTitle: '分屏同步滚动',
108
+ setSyncScrollDesc: '阅读器里「分屏」对照(模式 B:原文 PDF ↔ 中文版 PDF 两列)时,两列是否一起滚动。关闭后两列各自独立滚动(适合对照着看不同页);重新打开会自动把两列对齐回当前页,不会停在两页上。全局偏好:所有论文共用一个值,不按篇记;默认开。模式 A(babeldoc 的中英对照 PDF)只有一个滚动条,不受此项影响。',
109
+ setSyncScrollLabel: '分屏两列同步滚动',
110
+ setSyncScrollOnHint: '当前:开 —— 两列一起滚动(默认)',
111
+ setSyncScrollOffHint: '当前:关 —— 两列各自独立滚动;再打开时会自动对齐回当前页',
89
112
  // 文献管理(删除/重命名):契约见 docs/reader-ux-requirements.md §2.9。
90
113
  // 去重说明:rename/renameTopic/renamePaper/renameFail/delFail 只保留上面上游那组
91
114
  // (JS 对象字面量重复 key 不报错、后者静默胜出 → 必须手工去重,否则文案悄悄取自另一份)。
@@ -158,6 +181,11 @@ window.__ModuleLoader__.load({
158
181
  setMineruWhyLocal: 'Local mode expects your own MinerU service (127.0.0.1:8000) — for GPUs and papers that should stay on your machine.',
159
182
  setMineruWhyCloud: 'Cloud mode needs only a mineru.net token and no local GPU; the paper is uploaded to mineru.net for parsing.',
160
183
  setMineruOffHint: 'Currently Off: transcription uses local pdf.js — fine for PDFs that already have a text layer; scanned PDFs (no text layer) and formula citing need MinerU (local or cloud).',
184
+ setSyncScrollTitle: 'Split-view sync scrolling',
185
+ setSyncScrollDesc: 'In the reader split view (mode B: the original PDF next to the translated -zh.pdf) — should the two columns scroll together? Off: each column scrolls independently (handy to compare different pages); turning it back on realigns both columns to the current page instead of leaving them on different pages. Global preference: one value for every paper, never per paper; on by default. Mode A (babeldoc dual PDF) has a single scrollbar and is unaffected.',
186
+ setSyncScrollLabel: 'Scroll the two split columns together',
187
+ setSyncScrollOnHint: 'Currently: on — the two columns scroll together (default)',
188
+ setSyncScrollOffHint: 'Currently: off — the two columns scroll independently; turning it on realigns them to the current page',
161
189
  newName: 'New name', renameDone: 'Renamed',
162
190
  renameDetached: 'Note: {n} past chats are kept but no longer listed',
163
191
  renameTargetExists: 'A paper or topic with that name already exists',
@@ -1418,6 +1446,47 @@ window.__ModuleLoader__.load({
1418
1446
  )
1419
1447
  }
1420
1448
 
1449
+ /* ---------- 分屏同步滚动卡片(模式 B 的**全局**偏好)----------
1450
+ 本卡片与阅读器是**两个文档**(阅读器是同源 iframe ~ /paper-reader/),共享同一个 localStorage:
1451
+ · 这里勾/取消 → 写 `dpr.syncScroll` → 阅读器收到 storage 事件 → 开关与滚动行为立即跟着变
1452
+ (打开时还会自动把两列对齐回当前页);
1453
+ · 反之在阅读器「分屏」控件旁点开关 → 这里收到 storage 事件 → 勾选态立即跟着变。
1454
+ ⇒ 两处入口互相同步,且都是**同一个键**(键名与 '1'/'0' 编码由文件顶层的纯函数定义,
1455
+ 与 reader/index.html 逐字一致)。默认开 = 缺省值(与改造前行为一致)。 */
1456
+ function SyncScrollCard() {
1457
+ const readPref = () => { try { return dprSyncScrollFromRaw(localStorage.getItem(DPR_SYNC_SCROLL_KEY)) } catch { return true } }
1458
+ const [on, setOn] = useState(readPref)
1459
+ useEffect(() => {
1460
+ const onStorage = (e) => {
1461
+ if (!e || e.key !== DPR_SYNC_SCROLL_KEY) return
1462
+ setOn(dprSyncScrollFromRaw(e.newValue)) // 另一处(阅读器/另一个窗口)改了 → 立即反映
1463
+ }
1464
+ window.addEventListener('storage', onStorage)
1465
+ return () => window.removeEventListener('storage', onStorage)
1466
+ }, [])
1467
+ const apply = (v) => {
1468
+ setOn(v)
1469
+ try { localStorage.setItem(DPR_SYNC_SCROLL_KEY, dprSyncScrollRaw(v)) } catch { /* 隐私模式写不了:阅读器里仍可单独改 */ }
1470
+ }
1471
+ return h('div', { style: SET.card, 'data-dsh-plugin': 'dsh-paper-reader', 'data-dsh-part': 'settings-card' },
1472
+ h('h3', { style: SET.title }, t('setSyncScrollTitle')),
1473
+ h('p', { style: SET.desc }, t('setSyncScrollDesc')),
1474
+ h('div', { style: SET.row },
1475
+ h('label', { style: { ...SET.label, display: 'flex', alignItems: 'center', gap: '8px', margin: '0' }, 'data-dpr-sync-label': '' },
1476
+ h('input', {
1477
+ type: 'checkbox', checked: on, 'data-dpr-sync-input': '',
1478
+ // 与面板主题色对齐(原生 checkbox 的默认蓝与每套主题都对不上):accent-color 是标准
1479
+ // 属性,不支持的旧壳只是回落成默认色,不影响可用性
1480
+ style: { width: '16px', height: '16px', cursor: 'pointer', accentColor: 'var(--dsw-alias-button-primary-fill, #1f6feb)' },
1481
+ onChange: (e) => apply(!!e.target.checked),
1482
+ }),
1483
+ t('setSyncScrollLabel'),
1484
+ ),
1485
+ h('span', { style: SET.meta, 'data-dpr-sync-state': '' }, on ? t('setSyncScrollOnHint') : t('setSyncScrollOffHint')),
1486
+ ),
1487
+ )
1488
+ }
1489
+
1421
1490
  function SettingsPanel() {
1422
1491
  return h('div', { style: { maxWidth: '560px' }, 'data-dsh-plugin': 'dsh-paper-reader', 'data-dsh-surface': 'settings-modal' },
1423
1492
  h(EndpointCard, {
@@ -1433,6 +1502,7 @@ window.__ModuleLoader__.load({
1433
1502
  baseUrlPlaceholder: 'https://api.deepseek.com/v1', modelPlaceholder: 'deepseek-chat', keyPlaceholder: 'sk-...',
1434
1503
  }),
1435
1504
  h(MineruCard, null),
1505
+ h(SyncScrollCard, null),
1436
1506
  )
1437
1507
  }
1438
1508
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ggboy123/dsh-paper-reader",
3
- "version": "1.4.1",
3
+ "version": "1.5.0",
4
4
  "description": "DeepSeek Harness 插件:论文伴读工作台 — PDF 转录 / 检索 / 原生对话伴读 + 内置阅读器页面。",
5
5
  "license": "MIT",
6
6
  "type": "module",