@dongfangw/study-kit 0.0.0-stage → 0.1.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 (110) hide show
  1. package/LICENSE +671 -0
  2. package/README.md +28 -2
  3. package/cordis.patch.yml +3 -0
  4. package/ext/adoc-convert/index.mjs +62 -0
  5. package/lib/client.js +5917 -0
  6. package/lib/client.js.map +1 -0
  7. package/lib/docsplit.d.ts +73 -0
  8. package/lib/docsplit.d.ts.map +1 -0
  9. package/lib/docsplit.js +241 -0
  10. package/lib/docsplit.js.map +1 -0
  11. package/lib/git.d.ts +29 -0
  12. package/lib/git.d.ts.map +1 -0
  13. package/lib/git.js +305 -0
  14. package/lib/git.js.map +1 -0
  15. package/lib/index.d.ts +10 -0
  16. package/lib/index.d.ts.map +1 -0
  17. package/lib/index.js +324 -0
  18. package/lib/index.js.map +1 -0
  19. package/lib/isolation.d.ts +33 -0
  20. package/lib/isolation.d.ts.map +1 -0
  21. package/lib/isolation.js +30 -0
  22. package/lib/isolation.js.map +1 -0
  23. package/lib/libraries.d.ts +36 -0
  24. package/lib/libraries.d.ts.map +1 -0
  25. package/lib/libraries.js +118 -0
  26. package/lib/libraries.js.map +1 -0
  27. package/lib/render.d.ts +22 -0
  28. package/lib/render.d.ts.map +1 -0
  29. package/lib/render.js +568 -0
  30. package/lib/render.js.map +1 -0
  31. package/lib/session.d.ts +23 -0
  32. package/lib/session.d.ts.map +1 -0
  33. package/lib/session.js +35 -0
  34. package/lib/session.js.map +1 -0
  35. package/lib/skills.d.ts +24 -0
  36. package/lib/skills.d.ts.map +1 -0
  37. package/lib/skills.js +111 -0
  38. package/lib/skills.js.map +1 -0
  39. package/lib/slidev.d.ts +13 -0
  40. package/lib/slidev.d.ts.map +1 -0
  41. package/lib/slidev.js +755 -0
  42. package/lib/slidev.js.map +1 -0
  43. package/lib/slidevBin.d.ts +7 -0
  44. package/lib/slidevBin.d.ts.map +1 -0
  45. package/lib/slidevBin.js +130 -0
  46. package/lib/slidevBin.js.map +1 -0
  47. package/lib/slidevEnv.d.ts +56 -0
  48. package/lib/slidevEnv.d.ts.map +1 -0
  49. package/lib/slidevEnv.js +702 -0
  50. package/lib/slidevEnv.js.map +1 -0
  51. package/lib/static.d.ts +8 -0
  52. package/lib/static.d.ts.map +1 -0
  53. package/lib/static.js +79 -0
  54. package/lib/static.js.map +1 -0
  55. package/lib/tools.d.ts +4 -0
  56. package/lib/tools.d.ts.map +1 -0
  57. package/lib/tools.js +160 -0
  58. package/lib/tools.js.map +1 -0
  59. package/lib/types/client/DocMarks.d.ts +76 -0
  60. package/lib/types/client/DocMarks.d.ts.map +1 -0
  61. package/lib/types/client/DocViewer.d.ts +21 -0
  62. package/lib/types/client/DocViewer.d.ts.map +1 -0
  63. package/lib/types/client/GitPanel.d.ts +20 -0
  64. package/lib/types/client/GitPanel.d.ts.map +1 -0
  65. package/lib/types/client/LibraryWorkspace.d.ts +5 -0
  66. package/lib/types/client/LibraryWorkspace.d.ts.map +1 -0
  67. package/lib/types/client/MyLibraries.d.ts +5 -0
  68. package/lib/types/client/MyLibraries.d.ts.map +1 -0
  69. package/lib/types/client/SlidevDeckViewer.d.ts +25 -0
  70. package/lib/types/client/SlidevDeckViewer.d.ts.map +1 -0
  71. package/lib/types/client/SlidevEnvPanel.d.ts +11 -0
  72. package/lib/types/client/SlidevEnvPanel.d.ts.map +1 -0
  73. package/lib/types/client/annotations.d.ts +161 -0
  74. package/lib/types/client/annotations.d.ts.map +1 -0
  75. package/lib/types/client/docEnhance.d.ts +55 -0
  76. package/lib/types/client/docEnhance.d.ts.map +1 -0
  77. package/lib/types/client/docKey.d.ts +22 -0
  78. package/lib/types/client/docKey.d.ts.map +1 -0
  79. package/lib/types/client/git.module.css.gen.d.ts +3 -0
  80. package/lib/types/client/git.module.css.gen.d.ts.map +1 -0
  81. package/lib/types/client/icons.d.ts +50 -0
  82. package/lib/types/client/icons.d.ts.map +1 -0
  83. package/lib/types/client/index.d.ts +12 -0
  84. package/lib/types/client/index.d.ts.map +1 -0
  85. package/lib/types/client/prose.d.ts +19 -0
  86. package/lib/types/client/prose.d.ts.map +1 -0
  87. package/lib/types/client/readerControls.d.ts +55 -0
  88. package/lib/types/client/readerControls.d.ts.map +1 -0
  89. package/lib/types/client/readerPrefs.d.ts +73 -0
  90. package/lib/types/client/readerPrefs.d.ts.map +1 -0
  91. package/lib/types/client/readingPos.d.ts +82 -0
  92. package/lib/types/client/readingPos.d.ts.map +1 -0
  93. package/lib/types/client/styles.module.css.gen.d.ts +3 -0
  94. package/lib/types/client/styles.module.css.gen.d.ts.map +1 -0
  95. package/lib/types/client/submitDraft.d.ts +29 -0
  96. package/lib/types/client/submitDraft.d.ts.map +1 -0
  97. package/lib/types/client/viewActive.d.ts +55 -0
  98. package/lib/types/client/viewActive.d.ts.map +1 -0
  99. package/lib/types/types.d.ts +351 -0
  100. package/lib/types/types.d.ts.map +1 -0
  101. package/lib/types.d.ts +351 -0
  102. package/lib/types.d.ts.map +1 -0
  103. package/lib/types.js +6 -0
  104. package/lib/types.js.map +1 -0
  105. package/package.json +101 -6
  106. package/skills/aero-concept-qa/SKILL.md +65 -0
  107. package/skills/aero-learning-path/SKILL.md +61 -0
  108. package/skills/aero-study-guide/SKILL.md +47 -0
  109. package/skills/aero-think/SKILL.md +59 -0
  110. package/skills/kb-organize/SKILL.md +73 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","names":["docThemeCss","persist","useSyncExternalStore","STORE_KEY","emptyDb","sanitize","loadDb","db","persist","useSyncExternalStore","css","styleId","classes","css","useState","useRef","useCallback","useMemo","useRef","useState","useCallback","useMemo","css","useState","useCallback","css","useState","useRef","useCallback","css","useState","css","useRef","useCallback","useState","useCallback","useMemo","useRef","css","css","memo","useState","useRef","useCallback","useMemo","useState","useCallback"],"sources":["../src/client/prose.ts","../src/client/docEnhance.ts","../src/client/readerPrefs.ts","../src/client/readingPos.ts","../src/client/docKey.ts","../src/client/annotations.ts","../src/client/icons.tsx","../src/client/styles.module.css.gen.ts","../src/client/DocMarks.tsx","../src/client/DocViewer.tsx","../src/client/SlidevEnvPanel.tsx","../src/client/SlidevDeckViewer.tsx","../src/client/submitDraft.ts","../src/client/git.module.css.gen.ts","../src/client/GitPanel.tsx","../src/client/readerControls.tsx","../src/client/viewActive.ts","../src/client/LibraryWorkspace.tsx","../src/client/MyLibraries.tsx","../src/client/index.ts"],"sourcesContent":["import docThemeCss from './doc-theme.css?inline'\r\n\r\n/** 阅读上下文(客户端跟踪,提问时自动附带)。 */\r\nexport interface ReadingContext {\r\n /** 文件相对 KB 根的路径。 */\r\n readonly relPath: string\r\n /** 文档/课件标题。 */\r\n readonly title: string\r\n /** 当前小节标题(或幻灯片页码)。 */\r\n readonly section: string\r\n /** 当前阅读内容的文字摘要。 */\r\n readonly excerpt: string\r\n}\r\n\r\n/**\r\n * 外壳级样式:只保留「工作台有界布局」与 Slidev 玩家页的排版。\r\n * 文档正文(.aero-doc)的全部排版在 doc-theme.css —— 那里是 AsciiDoc 书籍版式,\r\n * 包含 admonition/图表题注/卡片块/表格等成套样式,二者职责不要混。\r\n */\r\nconst PROSE_CSS = `\r\n/* 工作台有界布局:当 DSH 外壳在「输入框激活/AI 流式回复」阶段把会话视图区切成\r\n flex:1 0 auto(内容高度)时,让承载本插件工作台的视图区始终保持有界高度,\r\n 从而左侧目录树 / 右侧正文 / Git 抽屉各自独立滚动,不与页面联动。\r\n\r\n ⚠️ 选择器必须锁定「**当前激活的**标签就是工作台」。视图区是\"对话\"与本插件各标签\r\n 共用的同一个容器:早先写成 :has([data-aero-workbench])(任意后代命中即生效),\r\n 而本地硬化补丁给会话视图加了**保活**——访问过的标签都常驻 DOM(非激活者\r\n display:none),于是只要本会话打开过一次「学习资料」,对话视图所在的同一个\r\n 容器就永久带上 overflow:hidden + flex:1 1 0,正文被裁剪、外层 scrollport 也不\r\n 再增高,表现为**对话无法滚动**(实测:聊天内容 2310px 被压在 485px 里,scrollTop\r\n 写不进去)。因此:有标签包裹层(data-conversation-view)时只认激活的那个;\r\n 上游没有包裹层(无保活的旧结构)时保持原匹配。两段实测 A/B 见 tmp/cdp-probe.mjs。 */\r\n[data-slot=\"conversation.session\"] > div:has(> [data-conversation-view-active] [data-aero-workbench]),\r\n[data-slot=\"conversation.session\"] > div:not(:has([data-conversation-view])):has([data-aero-workbench]) {\r\n flex: 1 1 0 !important;\r\n min-height: 0 !important;\r\n overflow: hidden !important;\r\n}\r\n.aero-slide{font-size:clamp(14px,2vw,22px);line-height:1.6}\r\n.aero-slide h1,.aero-slide h2{font-weight:700}\r\n.aero-slide img{max-width:100%;max-height:60vh;object-fit:contain;border-radius:6px}\r\n.aero-slide ul,.aero-slide ol{padding-left:1.4em}\r\n.aero-slide .aero-math-block{overflow-x:auto;overflow-y:hidden;margin:.5em 0}\r\n`\r\n\r\n/** 样式表标记属性:同一标记只保留一个 <style>,内容按最新代码覆盖。 */\r\nconst PROSE_ATTR = 'data-aero-prose'\r\nconst DOC_THEME_ATTR = 'data-aero-doc-theme'\r\n\r\n/**\r\n * 写入/更新一个 <style>。刻意不用「存在即跳过」:客户端插件会被 DSH 的\r\n * client-hmr 热重载(lib/client.js 一变即重新执行本模块),若只在缺失时插入,\r\n * 热重载后页面会继续沿用**上一代**样式,改样式时看起来「没生效」。\r\n */\r\nfunction upsertStyle(attr: string, css: string): void {\r\n // 去掉行首 BOM(U+FEFF):CSS 文件若存成「UTF-8 with BOM」,打包器会把这个字符\r\n // 原样带进 JS 字符串,注入 <style> 后**第一条规则的选择器被污染**(前缀变成一个\r\n // 不可能匹配的 \\uFEFF 类型选择器),于是那一条规则里的自定义属性全部不存在——\r\n // doc-theme.css 的第 0 节正好是 --aero-base / --aero-measure / 墨色 token 的唯一定义处,\r\n // 症状就是「A+ 与 DSH 字号都改不动,正文永远 16px」。源码的 BOM 已删除,这里再兜一层。\r\n const clean = css.replace(/^\\uFEFF/, '')\r\n let tag = document.querySelector<HTMLStyleElement>(`style[${attr}]`)\r\n if (tag === null) {\r\n tag = document.createElement('style')\r\n tag.setAttribute(attr, '1')\r\n document.head.appendChild(tag)\r\n }\r\n if (tag.textContent !== clean) tag.textContent = clean\r\n}\r\n\r\n/** 注入 KaTeX CSS(链到 /aero-kb/katex/katex.min.css)与文档/幻灯片正文样式。 */\r\nexport function ensureGlobalCss(): void {\r\n if (typeof document === 'undefined') return\r\n if (!document.querySelector('link[data-aero-katex]')) {\r\n const link = document.createElement('link')\r\n link.rel = 'stylesheet'\r\n link.href = '/aero-kb/katex/katex.min.css'\r\n link.dataset.aeroKatex = '1'\r\n document.head.appendChild(link)\r\n }\r\n upsertStyle(PROSE_ATTR, PROSE_CSS)\r\n // 书籍版式主题(AsciiDoc 块级构造 + 中文书籍排版)后写入,优先级高于外壳样式。\r\n upsertStyle(DOC_THEME_ATTR, docThemeCss)\r\n}\r\n\r\n/** HTML → 纯文本(用于摘录/上下文)。 */\r\nexport function htmlToText(html: string): string {\r\n const div = document.createElement('div')\r\n div.innerHTML = html\r\n return (div.textContent ?? '').replace(/\\s+/g, ' ').trim()\r\n}\r\n\r\nexport function truncate(s: string, n: number): string {\r\n const t = s.replace(/\\s+/g, ' ').trim()\r\n return t.length <= n ? t : t.slice(0, n) + '…'\r\n}\r\n\r\n/** 组装「阅读上下文 + 问题」的提问文本。 */\r\nexport function buildContextPrompt(ctx: ReadingContext, question?: string): string {\r\n const lines: string[] = []\r\n lines.push('【我正在阅读的资料】')\r\n lines.push(`- 文档/课件:${ctx.title}`)\r\n lines.push(`- 位置:${ctx.section}`)\r\n if (ctx.excerpt) {\r\n lines.push('')\r\n lines.push('【这段内容的摘要】')\r\n lines.push(truncate(ctx.excerpt, 900))\r\n }\r\n lines.push('')\r\n lines.push('【我的问题】')\r\n lines.push(question && question.trim() !== '' ? question.trim() : '(请结合上面的阅读内容回答我的问题)')\r\n return lines.join('\\n')\r\n}\r\n","/**\r\n * AsciiDoc 渲染结果的**阅读器端增强**(纯 DOM 后处理,不依赖宿主)。\r\n *\r\n * 为什么放在客户端而不是宿主 render.ts:\r\n * 宿主把 asciidoctor 的输出直接交给浏览器,而宿主进程内改渲染参数需要重启\r\n * `dsh`(会打断正在上课/备课的会话);本插件是客户端插件,lib/client.js 一写盘\r\n * 就由 DSH 的 client-hmr 热重载,因此阅读体验的改进全部放在这里做。\r\n *\r\n * 五件事(都幂等,可重复执行):\r\n * 1. 图注「落地」:知识库 `image::路径[图注]` 把图注写成了 alt 属性,\r\n * 页面上原本**看不到图注**(STYLE.adoc 要求的「图注五要素」全被吞掉)。\r\n * 这里把 alt 提升为可见题注,并拆成「图号 / 对象 / 条件→结论」三层。\r\n * 2. 去重自动题注号:作者手写的「图 C05.9-1」与 asciidoctor 自动加的\r\n * 「Figure 1. / 图 1.」会同时出现,中英混排很脏;仅当后面紧跟手写图号时去掉。\r\n * 3. 宽表包一层横向滚动容器(直接给 <table> 加 overflow 会破坏列宽算法)。\r\n * 4. 外链 target=_blank(否则点一个 http 链接会把整个工作台导航走)。\r\n * 5. 节标题编号「1 / 1.1 / 1.1.1」:知识手册一节动辄数百行,长文里靠编号定位;\r\n * **只给 knowledge-base 的 adoc**(教案自带「B — Bridge-in / 1.2.1 …」体系,\r\n * 参考书 md 另成体系,一律不碰),编号与右侧「本页目录」共用同一份(见 sectionNumbers)。\r\n */\r\n\r\n/** 自动题注号前缀(asciidoctor 的 figure/table/example/listing-caption 产物)。 */\r\nconst AUTO_CAPTION_RE =\r\n /^(?:Figure|Table|Example|Listing|图|表|例|代码)\\s*\\d+\\.\\s+(?=(?:图|表|例|代码)\\s*[A-Za-z]?\\d)/\r\n\r\n/** 手写图/表题注:`图 C05.9-1 …` / `表 5.9-1 …` / `图 1-2 …`。 */\r\nconst MANUAL_CAPTION_RE = /^((?:图|表)\\s*[A-Za-z]?\\d+[\\w.\\u2013-]*)\\s*([\\s\\S]*)$/\r\n\r\n/** 图注「条件→结论」分隔符(STYLE.adoc 约定的「。——」)。 */\r\nconst CAPTION_TAIL_RE = /^([\\s\\S]*?)\\s*。——\\s*([\\s\\S]*)$/\r\n\r\n/** 知识库固定小节 → 卡片样式类。 */\r\nconst SPECIAL_SECTIONS: ReadonlyArray<readonly [RegExp, string]> = [\r\n [/^本节小结$|^小结$/, 'aero-sect-summary'],\r\n [/^本节来源$|^来源$/, 'aero-sect-source'],\r\n [/^练习指引$|^课后练习$|^习题$/, 'aero-sect-practice'],\r\n]\r\n\r\nfunction text(el: Element): string {\r\n return (el.textContent ?? '').replace(/\\s+/g, ' ').trim()\r\n}\r\n\r\n/** 元素是否只有纯文本(没有元素子节点)——有子元素时(例如 KaTeX)不动其内容。 */\r\nfunction isPlainText(el: Element): boolean {\r\n return el.children.length === 0\r\n}\r\n\r\n/**\r\n * 把题注文本拆成「编号 / 对象 / 条件→结论」三段并写回元素。\r\n * 只在纯文本题注上生效,避免破坏题注里的行内公式(KaTeX 节点)。\r\n */\r\nfunction formatCaption(el: Element): void {\r\n el.classList.add('aero-caption')\r\n if (!isPlainText(el) || el.getAttribute('data-aero-cap') === '1') return\r\n let raw = text(el).replace(AUTO_CAPTION_RE, '')\r\n const manual = MANUAL_CAPTION_RE.exec(raw)\r\n let no: string | null = null\r\n if (manual !== null) {\r\n no = (manual[1] ?? '').trim()\r\n raw = (manual[2] ?? '').trim()\r\n }\r\n let body = raw\r\n let tail: string | null = null\r\n const t = CAPTION_TAIL_RE.exec(raw)\r\n if (t !== null) {\r\n body = (t[1] ?? '').trim()\r\n tail = (t[2] ?? '').trim()\r\n }\r\n el.textContent = ''\r\n if (no !== null && no !== '') {\r\n const span = document.createElement('span')\r\n span.className = 'aero-cap-no'\r\n span.textContent = no\r\n el.appendChild(span)\r\n }\r\n el.appendChild(document.createTextNode(body))\r\n if (tail !== null && tail !== '') {\r\n const span = document.createElement('span')\r\n span.className = 'aero-cap-tail'\r\n span.textContent = '。—— ' + tail\r\n el.appendChild(span)\r\n }\r\n el.setAttribute('data-aero-cap', '1')\r\n}\r\n\r\n/** 宽表包一层滚动容器。 */\r\nfunction wrapTables(root: HTMLElement): void {\r\n // 只处理「正文表格」:\r\n // · AsciiDoc 的 tableblock 表格本体 —— 注意 Asciidoctor 给**每个单元格**也加了\r\n // tableblock 类(td.tableblock.halign-*),所以必须按标签名精确匹配 table;\r\n // · Markdown 的裸 <table>(markdown-it 直接挂在 .aero-doc-body 下)。\r\n // 结构性内层表格(admonition / colist / hdlist)一律跳过——早期版本把 div 插进 <tr>,\r\n // 整张表的列宽算法会崩(实测列宽塌成 13px、单元格竖排)。\r\n for (const table of Array.from(root.querySelectorAll<HTMLTableElement>('table'))) {\r\n const parent = table.parentElement\r\n if (parent === null || parent.classList.contains('aero-tablewrap')) continue\r\n if (table.closest('.admonitionblock, .colist, .hdlist') !== null) continue\r\n const isDocTable = table.classList.contains('tableblock') ||\r\n parent.classList.contains('aero-doc-body') || parent.classList.contains('aero-doc')\r\n if (!isDocTable) continue\r\n const wrap = document.createElement('div')\r\n wrap.className = 'aero-tablewrap'\r\n parent.insertBefore(wrap, table)\r\n wrap.appendChild(table)\r\n }\r\n}\r\n\r\n/**\r\n * 图注落地 + 放大能力标记。\r\n * `image::path[图注]` 的位置参数是 **alt**(不是 title),所以这里以 alt 为准。\r\n */\r\nfunction enhanceFigures(root: HTMLElement): void {\r\n for (const block of Array.from(root.querySelectorAll<HTMLElement>('.imageblock'))) {\r\n const content = block.querySelector(':scope > .content')\r\n const img = content?.querySelector('img') ?? block.querySelector('img')\r\n if (img === null || img === undefined) continue\r\n const title = block.querySelector(':scope > .title')\r\n if (title !== null) {\r\n formatCaption(title)\r\n } else if (!block.hasAttribute('data-aero-cap-done')) {\r\n const alt = (img.getAttribute('alt') ?? '').trim()\r\n if (alt !== '') {\r\n const cap = document.createElement('div')\r\n cap.className = 'aero-caption'\r\n cap.textContent = alt\r\n formatCaption(cap)\r\n block.appendChild(cap)\r\n }\r\n }\r\n // 单图块才给放大:左右浮动的图与行内小图不参与\r\n if (block.parentElement !== null && !block.classList.contains('left') && !block.classList.contains('right')) {\r\n block.classList.add('aero-zoomable')\r\n img.setAttribute('data-aero-zoom', '1')\r\n if (!img.hasAttribute('title')) img.setAttribute('title', '点击放大')\r\n }\r\n block.setAttribute('data-aero-cap-done', '1')\r\n }\r\n}\r\n\r\n/** 表格/示例/代码块的题注(去掉重复的自动编号)。 */\r\nfunction enhanceBlockTitles(root: HTMLElement): void {\r\n for (const el of Array.from(root.querySelectorAll<HTMLElement>('.tableblock > caption'))) formatCaption(el)\r\n for (const el of Array.from(root.querySelectorAll<HTMLElement>('.exampleblock > .title, .listingblock > .title, .literalblock > .title, .openblock > .title'))) {\r\n if (!isPlainText(el) || el.getAttribute('data-aero-cap') === '1') continue\r\n const raw = text(el)\r\n const stripped = raw.replace(AUTO_CAPTION_RE, '')\r\n if (stripped !== raw) el.textContent = stripped\r\n el.setAttribute('data-aero-cap', '1')\r\n }\r\n}\r\n\r\n/** 知识库固定小节(本节小结 / 本节来源 / 练习指引)打标,交给 CSS 做卡片。 */\r\nfunction markSpecialSections(root: HTMLElement): void {\r\n for (const heading of Array.from(root.querySelectorAll<HTMLElement>('h2, h3'))) {\r\n // 编号已写进标题时(重复执行 / 顺序变化)先摘掉,否则「9. 本节小结」匹配不上。\r\n const label = stripManualSectionNo(text(heading))\r\n for (const [re, cls] of SPECIAL_SECTIONS) {\r\n if (!re.test(label)) continue\r\n const block = heading.closest('.sect1, .sect2')\r\n if (block !== null) block.classList.add(cls)\r\n break\r\n }\r\n }\r\n}\r\n\r\n/** 外链新窗口打开:不这么做会把整个工作台导航走(阅读位置全丢)。 */\r\nfunction enhanceExternalLinks(root: HTMLElement): void {\r\n for (const a of Array.from(root.querySelectorAll<HTMLAnchorElement>('a[href]'))) {\r\n const href = a.getAttribute('href') ?? ''\r\n if (!/^https?:\\/\\//i.test(href)) continue\r\n a.setAttribute('target', '_blank')\r\n a.setAttribute('rel', 'noopener noreferrer')\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// 节标题编号(「1 / 1.1 / 1.1.1」)\r\n//\r\n// 知识手册的**一节**(如 C02.2)动辄数百行、十几个小节标题,源文件里没有编号,\r\n// 长文里只能靠「往上翻找标题」定位。这里在阅读器端按标题层级现算一套号,\r\n// 正文标题与右侧「本页目录」共用同一个 Map(宿主渲染不动 → 不需要重启 dsh)。\r\n// ---------------------------------------------------------------------------\r\n\r\n/** 启用编号的文档:知识手册(全速域 / 数学基础)的 adoc 正文。 */\r\nconst HANDBOOK_PATH_RE = /^knowledge-base\\//\r\n\r\n/** 文档是否属于「节标题编号」范围(教案 adoc 与参考书 md 各自已有编号体系)。 */\r\nexport function isSectionNumberingTarget(relPath: string, kind: 'adoc' | 'md'): boolean {\r\n return kind === 'adoc' && HANDBOOK_PATH_RE.test(relPath.replaceAll('\\\\', '/'))\r\n}\r\n\r\n/**\r\n * 作者手写在标题里的编号(`1. 模型范围` / `1.1、`)——历史节文件里可能残留(早先的\r\n * C09.1/C09.2 就写过一半)。编号改由阅读器统一给出,显示前把这截重复前缀摘掉。\r\n * 只认「数字 + 句读符」(`18 世纪`、`1904 年`这类年份没有句读符,不会被误摘)。\r\n */\r\nconst MANUAL_SECTION_NO_RE = /^\\d+(?:\\.\\d+)*[.、)]\\s*/\r\n\r\n/** 摘掉标题里手写的编号前缀(没有则原样返回)。 */\r\nexport function stripManualSectionNo(title: string): string {\r\n return title.replace(MANUAL_SECTION_NO_RE, '')\r\n}\r\n\r\n/** 参与编号的标题(与宿主 `DocRenderResult.sections` 的最小公共形状)。 */\r\nexport interface SectionHeading {\r\n readonly id: string\r\n readonly level: number\r\n readonly title: string\r\n}\r\n\r\n/**\r\n * 按标题层级算编号:同级递增、遇浅级重置更深级;`level <= 1`(文档标题 h1)不编号也不占号。\r\n *\r\n * 层级跳级(h2 直接到 h4)当前全库不存在;真出现时中间层记 0(`1.0.1`),\r\n * 由 `scripts/tests/section-numbers.test.ts` 对全库断言「无跳级」兜底。\r\n */\r\nexport function sectionNumbers(sections: readonly SectionHeading[]): Map<string, string> {\r\n const numbers = new Map<string, string>()\r\n const counters: number[] = []\r\n for (const section of sections) {\r\n if (section.level <= 1) continue\r\n const depth = section.level - 2\r\n if (counters.length > depth + 1) counters.length = depth + 1\r\n while (counters.length <= depth) counters.push(0)\r\n counters[depth] = (counters[depth] ?? 0) + 1\r\n numbers.set(section.id, counters.join('.'))\r\n }\r\n return numbers\r\n}\r\n\r\n/** 去掉标题首个文本节点里手写的编号(只动文本节点,KaTeX 等子元素不受影响)。 */\r\nfunction dropManualSectionNo(heading: HTMLElement): void {\r\n const node = heading.firstChild\r\n if (node === null || node.nodeType !== 3) return\r\n const raw = node.nodeValue ?? ''\r\n node.nodeValue = stripManualSectionNo(raw)\r\n}\r\n\r\n/** 把算好的编号写进正文标题(幂等:先摘旧号,再按当前层级重写)。 */\r\nfunction numberSectionHeadings(root: HTMLElement, numbers: ReadonlyMap<string, string>): void {\r\n for (const heading of Array.from(root.querySelectorAll<HTMLElement>('h2, h3, h4, h5, h6'))) {\r\n const no = numbers.get(heading.id)\r\n if (no === undefined || no === '') continue\r\n for (const stale of Array.from(heading.querySelectorAll(':scope > .aero-secnum'))) stale.remove()\r\n dropManualSectionNo(heading)\r\n const span = document.createElement('span')\r\n span.className = 'aero-secnum'\r\n // 尾随空格进文本(复制标题、阅读上下文与目录三者一致);视觉间距由 CSS 补足。\r\n span.textContent = `${no}. `\r\n heading.insertBefore(span, heading.firstChild)\r\n }\r\n}\r\n\r\n/**\r\n * Markdown 插图段:教材 md 的写法是「图片行 + 尾随两空格 + 图注行」,\r\n * markdown-it 会渲染成 `<p><img><br>图1-1 一点处密度的定义</p>`,\r\n * 即**图与图注挤在同一个段落里**(图注还可能含行内公式 → KaTeX 元素)。\r\n *\r\n * 处理:把 `<br>` 去掉、把图注节点整体搬进 `.aero-caption`(用 appendChild 搬运\r\n * 而不是取 textContent,否则图注里的行内公式会退化成纯文本),图片加放大能力。\r\n * 段落里还有正文的(图文混排)一律不动。\r\n */\r\nfunction enhanceMarkdownFigures(root: HTMLElement): void {\r\n for (const p of Array.from(root.querySelectorAll<HTMLParagraphElement>('p'))) {\r\n if (p.classList.contains('aero-md-figure')) continue\r\n const imgs = Array.from(p.querySelectorAll('img'))\r\n if (imgs.length === 0) continue\r\n const rest: ChildNode[] = []\r\n for (const node of Array.from(p.childNodes)) {\r\n if (node.nodeType === 1 && (node as Element).tagName === 'IMG') continue\r\n if (node.nodeType === 1 && (node as Element).tagName === 'BR') continue\r\n if (node.nodeType === 3 && (node.nodeValue ?? '').trim() === '') continue\r\n rest.push(node)\r\n }\r\n const restText = rest.map((n) => n.textContent ?? '').join(' ').replace(/\\s+/g, ' ').trim()\r\n // 只认「纯图片」或「图片 + 图注」:图注以 图/表/例 + 编号 开头\r\n const isCaptionLike = rest.length === 0 || /^(图|表|例)\\s*[A-Za-z]?\\d/.test(restText)\r\n if (!isCaptionLike) continue\r\n\r\n p.classList.add('aero-md-figure')\r\n if (rest.length > 0) {\r\n const cap = document.createElement('div')\r\n cap.className = 'aero-caption'\r\n for (const node of rest) cap.appendChild(node)\r\n p.appendChild(cap)\r\n formatCaption(cap)\r\n }\r\n for (const img of imgs) {\r\n img.setAttribute('data-aero-zoom', '1')\r\n if (!img.hasAttribute('title')) img.setAttribute('title', '点击放大')\r\n if (rest.length === 0) {\r\n const alt = (img.getAttribute('alt') ?? '').trim()\r\n if (alt !== '' && p.querySelector('.aero-caption') === null) {\r\n const cap = document.createElement('div')\r\n cap.className = 'aero-caption'\r\n cap.textContent = alt\r\n formatCaption(cap)\r\n p.appendChild(cap)\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * 对渲染后的正文做全部增强;幂等,可对同一节点重复调用。\r\n *\r\n * numbers 为 `sectionNumbers()` 的产物(键 = 标题 id,值 = `1.1`):传了才写节标题编号,\r\n * 编号必须放在 `markSpecialSections` 之后,否则「本节小结」等固定小节匹配不上。\r\n */\r\nexport function enhanceDoc(root: HTMLElement, numbers?: ReadonlyMap<string, string> | null): void {\r\n wrapTables(root)\r\n enhanceBlockTitles(root)\r\n enhanceFigures(root)\r\n enhanceMarkdownFigures(root)\r\n markSpecialSections(root)\r\n enhanceExternalLinks(root)\r\n if (numbers !== undefined && numbers !== null) numberSectionHeadings(root, numbers)\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// 资料名片:从 AsciiDoc 头部属性(:kb-id:/:kb-status:/…)生成「本书信息」卡片。\r\n// 这些属性在 asciidoctor 的 HTML 里不会输出,因此单独取一次源文档头部解析。\r\n// ---------------------------------------------------------------------------\r\n\r\n/** 知识库文档头部元数据(键名统一小写,已去掉 `kb-` 前缀里的展示映射在 UI 层做)。 */\r\nexport interface DocMeta {\r\n readonly title?: string\r\n readonly attrs: Readonly<Record<string, string>>\r\n}\r\n\r\nconst ATTR_LINE_RE = /^:([A-Za-z0-9_][A-Za-z0-9_-]*):\\s*(.*)$/\r\n\r\n/**\r\n * 解析 AsciiDoc 文件头部:文档标题(`= …`)与紧随其后的 `:属性: 值` 行。\r\n * 遇到首个空行或正文行即停止(AsciiDoc 头部只在文件最前面)。\r\n */\r\nexport function parseAdocHeader(source: string): DocMeta {\r\n const attrs: Record<string, string> = {}\r\n let title: string | undefined\r\n const lines = source.split(/\\r?\\n/)\r\n let seenTitle = false\r\n for (const line of lines.slice(0, 80)) {\r\n const trimmed = line.trim()\r\n if (trimmed === '') {\r\n if (seenTitle || Object.keys(attrs).length > 0) break\r\n continue\r\n }\r\n if (!seenTitle && /^=\\s+\\S/.test(trimmed) && !trimmed.startsWith('==')) {\r\n title = trimmed.replace(/^=\\s+/, '').trim()\r\n seenTitle = true\r\n continue\r\n }\r\n const m = ATTR_LINE_RE.exec(trimmed)\r\n if (m !== null) {\r\n attrs[(m[1] ?? '').toLowerCase()] = (m[2] ?? '').trim()\r\n continue\r\n }\r\n break\r\n }\r\n return title === undefined ? { attrs } : { title, attrs }\r\n}\r\n","/**\r\n * 阅读器偏好(客户端本地持久化 + 跨组件订阅)。\r\n *\r\n * 全部在「学习资料」顶栏的「阅读设置」面板里调,存 localStorage,DocViewer 与\r\n * LibraryWorkspace 订阅同一份状态:\r\n * · 版式 docLayout —— 书籍版式(默认):衬线、两端对齐、首行缩进 2 字符、居中章题、\r\n * 42em 版心;网页版式:无衬线、左对齐、不缩进、56em 版心。面板无衬线/宽版心更适合扫读。\r\n * · 字号 docFontStep —— 在 DSH 全局字号(--dsh-content-font-size)之上的倍率档。\r\n * 与全局设置相乘而非覆盖,因此用户在 DSH 设置里调整后仍然生效。\r\n * · 字体 docFont —— 跟随版式 / 衬线(宋体系)/ 无衬线(黑体系)/ 楷体。\r\n * · 行距 docLeading、版心 docMeasure、底色 docPaper —— 阅读舒适度的三个直接旋钮。\r\n * · 本页目录 docOutline —— 界面元素显隐(随正文而来,正常保留)。\r\n * · 专注 docZen / 文件树 docSidebar —— 只在本会话内生效,**刻意不写 localStorage**:\r\n * 这两个开关都会把\"文档列表\"这一入口藏起来,若跨重启保留,重进「学习资料」看到的就是\r\n * \"一份文档都没有\"且想不起自己点过什么(全屏同理不保留)。\r\n * 原则:会隐藏内容入口的显隐不跨会话,排版偏好(版式/字号/字体/行距/版心/底色/目录)照常保留。\r\n *\r\n * 实现刻意做成一个 ~20 行的订阅式存储,避免为此引入状态库或把状态提到\r\n * LibraryWorkspace 再逐层透传。写入 data-* 属性由视图层负责,取值规则见 doc-theme.css。\r\n */\r\nimport { useSyncExternalStore } from 'react'\r\n\r\nexport type DocLayout = 'book' | 'web'\r\nexport type DocFont = 'auto' | 'serif' | 'sans' | 'kai'\r\nexport type DocLeading = 'tight' | 'normal' | 'loose'\r\nexport type DocMeasure = 'auto' | 'narrow' | 'wide' | 'full'\r\nexport type DocPaper = 'theme' | 'white' | 'sepia' | 'green' | 'dark'\r\n\r\n/**\r\n * 字号档(倍率)。索引即持久化值,越界回落到默认档。\r\n *\r\n * 上限 160% → 300%(新增 180 / 200 / 250 / 300 四档):160% 对长时间阅读\r\n * (投屏、视力不佳、高 DPI 小屏)仍然偏小,而倍率只作用于正文——版心按 em\r\n * 缩放,行宽不会随字号失控。阶梯与浏览器缩放习惯对齐(…125 / 140 / 160 /\r\n * 180 / 200 / 250 / 300),避免出现「再按一档跳过头」的档位。\r\n *\r\n * 这里是字号档的唯一真源:doc-theme.css 通过 --aero-scale 读取倍率,不再逐档\r\n * 枚举 CSS 规则,因此改这一行就够,不会出现「表里有档、样式里没有」的漂移。\r\n */\r\nexport const FONT_STEPS = [0.9, 1, 1.1, 1.25, 1.4, 1.6, 1.8, 2, 2.5, 3] as const\r\nexport const FONT_STEP_DEFAULT = 1\r\nexport const FONT_STEP_MAX = FONT_STEPS.length - 1\r\n\r\nconst LAYOUT_KEY = 'aero.doc.layout'\r\nconst FONT_STEP_KEY = 'aero.doc.fontStep'\r\nconst FONT_KEY = 'aero.doc.font'\r\nconst LEADING_KEY = 'aero.doc.leading'\r\nconst MEASURE_KEY = 'aero.doc.measure'\r\nconst PAPER_KEY = 'aero.doc.paper'\r\nconst OUTLINE_KEY = 'aero.doc.outline'\r\n/** 旧版本把「专注」「文件树」也写进了 localStorage;初始化时清掉,见 zenStore/sidebarStore 说明。 */\r\nconst LEGACY_SESSION_KEYS = ['aero.doc.zen', 'aero.doc.sidebar'] as const\r\n\r\nfunction readStored<T extends string>(key: string, allowed: readonly T[], fallback: T): T {\r\n try {\r\n const raw = window.localStorage.getItem(key)\r\n if (raw !== null && (allowed as readonly string[]).includes(raw)) return raw as T\r\n } catch {\r\n /* 隐私模式等场景下 localStorage 不可用:退回默认值 */\r\n }\r\n return fallback\r\n}\r\n\r\n/** 布尔偏好:认 '1'/'0',并兼容早期版本写过的 'open'/'closed';其余走默认值。 */\r\nfunction readFlag(key: string, fallback: boolean): boolean {\r\n try {\r\n const raw = window.localStorage.getItem(key)\r\n if (raw === '1' || raw === 'open') return true\r\n if (raw === '0' || raw === 'closed') return false\r\n } catch {\r\n /* 同上 */\r\n }\r\n return fallback\r\n}\r\n\r\n/** 档位索引:越界或非整数一律回落到默认档,避免旧数据把界面卡在非法状态。 */\r\nfunction readIndex(key: string, max: number, fallback: number): number {\r\n try {\r\n const raw = window.localStorage.getItem(key)\r\n if (raw !== null) {\r\n const n = Number(raw)\r\n if (Number.isInteger(n) && n >= 0 && n <= max) return n\r\n }\r\n } catch {\r\n /* 同上 */\r\n }\r\n return fallback\r\n}\r\n\r\nfunction persist(key: string, value: string): void {\r\n try {\r\n window.localStorage.setItem(key, value)\r\n } catch {\r\n /* 存不下就只在本次会话生效 */\r\n }\r\n}\r\n\r\ninterface Store<T> {\r\n get(): T\r\n set(next: T): void\r\n subscribe(fn: () => void): () => void\r\n use(): T\r\n}\r\n\r\nfunction createStore<T>(initial: T): Store<T> {\r\n let current = initial\r\n const listeners = new Set<() => void>()\r\n return {\r\n get: () => current,\r\n set(next) {\r\n if (next === current) return\r\n current = next\r\n for (const fn of listeners) fn()\r\n },\r\n subscribe(fn) {\r\n listeners.add(fn)\r\n return () => {\r\n listeners.delete(fn)\r\n }\r\n },\r\n use() {\r\n return useSyncExternalStore(this.subscribe, this.get, this.get)\r\n },\r\n }\r\n}\r\n\r\nconst layoutStore = createStore<DocLayout>(readStored(LAYOUT_KEY, ['book', 'web'] as const, 'book'))\r\nconst fontStepStore = createStore<number>(readIndex(FONT_STEP_KEY, FONT_STEP_MAX, FONT_STEP_DEFAULT))\r\nconst fontStore = createStore<DocFont>(readStored(FONT_KEY, ['auto', 'serif', 'sans', 'kai'] as const, 'auto'))\r\nconst leadingStore = createStore<DocLeading>(readStored(LEADING_KEY, ['tight', 'normal', 'loose'] as const, 'normal'))\r\nconst measureStore = createStore<DocMeasure>(readStored(MEASURE_KEY, ['auto', 'narrow', 'wide', 'full'] as const, 'auto'))\r\nconst paperStore = createStore<DocPaper>(readStored(PAPER_KEY, ['theme', 'white', 'sepia', 'green', 'dark'] as const, 'theme'))\r\nconst outlineStore = createStore<boolean>(readFlag(OUTLINE_KEY, true))\r\n\r\n// 「专注」与「文件树」都是会话内的视图状态,不进 localStorage。\r\n// 旧版本存过 aero.doc.zen / aero.doc.sidebar:这两个键一旦残留,重进「学习资料」时\r\n// 文件树就是 display:none,用户只会看到\"这里没有文档\"。升级时清掉,避免被旧状态困住。\r\ntry {\r\n for (const key of LEGACY_SESSION_KEYS) window.localStorage.removeItem(key)\r\n} catch {\r\n /* 隐私模式等场景下 localStorage 不可用:也无旧键可清 */\r\n}\r\nconst zenStore = createStore<boolean>(false)\r\nconst sidebarStore = createStore<boolean>(true)\r\n\r\n/** 当前版式。 */\r\nexport function getDocLayout(): DocLayout {\r\n return layoutStore.get()\r\n}\r\n\r\n/** 切换版式(写入 localStorage)。 */\r\nexport function setDocLayout(next: DocLayout): void {\r\n persist(LAYOUT_KEY, next)\r\n layoutStore.set(next)\r\n}\r\n\r\n/** 订阅版式(组件内使用)。 */\r\nexport function useDocLayout(): DocLayout {\r\n return layoutStore.use()\r\n}\r\n\r\n/** 当前字号档索引。 */\r\nexport function getFontStep(): number {\r\n return fontStepStore.get()\r\n}\r\n\r\n/** 设置字号档;越界自动夹到 [0, FONT_STEP_MAX]。 */\r\nexport function setFontStep(next: number): void {\r\n const clamped = Math.max(0, Math.min(FONT_STEP_MAX, Math.round(next)))\r\n persist(FONT_STEP_KEY, String(clamped))\r\n fontStepStore.set(clamped)\r\n}\r\n\r\n/** 字号加/减一档(快捷键与 A- / A+ 按钮共用)。 */\r\nexport function nudgeFontStep(delta: number): void {\r\n setFontStep(getFontStep() + delta)\r\n}\r\n\r\n/** 字号复位到默认档。 */\r\nexport function resetFontStep(): void {\r\n setFontStep(FONT_STEP_DEFAULT)\r\n}\r\n\r\nexport function useFontStep(): number {\r\n return fontStepStore.use()\r\n}\r\n\r\nexport function getDocFont(): DocFont {\r\n return fontStore.get()\r\n}\r\n\r\nexport function setDocFont(next: DocFont): void {\r\n persist(FONT_KEY, next)\r\n fontStore.set(next)\r\n}\r\n\r\nexport function useDocFont(): DocFont {\r\n return fontStore.use()\r\n}\r\n\r\nexport function getDocLeading(): DocLeading {\r\n return leadingStore.get()\r\n}\r\n\r\nexport function setDocLeading(next: DocLeading): void {\r\n persist(LEADING_KEY, next)\r\n leadingStore.set(next)\r\n}\r\n\r\nexport function useDocLeading(): DocLeading {\r\n return leadingStore.use()\r\n}\r\n\r\nexport function getDocMeasure(): DocMeasure {\r\n return measureStore.get()\r\n}\r\n\r\nexport function setDocMeasure(next: DocMeasure): void {\r\n persist(MEASURE_KEY, next)\r\n measureStore.set(next)\r\n}\r\n\r\nexport function useDocMeasure(): DocMeasure {\r\n return measureStore.use()\r\n}\r\n\r\nexport function getDocPaper(): DocPaper {\r\n return paperStore.get()\r\n}\r\n\r\nexport function setDocPaper(next: DocPaper): void {\r\n persist(PAPER_KEY, next)\r\n paperStore.set(next)\r\n}\r\n\r\nexport function useDocPaper(): DocPaper {\r\n return paperStore.use()\r\n}\r\n\r\n/** 本页目录是否展开。 */\r\nexport function getOutlineOpen(): boolean {\r\n return outlineStore.get()\r\n}\r\n\r\nexport function setOutlineOpen(open: boolean): void {\r\n persist(OUTLINE_KEY, open ? '1' : '0')\r\n outlineStore.set(open)\r\n}\r\n\r\n/** 订阅「本页目录」显隐(组件内使用)。 */\r\nexport function useOutlineOpen(): boolean {\r\n return outlineStore.use()\r\n}\r\n\r\n/** 专注阅读:隐藏左侧文件树与底部提问栏,正文独占。仅本会话有效(刷新即回到常规视图)。 */\r\nexport function getZen(): boolean {\r\n return zenStore.get()\r\n}\r\n\r\nexport function setZen(on: boolean): void {\r\n zenStore.set(on)\r\n}\r\n\r\nexport function useZen(): boolean {\r\n return zenStore.use()\r\n}\r\n\r\n/** 左侧文件树是否展开。仅本会话有效:每次进入「学习资料」都从展开态开始(文档列表是入口,不能被记住的\"隐藏\"困住)。 */\r\nexport function getSidebarOpen(): boolean {\r\n return sidebarStore.get()\r\n}\r\n\r\nexport function setSidebarOpen(on: boolean): void {\r\n sidebarStore.set(on)\r\n}\r\n\r\nexport function useSidebarOpen(): boolean {\r\n return sidebarStore.use()\r\n}\r\n\r\n/** 供视图层一次性取齐全部阅读偏好(固定顺序调用,不违反 Hooks 规则)。 */\r\nexport interface ReaderPrefs {\r\n layout: DocLayout\r\n fontStep: number\r\n font: DocFont\r\n leading: DocLeading\r\n measure: DocMeasure\r\n paper: DocPaper\r\n outlineOpen: boolean\r\n zen: boolean\r\n sidebarOpen: boolean\r\n}\r\n\r\nexport function useReaderPrefs(): ReaderPrefs {\r\n return {\r\n layout: layoutStore.use(),\r\n fontStep: fontStepStore.use(),\r\n font: fontStore.use(),\r\n leading: leadingStore.use(),\r\n measure: measureStore.use(),\r\n paper: paperStore.use(),\r\n outlineOpen: outlineStore.use(),\r\n zen: zenStore.use(),\r\n sidebarOpen: sidebarStore.use(),\r\n }\r\n}\r\n","/**\r\n * 每份文档「上次读到哪里」:数据模型、持久化与坐标换算。\r\n *\r\n * 教师诉求原话:「我在阅读知识库的多个文档时,经常在多个文档间切换,请保留每个文档\r\n * 我上次阅读的位置,方便我对照查看。」\r\n *\r\n * 为什么位置不是「一个 scrollTop」:\r\n * · 正文高度随**字号档**(0.9–3.0 十档)、**版心宽度**(四档)、**窗口宽度**、图注是否\r\n * 加载完而变化——同一个 scrollTop 在另一个版式下指向完全不同的段落。这正是\r\n * `annotations.ts` 不肯用节点引用/像素坐标的同一条理由。\r\n * · 因此位置记成 **`anchor`(顶部可见标题的 id)+ `offset`(相对该标题顶端的像素)**:\r\n * 标题 id 由宿主渲染时给出,是同一份源里稳定的锚;像素只负责标题内部的细粒度。\r\n * 改字号、改版心、缩窗口之后仍然回到同一段文字。\r\n * · 再记一个 `progress`(0..1 的滚动进度),只在锚点失效时兜底——文档改版、分段规则\r\n * 变化会让某个标题 id 不再存在,那时按进度落到大致位置,总比回到开头强。\r\n *\r\n * 存储:`localStorage['aero.pos.v1']`,一个键存整库(与 `annotations.ts` 同一条路:\r\n * **按浏览器/机器独立,不跨设备同步**)。键 = 文档键 `<relPath>#<seg>`(复用\r\n * `docKeyOf`):超长文档被宿主切段(`src/docsplit.ts`),各段是独立渲染结果,\r\n * 位置必须分开记,否则「第 2 段的第 1200 像素」会被用到第 1 段上。\r\n *\r\n * 刻意不做的事:\r\n * · 不写「本页目录」里那种跟随高亮的章节目录之外的任何 UI(提示条由 DocViewer 画);\r\n * · 不做跨标签页 storage 事件同步——同一会话不会在两个窗口里同时打开同一文档,\r\n * 而每次写入都从本地最新库开始,最坏情况只是丢掉一次互相覆盖的位置。\r\n */\r\n\r\n// 本模块**零依赖**(不碰 DOM、不引 react、不引别的客户端模块):换算逻辑要能在 node 里\r\n// 直接单测(scripts/tests/reading-pos.test.ts)。位置键由调用方给(DocViewer 用的是标注\r\n// 那套 `<relPath>#<seg>`,唯一真源见 docKey.ts),这里只当作不透明字符串。\r\n\r\n// ---------------------------------------------------------------------------\r\n// 数据模型\r\n// ---------------------------------------------------------------------------\r\n\r\n/** 位置(不含时间戳):章节锚点 + 章内偏移 + 进度。 */\r\nexport interface DocSpot {\r\n /** 顶部可见标题的 id;正文开头还没有标题(如章首摘要区)时为空串。 */\r\n readonly anchor: string\r\n /** 相对标题顶端的像素(>=0);`anchor` 为空时退化为纯 scrollTop。 */\r\n readonly offset: number\r\n /** 0..1 的阅读进度(scrollTop / 可滚高度),锚点失效时兜底。 */\r\n readonly progress: number\r\n /** 保存时该标题的文字(提示条文案用),没有标题时为空串。 */\r\n readonly label: string\r\n}\r\n\r\n/** 落库的位置:位置 + 保存时间。 */\r\nexport interface DocPos extends DocSpot {\r\n /** 保存时间(ms,`Date.now()`)。 */\r\n readonly at: number\r\n}\r\n\r\n/**\r\n * 一个标题在**内容坐标**(= 滚动条坐标系)里的顶端位置。\r\n *\r\n * 为什么由调用方量好再传进来:本模块保持零 DOM 依赖,换算逻辑可以单测\r\n * (`scripts/tests/reading-pos.test.ts`),而量矩形是视图层的事。\r\n */\r\nexport interface HeadingMark {\r\n readonly id: string\r\n /** 标题文字(已压掉多余空白的纯文本)。 */\r\n readonly text: string\r\n /** 标题顶端相对内容顶端的像素。 */\r\n readonly top: number\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// 持久化(localStorage,单键整库)\r\n// ---------------------------------------------------------------------------\r\n\r\nconst STORE_KEY = 'aero.pos.v1'\r\n\r\n/**\r\n * 最多保留多少份文档的位置。\r\n *\r\n * 知识库有 1500+ 个文件,理论上可以全记,但 localStorage 是共享配额(同源 5MB 量级,\r\n * 本插件已有标注库占着)。位置记录只有一两百字节,400 份 ≈ 80KB,够用;\r\n * 超出的按「最久没读」淘汰——被淘汰的文档下次打开回到开头,与从没读过一致。\r\n */\r\nconst MAX_DOCS = 400\r\n\r\ninterface Database {\r\n readonly v: 1\r\n readonly docs: Record<string, DocPos>\r\n}\r\n\r\nfunction emptyDb(): Database {\r\n return { v: 1, docs: {} }\r\n}\r\n\r\nfunction finiteOr(value: unknown, fallback: number): number {\r\n return typeof value === 'number' && Number.isFinite(value) ? value : fallback\r\n}\r\n\r\n/** 逐条净化:手改过/旧版本的数据不能让整库报废(一条坏数据只丢它自己)。 */\r\nfunction sanitize(raw: unknown): DocPos | null {\r\n if (typeof raw !== 'object' || raw === null) return null\r\n const p = raw as Record<string, unknown>\r\n if (typeof p.anchor !== 'string') return null\r\n const anchor = p.anchor\r\n // id 只会是渲染器给出的 `_section_N` / `sec-…` 一类短标识;超长的一律当作脏数据。\r\n if (anchor.length > 200) return null\r\n const offset = Math.max(0, finiteOr(p.offset, 0))\r\n const progress = Math.min(1, Math.max(0, finiteOr(p.progress, 0)))\r\n return {\r\n anchor,\r\n offset,\r\n progress,\r\n label: typeof p.label === 'string' ? p.label.slice(0, 160) : '',\r\n at: Math.max(0, finiteOr(p.at, 0)),\r\n }\r\n}\r\n\r\nfunction loadDb(): Database {\r\n try {\r\n const raw = window.localStorage.getItem(STORE_KEY)\r\n if (raw === null) return emptyDb()\r\n const parsed: unknown = JSON.parse(raw)\r\n if (typeof parsed !== 'object' || parsed === null) return emptyDb()\r\n const docsRaw = (parsed as { docs?: unknown }).docs\r\n if (typeof docsRaw !== 'object' || docsRaw === null) return emptyDb()\r\n const docs: Record<string, DocPos> = {}\r\n for (const [key, value] of Object.entries(docsRaw as Record<string, unknown>)) {\r\n const pos = sanitize(value)\r\n if (pos !== null) docs[key] = pos\r\n }\r\n return { v: 1, docs }\r\n } catch {\r\n /* 隐私模式 / 数据损坏:从空库开始(不覆盖磁盘上的坏数据,等下一次写入再修) */\r\n return emptyDb()\r\n }\r\n}\r\n\r\nlet db: Database = loadDb()\r\n\r\nfunction persist(): void {\r\n try {\r\n window.localStorage.setItem(STORE_KEY, JSON.stringify(db))\r\n } catch {\r\n /* 配额满 / 隐私模式:本次会话仍可用(内存里已更新) */\r\n }\r\n}\r\n\r\n/** 超过上限时按 `at` 从旧到新淘汰。只在写入路径调用(读路径不改库)。 */\r\nfunction prune(records: Record<string, DocPos>): Record<string, DocPos> {\r\n const keys = Object.keys(records)\r\n if (keys.length <= MAX_DOCS) return records\r\n const doomed = keys\r\n .sort((a, b) => (records[a]?.at ?? 0) - (records[b]?.at ?? 0))\r\n .slice(0, keys.length - MAX_DOCS)\r\n const next: Record<string, DocPos> = { ...records }\r\n for (const key of doomed) delete next[key]\r\n return next\r\n}\r\n\r\n/** 取某文档上次的位置;没读过返回 null。 */\r\nexport function loadPos(key: string): DocPos | null {\r\n return db.docs[key] ?? null\r\n}\r\n\r\n/** 记下某文档的位置(每次滚动节流后写一次)。 */\r\nexport function savePos(key: string, pos: DocPos): void {\r\n db = { v: 1, docs: prune({ ...db.docs, [key]: pos }) }\r\n persist()\r\n}\r\n\r\n/** 忘掉某文档的位置(「从头读」)。 */\r\nexport function clearPos(key: string): void {\r\n if (db.docs[key] === undefined) return\r\n const next = { ...db.docs }\r\n delete next[key]\r\n db = { v: 1, docs: next }\r\n persist()\r\n}\r\n\r\n/** 已记录位置的文档数(自检/调试用)。 */\r\nexport function positionCount(): number {\r\n return Object.keys(db.docs).length\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// 坐标换算(纯函数,可单测)\r\n// ---------------------------------------------------------------------------\r\n\r\n/** 低于这个像素量就认为「还在开头」:不弹提示、也不做恢复(打开新文档不该打扰人)。 */\r\nexport const RESUME_MIN_PX = 28\r\n\r\nfunction clamp(value: number, min: number, max: number): number {\r\n return Math.min(max, Math.max(min, value))\r\n}\r\n\r\nfunction scrollableRange(scrollHeight: number, clientHeight: number): number {\r\n return Math.max(0, scrollHeight - clientHeight)\r\n}\r\n\r\n/**\r\n * 当前位置 → `DocSpot`。\r\n *\r\n * `headings` 必须按文档顺序给(`top` 递增):命中「顶端已越过视口上沿的最后一个标题」,\r\n * 循环一越过就 break,所以深处的文档也不会每次都扫完几百个标题。\r\n */\r\nexport function positionAt(\r\n headings: readonly HeadingMark[],\r\n scrollTop: number,\r\n scrollHeight: number,\r\n clientHeight: number,\r\n): DocSpot {\r\n const max = scrollableRange(scrollHeight, clientHeight)\r\n const top = clamp(scrollTop, 0, max)\r\n let anchor = ''\r\n let offset = top\r\n let label = ''\r\n for (const h of headings) {\r\n // +0.5px 容差:标题正好贴在视口上沿时(矩形是分数像素、scrollTop 是整数)也算命中,\r\n // 否则「标题已在最上面」会被记成上一节的末尾(提示条里的章节名会差一节)。\r\n // 容差刻意小于 1px:整数位置上的 positionAt→targetTop 往返是**严格恒等**。\r\n if (h.top > top + 0.5) break\r\n anchor = h.id\r\n offset = Math.max(0, top - h.top)\r\n label = h.text\r\n }\r\n return { anchor, offset, progress: max === 0 ? 0 : clamp(top / max, 0, 1), label }\r\n}\r\n\r\n/**\r\n * `DocSpot` → scrollTop。\r\n *\r\n * 锚点存在就按「标题顶端 + 章内偏移」还原(改字号/版心后依然指向同一段文字);\r\n * 锚点不存在(文档改版、切段规则变化)则按进度落到大致位置。\r\n */\r\nexport function targetTop(\r\n spot: DocSpot,\r\n headings: readonly HeadingMark[],\r\n scrollHeight: number,\r\n clientHeight: number,\r\n): number {\r\n const max = scrollableRange(scrollHeight, clientHeight)\r\n if (spot.anchor !== '') {\r\n const hit = headings.find((h) => h.id === spot.anchor)\r\n if (hit !== undefined) return clamp(hit.top + spot.offset, 0, max)\r\n }\r\n return clamp(spot.progress * max, 0, max)\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// 提示条文案\r\n// ---------------------------------------------------------------------------\r\n\r\n/** 保存时间 → 人话(「3 分钟前」「昨天」「12 天前」);提示条用,不参与逻辑。 */\r\nexport function describeAge(at: number, now: number = Date.now()): string {\r\n const minutes = Math.floor(Math.max(0, now - at) / 60_000)\r\n if (minutes < 1) return '刚刚'\r\n if (minutes < 60) return `${String(minutes)} 分钟前`\r\n const hours = Math.floor(minutes / 60)\r\n if (hours < 24) return `${String(hours)} 小时前`\r\n const days = Math.floor(hours / 24)\r\n if (days === 1) return '昨天'\r\n if (days < 30) return `${String(days)} 天前`\r\n const months = Math.floor(days / 30)\r\n if (months < 12) return `${String(months)} 个月前`\r\n return `${String(Math.floor(months / 12))} 年前`\r\n}\r\n","/**\r\n * 文档键 / 课件键:**标注**(`annotations.ts`)与**阅读位置**(`readingPos.ts`)共用。\r\n *\r\n * 单独成文件的两个理由:\r\n * · 键是「同一个东西」——标注挂在 `<relPath>#<seg>` 上,阅读位置也挂在它上面;\r\n * 两边各写一遍 key 的拼法,迟早会出现「标注在第 2 段、位置落在第 1 段」的漂移。\r\n * · 本模块**零依赖**(不碰 DOM、不引 react),因此纯函数可以像 `docEnhance.ts` 一样\r\n * 在 node 里直接单测(`scripts/tests/reading-pos.test.ts`);`annotations.ts` 在模块\r\n * 初始化时会读 localStorage,把它当作键的唯一来源会绑死测试环境。\r\n */\r\n\r\n/**\r\n * 文档键:`<relPath>#<seg>`。\r\n *\r\n * 为什么带段号:超长文档被宿主切段(src/docsplit.ts),每段是独立渲染结果,\r\n * 段内偏移与别段没有可比性;带段号才能保证「第 3 段的第 120 字」永远指同一处。\r\n */\r\nexport function docKeyOf(relPath: string, seg: number): string {\r\n return seg > 0 ? `${relPath}#${String(seg)}` : relPath\r\n}\r\n\r\n/** 课件键:与文档区分开,避免和同名 md 撞车。 */\r\nexport function deckKeyOf(relPath: string): string {\r\n return `deck:${relPath}`\r\n}\r\n\r\n/** 键 → 人类可读标签(导出与面板标题用)。 */\r\nexport function labelOfKey(key: string): string {\r\n if (key.startsWith('deck:')) return key.slice('deck:'.length)\r\n const hash = key.lastIndexOf('#')\r\n if (hash > 0 && /^\\d+$/.test(key.slice(hash + 1))) return key.slice(0, hash)\r\n return key\r\n}\r\n","/**\r\n * 阅读标注(荧光笔 / 重点线 / 便签提问):数据模型、持久化与正文锚定。\r\n *\r\n * 学生诉求:读知识库与课件时想「像微信读书那样」把重点用几种荧光色标出来、画一条\r\n * 重点线、对不懂的地方写一句自己的提问。老师端因此要能看见这些标记并一键拿去问 AI。\r\n *\r\n * 为什么锚点做成「字符偏移 + 原文 + 前后文」三元组:\r\n * · 正文每次打开都由宿主重新渲染(asciidoctor / markdown-it),DOM 节点不稳定,\r\n * 不能存节点引用或 CSS 路径;\r\n * · 偏移在**同一份渲染结果**内是稳定的(渲染是确定性的:同一份源、同一个渲染器、\r\n * 同一套客户端增强 → 同一个文本),直接命中即可;\r\n * · 文档改版导致偏移错位时,用原文 + 前后文重新定位(模糊兜底);\r\n * 定位不到的标注**不删除**,只在控制台告警——学生的笔记不能被静默吞掉。\r\n *\r\n * 坐标系的定义:正文根节点(`.aero-doc-body`)内**所有文本节点**按文档序拼接成的\r\n * 字符串。刻意不排除公式(KaTeX)与代码块的文本:`Range.toString()` 的语义正是\r\n * 「范围内所有文本节点的 data 顺序拼接」,只有让索引与它逐字对齐,落点才不会漂。\r\n * 公式内部不参与**绘制**(见 canPaint),免得破坏 KaTeX 的字距;标注仍会记下来、\r\n * 在面板里能看见,只是那几段字形本身不上色。\r\n */\r\n\r\nimport { useSyncExternalStore } from 'react'\r\n\r\n// ---------------------------------------------------------------------------\r\n// 数据模型\r\n// ---------------------------------------------------------------------------\r\n\r\n/** 荧光笔颜色(与 doc-theme.css 的 --aero-mark-* 一一对应)。 */\r\nexport const ANNO_COLORS = ['yellow', 'green', 'blue', 'pink'] as const\r\nexport type AnnoColor = (typeof ANNO_COLORS)[number]\r\n\r\n/** 颜色中文名(按钮 title / 面板文案)。 */\r\nexport const ANNO_COLOR_LABEL: Readonly<Record<AnnoColor, string>> = {\r\n yellow: '荧光黄',\r\n green: '荧光绿',\r\n blue: '荧光蓝',\r\n pink: '荧光粉',\r\n}\r\n\r\n/** 标注形态:荧光笔底纹 / 重点线(下划线)。 */\r\nexport type AnnoStyle = 'highlight' | 'underline'\r\n\r\n/** 一条标注。`page` 只对课件有意义(1 起),文档一律 0。 */\r\nexport interface Annotation {\r\n readonly id: string\r\n /** 正文纯文本起点(含)。 */\r\n readonly start: number\r\n /** 正文纯文本终点(不含)。 */\r\n readonly end: number\r\n /** 选中的原文(重新定位的依据)。 */\r\n readonly quote: string\r\n /** 原文前若干字(消歧)。 */\r\n readonly prefix: string\r\n /** 原文后若干字(消歧)。 */\r\n readonly suffix: string\r\n readonly color: AnnoColor\r\n readonly style: AnnoStyle\r\n /** 自己的想法 / 提问;空串表示只是标记。 */\r\n readonly note: string\r\n readonly page: number\r\n readonly createdAt: number\r\n readonly updatedAt: number\r\n}\r\n\r\n/** 新建标注时由调用方给出的字段。 */\r\nexport type AnnotationInit = Omit<Annotation, 'id' | 'createdAt' | 'updatedAt'>\r\n\r\n/** 一次选区落成的锚点(尚未落库)。 */\r\nexport interface AnnoAnchor {\r\n readonly start: number\r\n readonly end: number\r\n readonly quote: string\r\n readonly prefix: string\r\n readonly suffix: string\r\n}\r\n\r\n/** 可修改的字段(改色 / 切换形态 / 改便签)。 */\r\nexport interface AnnotationPatch {\r\n readonly color?: AnnoColor\r\n readonly style?: AnnoStyle\r\n readonly note?: string\r\n}\r\n\r\n/** 上下文长度(前缀/后缀各取多少字)。 */\r\nconst CONTEXT_CHARS = 24\r\n\r\n/** 单条标注最长可标注字数(超过基本是误选整篇)。 */\r\nexport const MAX_QUOTE_CHARS = 2400\r\n\r\n// ---------------------------------------------------------------------------\r\n// 文档键\r\n//\r\n// 键的拼法(`<relPath>#<seg>` / `deck:<relPath>`)住在 `docKey.ts`:阅读位置用的是同一套\r\n// 键,两处各写一遍迟早会漂移。这里原样转发,调用方(DocViewer / SlidevDeckViewer 等)\r\n// 不必改导入路径。\r\n// ---------------------------------------------------------------------------\r\n\r\nimport { deckKeyOf, docKeyOf, labelOfKey } from './docKey.js'\r\n\r\nexport { deckKeyOf, docKeyOf, labelOfKey }\r\n\r\n// ---------------------------------------------------------------------------\r\n// 持久化(localStorage,单键整库 + 订阅)\r\n// ---------------------------------------------------------------------------\r\n\r\nconst STORE_KEY = 'aero.anno.v1'\r\n\r\ninterface Database {\r\n readonly v: 1\r\n readonly docs: Record<string, Annotation[]>\r\n}\r\n\r\nfunction emptyDb(): Database {\r\n return { v: 1, docs: {} }\r\n}\r\n\r\nfunction isColor(value: unknown): value is AnnoColor {\r\n return typeof value === 'string' && (ANNO_COLORS as readonly string[]).includes(value)\r\n}\r\n\r\n/** 逐条净化:旧版本/手改过的数据不能让整库报废(一条坏数据只丢它自己)。 */\r\nfunction sanitize(raw: unknown): Annotation | null {\r\n if (typeof raw !== 'object' || raw === null) return null\r\n const a = raw as Record<string, unknown>\r\n const id = typeof a.id === 'string' && a.id !== '' ? a.id : null\r\n const quote = typeof a.quote === 'string' ? a.quote : null\r\n if (id === null || quote === null || quote === '') return null\r\n const start = typeof a.start === 'number' && Number.isFinite(a.start) ? Math.max(0, Math.floor(a.start)) : 0\r\n const end = typeof a.end === 'number' && Number.isFinite(a.end) ? Math.max(start, Math.floor(a.end)) : start + quote.length\r\n return {\r\n id,\r\n start,\r\n end,\r\n quote,\r\n prefix: typeof a.prefix === 'string' ? a.prefix : '',\r\n suffix: typeof a.suffix === 'string' ? a.suffix : '',\r\n color: isColor(a.color) ? a.color : 'yellow',\r\n style: a.style === 'underline' ? 'underline' : 'highlight',\r\n note: typeof a.note === 'string' ? a.note : '',\r\n page: typeof a.page === 'number' && Number.isFinite(a.page) ? Math.max(0, Math.floor(a.page)) : 0,\r\n createdAt: typeof a.createdAt === 'number' ? a.createdAt : Date.now(),\r\n updatedAt: typeof a.updatedAt === 'number' ? a.updatedAt : Date.now(),\r\n }\r\n}\r\n\r\nfunction loadDb(): Database {\r\n try {\r\n const raw = window.localStorage.getItem(STORE_KEY)\r\n if (raw === null) return emptyDb()\r\n const parsed: unknown = JSON.parse(raw)\r\n if (typeof parsed !== 'object' || parsed === null) return emptyDb()\r\n const docsRaw = (parsed as { docs?: unknown }).docs\r\n if (typeof docsRaw !== 'object' || docsRaw === null) return emptyDb()\r\n const docs: Record<string, Annotation[]> = {}\r\n for (const [key, list] of Object.entries(docsRaw as Record<string, unknown>)) {\r\n if (!Array.isArray(list)) continue\r\n const clean: Annotation[] = []\r\n for (const item of list) {\r\n const anno = sanitize(item)\r\n if (anno !== null) clean.push(anno)\r\n }\r\n if (clean.length > 0) docs[key] = clean.sort((x, y) => x.start - y.start)\r\n }\r\n return { v: 1, docs }\r\n } catch {\r\n /* 隐私模式 / 数据损坏:从空库开始(不覆盖磁盘上的坏数据,等下一次写入再修) */\r\n return emptyDb()\r\n }\r\n}\r\n\r\nlet db: Database = loadDb()\r\nconst listeners = new Set<() => void>()\r\n/** 每个文档键的只读数组缓存:useSyncExternalStore 要求同一状态返回同一引用。 */\r\nconst snapshots = new Map<string, readonly Annotation[]>()\r\n\r\nfunction persist(): void {\r\n try {\r\n window.localStorage.setItem(STORE_KEY, JSON.stringify(db))\r\n } catch {\r\n /* 配额满 / 隐私模式:本次会话仍可用(内存里已更新) */\r\n }\r\n}\r\n\r\nfunction emit(): void {\r\n snapshots.clear()\r\n for (const fn of listeners) fn()\r\n}\r\n\r\nfunction subscribe(fn: () => void): () => void {\r\n listeners.add(fn)\r\n return () => {\r\n listeners.delete(fn)\r\n }\r\n}\r\n\r\nfunction snapshot(doc: string): readonly Annotation[] {\r\n const cached = snapshots.get(doc)\r\n if (cached !== undefined) return cached\r\n const list = db.docs[doc] ?? []\r\n snapshots.set(doc, list)\r\n return list\r\n}\r\n\r\n/** 跨标签页/窗口同步(同一浏览器开了两个「学习资料」时,一边标注另一边也刷新)。 */\r\nif (typeof window !== 'undefined') {\r\n window.addEventListener('storage', (e) => {\r\n if (e.key !== STORE_KEY) return\r\n db = loadDb()\r\n emit()\r\n })\r\n}\r\n\r\n/** 某文档的全部标注(按正文位置排序)。 */\r\nexport function annotationsOf(doc: string): readonly Annotation[] {\r\n return snapshot(doc)\r\n}\r\n\r\n/** 订阅某文档的标注(组件内使用)。 */\r\nexport function useAnnotations(doc: string): readonly Annotation[] {\r\n return useSyncExternalStore(\r\n subscribe,\r\n () => snapshot(doc),\r\n () => snapshot(doc),\r\n )\r\n}\r\n\r\n/** 全库标注总数(工具栏徽标)。 */\r\nexport function totalAnnotationCount(): number {\r\n let total = 0\r\n for (const list of Object.values(db.docs)) total += list.length\r\n return total\r\n}\r\n\r\nfunction newId(): string {\r\n return `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`\r\n}\r\n\r\n/** 新增一条标注;返回落库后的完整记录。 */\r\nexport function addAnnotation(doc: string, init: AnnotationInit): Annotation {\r\n const now = Date.now()\r\n const anno: Annotation = { ...init, id: newId(), createdAt: now, updatedAt: now }\r\n const list = db.docs[doc] ?? []\r\n // 与已有标注完全相同的一段(同起止同形态)只保留一条:避免双击弹出两个色块。\r\n const dup = list.find((a) => a.start === anno.start && a.end === anno.end && a.style === anno.style)\r\n const next = dup === undefined ? [...list, anno] : list.map((a) => (a.id === dup.id ? { ...a, ...init, updatedAt: now } : a))\r\n db = { v: 1, docs: { ...db.docs, [doc]: next.sort((x, y) => x.start - y.start) } }\r\n persist()\r\n emit()\r\n return dup === undefined ? anno : { ...dup, ...init, updatedAt: now }\r\n}\r\n\r\n/** 合并到已有或新建:给定同一段文字已有标注时改它,没有才新建(取色点两次不会叠两条)。 */\r\nexport function paintAnnotation(doc: string, anchor: AnnoAnchor, color: AnnoColor, style: AnnoStyle, note: string): Annotation {\r\n const existing = snapshot(doc).find((a) => a.start === anchor.start && a.end === anchor.end && a.quote === anchor.quote)\r\n if (existing !== undefined) {\r\n updateAnnotation(doc, existing.id, { color, style })\r\n return { ...existing, color, style }\r\n }\r\n return addAnnotation(doc, { ...anchor, color, style, note, page: 0 })\r\n}\r\n\r\n/**\r\n * 课件标注:按「页 + 原文」去重后落库。\r\n *\r\n * 课件没有稳定的字符偏移坐标系(翻页时整页内容被替换),因此 start/end 只做占位,\r\n * 定位完全靠 `page` 与 `quote`(见 SlidevDeckViewer 的 findQuoteRects)。\r\n */\r\nexport function addPageAnnotation(\r\n doc: string,\r\n page: number,\r\n quote: string,\r\n color: AnnoColor,\r\n style: AnnoStyle,\r\n note: string,\r\n): Annotation {\r\n const needle = quote.replace(/\\s+/g, ' ').trim()\r\n const existing = snapshot(doc).find(\r\n (a) => a.page === page && a.style === style && a.quote.replace(/\\s+/g, ' ').trim() === needle,\r\n )\r\n if (existing !== undefined) {\r\n updateAnnotation(doc, existing.id, { color, ...(note !== '' ? { note } : {}) })\r\n return { ...existing, color, ...(note !== '' ? { note } : {}) }\r\n }\r\n return addAnnotation(doc, {\r\n start: 0,\r\n end: needle.length,\r\n quote: needle,\r\n prefix: '',\r\n suffix: '',\r\n color,\r\n style,\r\n note,\r\n page,\r\n })\r\n}\r\n\r\n/** 修改一条标注(改色 / 切换形态 / 改便签)。 */\r\nexport function updateAnnotation(doc: string, id: string, patch: AnnotationPatch): void {\r\n const list = db.docs[doc]\r\n if (list === undefined) return\r\n let touched = false\r\n const next = list.map((a) => {\r\n if (a.id !== id) return a\r\n touched = true\r\n return {\r\n ...a,\r\n ...(patch.color !== undefined ? { color: patch.color } : {}),\r\n ...(patch.style !== undefined ? { style: patch.style } : {}),\r\n ...(patch.note !== undefined ? { note: patch.note } : {}),\r\n updatedAt: Date.now(),\r\n }\r\n })\r\n if (!touched) return\r\n db = { v: 1, docs: { ...db.docs, [doc]: next } }\r\n persist()\r\n emit()\r\n}\r\n\r\n/** 删除一条标注。 */\r\nexport function removeAnnotation(doc: string, id: string): void {\r\n const list = db.docs[doc]\r\n if (list === undefined) return\r\n const next = list.filter((a) => a.id !== id)\r\n const docs = { ...db.docs }\r\n if (next.length === 0) delete docs[doc]\r\n else docs[doc] = next\r\n db = { v: 1, docs }\r\n persist()\r\n emit()\r\n}\r\n\r\n/** 清空某文档的标注;返回清掉几条。 */\r\nexport function clearAnnotations(doc: string): number {\r\n const list = db.docs[doc]\r\n if (list === undefined) return 0\r\n const docs = { ...db.docs }\r\n delete docs[doc]\r\n db = { v: 1, docs }\r\n persist()\r\n emit()\r\n return list.length\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// 导出(Markdown)——学生复习、贴给 AI、或交给老师提问都用这一份\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction colorDot(color: AnnoColor): string {\r\n switch (color) {\r\n case 'yellow': return '🟡'\r\n case 'green': return '🟢'\r\n case 'blue': return '🔵'\r\n case 'pink': return '🩷'\r\n }\r\n}\r\n\r\n/**\r\n * 导出为 Markdown。不传 `docs` 时导出全部文档;`docTitle` 用于把路径写成人类标题。\r\n */\r\nexport function exportMarkdown(\r\n docs?: readonly string[],\r\n titleOf?: (key: string) => string,\r\n): string {\r\n const keys = docs ?? Object.keys(db.docs)\r\n const lines: string[] = ['# 我的阅读标记与提问', '']\r\n let count = 0\r\n for (const key of keys) {\r\n const list = db.docs[key]\r\n if (list === undefined || list.length === 0) continue\r\n const title = titleOf === undefined ? labelOfKey(key) : titleOf(key)\r\n lines.push(`## ${title}`, '')\r\n for (const a of list) {\r\n count++\r\n const where = a.page > 0 ? `(第 ${String(a.page)} 页)` : ''\r\n const body = `${colorDot(a.color)} ${a.style === 'underline' ? '重点线' : '标记'}${where}「${a.quote}」`\r\n lines.push(`${String(count)}. ${body}`)\r\n if (a.note.trim() !== '') lines.push(` - 我的想法:${a.note.trim()}`)\r\n }\r\n lines.push('')\r\n }\r\n if (count === 0) lines.push('(还没有标记。选中正文 → 取一种荧光色、画重点线,或写一句自己的提问。)')\r\n return lines.join('\\n')\r\n}\r\n\r\n/** 面板里每条标记的一行摘要(去掉多余空白,长引文截断)。 */\r\nexport function summarizeQuote(quote: string, max = 120): string {\r\n const flat = quote.replace(/\\s+/g, ' ').trim()\r\n return flat.length <= max ? flat : `${flat.slice(0, max)}…`\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// 正文文本索引(偏移坐标系)\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface TextEntry {\r\n readonly node: Text\r\n readonly start: number\r\n}\r\n\r\n/** 正文纯文本索引:`text` 与 `entries` 逐字对齐(= Range.toString() 的坐标系)。 */\r\nexport interface TextIndex {\r\n readonly text: string\r\n readonly entries: readonly TextEntry[]\r\n}\r\n\r\n/** 建索引:按文档序收所有文本节点(含公式/代码里的),保证与 Range.toString() 一致。 */\r\nexport function buildTextIndex(root: Node): TextIndex {\r\n const entries: TextEntry[] = []\r\n const parts: string[] = []\r\n let total = 0\r\n const visit = (node: Node): void => {\r\n if (node.nodeType === 3) {\r\n const t = node as Text\r\n const v = t.nodeValue ?? ''\r\n entries.push({ node: t, start: total })\r\n parts.push(v)\r\n total += v.length\r\n return\r\n }\r\n if (node.nodeType !== 1) return\r\n for (const child of Array.from(node.childNodes)) visit(child)\r\n }\r\n visit(root)\r\n return { text: parts.join(''), entries }\r\n}\r\n\r\n/** 文本里某个偏移 → 前缀/后缀(截断到 CONTEXT_CHARS,跨空白归一为单空格)。 */\r\nfunction contextAround(text: string, start: number, end: number): { prefix: string; suffix: string } {\r\n const prefix = text.slice(Math.max(0, start - CONTEXT_CHARS), start).replace(/\\s+/g, ' ')\r\n const suffix = text.slice(end, end + CONTEXT_CHARS).replace(/\\s+/g, ' ')\r\n return { prefix, suffix }\r\n}\r\n\r\n/**\r\n * 把一次 DOM 选区落成锚点。\r\n *\r\n * 偏移用两个 Range 的 `toString().length` 求(`selectNodeContents(root)` 起点 → 选区边界),\r\n * 这样无论边界落在文本节点还是元素节点(三击选整段就是后者)都得到同一个坐标系,\r\n * 不必自己走边界点。\r\n */\r\nexport function anchorFromRange(root: HTMLElement, range: Range): AnnoAnchor | null {\r\n if (range.collapsed) return null\r\n const index = buildTextIndex(root)\r\n const probe = document.createRange()\r\n probe.selectNodeContents(root)\r\n try {\r\n probe.setEnd(range.startContainer, range.startOffset)\r\n } catch {\r\n return null\r\n }\r\n const start = probe.toString().length\r\n try {\r\n probe.setEnd(range.endContainer, range.endOffset)\r\n } catch {\r\n return null\r\n }\r\n const end = probe.toString().length\r\n if (end <= start) return null\r\n if (end - start > MAX_QUOTE_CHARS) return null\r\n const quote = index.text.slice(start, end)\r\n if (quote.trim() === '') return null\r\n const { prefix, suffix } = contextAround(index.text, start, end)\r\n return { start, end, quote, prefix, suffix }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// 绘制:把标注落到 DOM(<mark class=\"aero-anno\">)\r\n// ---------------------------------------------------------------------------\r\n\r\n/** 绘制结果(供 UI 徽标/边注圆点使用)。 */\r\nexport interface PaintResult {\r\n /** 落笔成功的标注 id(按文档序)。 */\r\n readonly painted: readonly string[]\r\n /** 偏移失效且按原文也找不回来的标注 id。 */\r\n readonly unresolved: readonly string[]\r\n}\r\n\r\n/** 该文本节点所在的元素是否允许落笔(公式内部不画,免得破坏 KaTeX 字距)。 */\r\nfunction canPaint(node: Text): boolean {\r\n const parent = node.parentElement\r\n if (parent === null) return false\r\n if (parent.closest('.katex, script, style, textarea, svg') !== null) return false\r\n return true\r\n}\r\n\r\n/** 摘掉上一轮绘制的 <mark>,把文本还回去(幂等绘制的前置步骤)。 */\r\nexport function clearPainted(root: HTMLElement): void {\r\n const marks = Array.from(root.querySelectorAll<HTMLElement>('mark.aero-anno'))\r\n if (marks.length === 0) return\r\n const parents = new Set<Node>()\r\n for (const mark of marks) {\r\n const parent = mark.parentNode\r\n if (parent === null) continue\r\n while (mark.firstChild !== null) parent.insertBefore(mark.firstChild, mark)\r\n parent.removeChild(mark)\r\n parents.add(parent)\r\n }\r\n for (const parent of parents) {\r\n if (parent.nodeType === 1) (parent as Element).normalize()\r\n }\r\n}\r\n\r\n/** 公共前后文长度(模糊定位打分)。 */\r\nfunction commonSuffixLength(a: string, b: string): number {\r\n let n = 0\r\n const max = Math.min(a.length, b.length)\r\n while (n < max && a[a.length - 1 - n] === b[b.length - 1 - n]) n++\r\n return n\r\n}\r\n\r\nfunction commonPrefixLength(a: string, b: string): number {\r\n let n = 0\r\n const max = Math.min(a.length, b.length)\r\n while (n < max && a[n] === b[n]) n++\r\n return n\r\n}\r\n\r\n/** 偏移失效时按「原文 + 前后文」重新定位;找不到返回 null。 */\r\nfunction relocate(text: string, anno: Annotation): readonly [number, number] | null {\r\n if (anno.quote === '') return null\r\n let best: { start: number; score: number } | null = null\r\n let from = 0\r\n let tries = 0\r\n while (tries < 400) {\r\n const at = text.indexOf(anno.quote, from)\r\n if (at < 0) break\r\n tries++\r\n const before = text.slice(Math.max(0, at - anno.prefix.length), at)\r\n const after = text.slice(at + anno.quote.length, at + anno.quote.length + anno.suffix.length)\r\n const score = commonSuffixLength(before, anno.prefix) + commonPrefixLength(after, anno.suffix)\r\n if (best === null || score > best.score) best = { start: at, score }\r\n from = at + 1\r\n }\r\n return best === null ? null : [best.start, best.start + anno.quote.length]\r\n}\r\n\r\ninterface Resolved {\r\n readonly anno: Annotation\r\n readonly start: number\r\n readonly end: number\r\n}\r\n\r\n/** 把每条标注解析成当前文本里的 [start, end)(偏移命中优先,否则按原文重定位)。 */\r\nfunction resolveAll(annos: readonly Annotation[], text: string): { resolved: Resolved[]; unresolved: string[] } {\r\n const resolved: Resolved[] = []\r\n const unresolved: string[] = []\r\n for (const anno of annos) {\r\n const { start, end, quote } = anno\r\n if (start >= 0 && end <= text.length && end > start && text.slice(start, end) === quote) {\r\n resolved.push({ anno, start, end })\r\n continue\r\n }\r\n const found = relocate(text, anno)\r\n if (found === null) {\r\n unresolved.push(anno.id)\r\n continue\r\n }\r\n resolved.push({ anno, start: found[0], end: found[1] })\r\n }\r\n return { resolved, unresolved }\r\n}\r\n\r\nfunction makeMark(res: Resolved, chunk: string): HTMLElement {\r\n const mark = document.createElement('mark')\r\n mark.className = 'aero-anno'\r\n mark.dataset.anno = res.anno.id\r\n mark.dataset.color = res.anno.color\r\n mark.dataset.style = res.anno.style\r\n if (res.anno.note.trim() !== '') mark.dataset.noted = '1'\r\n mark.setAttribute('title', res.anno.note.trim() === '' ? '点击:改色 / 写想法' : `我的想法:${res.anno.note.trim()}`)\r\n mark.textContent = chunk\r\n return mark\r\n}\r\n\r\n/**\r\n * 绘制全部标注。**幂等**:先摘掉旧 mark 再按当前文本重画。\r\n *\r\n * 同一段文字被多条标注覆盖时,**先建的那条占位**(后来的只画在剩余字符上):\r\n * 叠加两种荧光色会变成脏色,且删除时无法判断该摘哪一层。\r\n */\r\nexport function paintAnnotations(root: HTMLElement, annos: readonly Annotation[]): PaintResult {\r\n clearPainted(root)\r\n if (annos.length === 0) return { painted: [], unresolved: [] }\r\n const index = buildTextIndex(root)\r\n const { resolved, unresolved } = resolveAll(annos, index.text)\r\n if (resolved.length === 0) return { painted: [], unresolved }\r\n\r\n // 先建者优先:按创建时间排序后依次占位。\r\n const order = resolved.slice().sort((a, b) => a.anno.createdAt - b.anno.createdAt)\r\n const painted = new Set<string>()\r\n\r\n for (const entry of index.entries) {\r\n const raw = entry.node.nodeValue ?? ''\r\n if (raw === '') continue\r\n const nodeStart = entry.start\r\n const nodeEnd = nodeStart + raw.length\r\n // owner[i] = 覆盖该字符的标注在 order 里的下标(-1 = 无)\r\n let owner: Int32Array | null = null\r\n for (let k = 0; k < order.length; k++) {\r\n const res = order[k]\r\n if (res === undefined) continue\r\n const s = Math.max(nodeStart, res.start)\r\n const e = Math.min(nodeEnd, res.end)\r\n if (e <= s) continue\r\n if (owner === null) owner = new Int32Array(raw.length).fill(-1)\r\n for (let i = s - nodeStart; i < e - nodeStart; i++) {\r\n if (owner[i] === -1) owner[i] = k\r\n }\r\n painted.add(res.anno.id)\r\n }\r\n if (owner === null || !canPaint(entry.node)) continue\r\n\r\n const frag = document.createDocumentFragment()\r\n let pos = 0\r\n while (pos < raw.length) {\r\n const owned = owner[pos] ?? -1\r\n let next = pos + 1\r\n while (next < raw.length && (owner[next] ?? -1) === owned) next++\r\n const chunk = raw.slice(pos, next)\r\n if (owned < 0) {\r\n frag.appendChild(document.createTextNode(chunk))\r\n } else {\r\n const res = order[owned]\r\n if (res === undefined) frag.appendChild(document.createTextNode(chunk))\r\n else frag.appendChild(makeMark(res, chunk))\r\n }\r\n pos = next\r\n }\r\n const parent = entry.node.parentNode\r\n if (parent !== null) parent.replaceChild(frag, entry.node)\r\n }\r\n\r\n // 只画了一部分(例如整段都落在公式里)也算画上了;真正没画上的只有 unresolved。\r\n const paintedList = order.filter((r) => painted.has(r.anno.id)).map((r) => r.anno.id)\r\n return { painted: paintedList, unresolved }\r\n}\r\n\r\n/** 需要闪烁提示的标注(面板「定位」用):给它的 mark 打属性,1.6 s 后摘掉。 */\r\nexport function flashAnnotation(root: HTMLElement, id: string): void {\r\n const marks = Array.from(root.querySelectorAll<HTMLElement>(`mark.aero-anno[data-anno=\"${CSS.escape(id)}\"]`))\r\n if (marks.length === 0) return\r\n for (const mark of marks) mark.dataset.flash = '1'\r\n window.setTimeout(() => {\r\n for (const mark of marks) {\r\n if (mark.isConnected) delete mark.dataset.flash\r\n }\r\n }, 1600)\r\n}\r\n\r\n/** 滚到某条标注(面板「定位」)。 */\r\nexport function scrollToAnnotation(root: HTMLElement, id: string): boolean {\r\n const mark = root.querySelector<HTMLElement>(`mark.aero-anno[data-anno=\"${CSS.escape(id)}\"]`)\r\n if (mark === null) return false\r\n mark.scrollIntoView({ block: 'center', behavior: 'smooth' })\r\n flashAnnotation(root, id)\r\n return true\r\n}\r\n\r\n/** 正文里某条标注的第一个 mark 的视口矩形(弹层定位用)。 */\r\nexport function markRectOf(root: HTMLElement, id: string): DOMRect | null {\r\n const mark = root.querySelector<HTMLElement>(`mark.aero-anno[data-anno=\"${CSS.escape(id)}\"]`)\r\n return mark === null ? null : mark.getBoundingClientRect()\r\n}\r\n\r\n/**\r\n * 文本偏移 → Range(课件页内高亮用:在 iframe 的文档里量选中文字的矩形)。\r\n *\r\n * `doc` 必须是这些文本节点所属的文档——跨文档 createRange 会抛 WrongDocumentError。\r\n */\r\nexport function rangeFromOffsets(index: TextIndex, start: number, end: number, doc: Document): Range | null {\r\n if (start < 0 || end <= start || end > index.text.length) return null\r\n const point = (offset: number): { node: Text; offset: number } | null => {\r\n let last: TextEntry | null = null\r\n for (const entry of index.entries) {\r\n const len = (entry.node.nodeValue ?? '').length\r\n if (offset >= entry.start && offset <= entry.start + len) return { node: entry.node, offset: offset - entry.start }\r\n last = entry\r\n }\r\n return last === null ? null : { node: last.node, offset: (last.node.nodeValue ?? '').length }\r\n }\r\n const from = point(start)\r\n const to = point(end)\r\n if (from === null || to === null) return null\r\n const range = doc.createRange()\r\n try {\r\n range.setStart(from.node, from.offset)\r\n range.setEnd(to.node, to.offset)\r\n } catch {\r\n return null\r\n }\r\n return range\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// 边注圆点:给「有想法」的标注在正文右侧留一个可见入口(微信读书式的批注气泡)\r\n// ---------------------------------------------------------------------------\r\n\r\n/** 一条边注圆点的定位信息(坐标相对滚动容器内容)。 */\r\nexport interface NotePin {\r\n readonly id: string\r\n readonly color: AnnoColor\r\n readonly top: number\r\n readonly left: number\r\n readonly note: string\r\n readonly index: number\r\n}\r\n\r\n/**\r\n * 计算边注圆点位置。\r\n *\r\n * 圆点放在正文纸面的右缘外侧(版心右侧的留白里),纵向对齐它那条标注的首行;\r\n * 同一行有多个圆点时向下让开(最小间距 PIN_GAP),不互相压住。\r\n */\r\nexport function notePins(\r\n root: HTMLElement,\r\n scroller: HTMLElement,\r\n annos: readonly Annotation[],\r\n): NotePin[] {\r\n const noted = annos.filter((a) => a.note.trim() !== '')\r\n if (noted.length === 0) return []\r\n const scrollRect = scroller.getBoundingClientRect()\r\n const rootRect = root.getBoundingClientRect()\r\n const scrollTop = scroller.scrollTop\r\n const scrollLeft = scroller.scrollLeft\r\n const maxLeft = Math.max(8, scroller.clientWidth - 26)\r\n const pins: NotePin[] = []\r\n let index = 0\r\n for (const anno of noted) {\r\n const mark = root.querySelector<HTMLElement>(`mark.aero-anno[data-anno=\"${CSS.escape(anno.id)}\"]`)\r\n if (mark === null) continue\r\n const rect = mark.getBoundingClientRect()\r\n index++\r\n const left = Math.min(maxLeft, rootRect.right - scrollRect.left + scrollLeft + 2)\r\n const top = rect.top - scrollRect.top + scrollTop\r\n pins.push({ id: anno.id, color: anno.color, top, left, note: anno.note.trim(), index })\r\n }\r\n // 纵向避让:从上到下依次推,保证至少 PIN_GAP 的间距\r\n const PIN_GAP = 22\r\n pins.sort((a, b) => a.top - b.top)\r\n let last = Number.NEGATIVE_INFINITY\r\n const spaced = pins.map((pin) => {\r\n const top = Math.max(pin.top, last + PIN_GAP)\r\n last = top\r\n return { ...pin, top }\r\n })\r\n return spaced\r\n}\r\n","/** 统一的内联 SVG 图标(GitHub octicon 风格,16×16 视图框,stroke 1.5)。 */\r\nimport type { ReactNode } from 'react'\r\n\r\ninterface SvgProps {\r\n size?: number\r\n className?: string\r\n}\r\n\r\nfunction Svg({ size = 14, className, children }: SvgProps & { children: ReactNode }): JSX.Element {\r\n return (\r\n <svg\r\n className={className}\r\n width={size}\r\n height={size}\r\n viewBox=\"0 0 16 16\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"1.5\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n aria-hidden=\"true\"\r\n >\r\n {children}\r\n </svg>\r\n )\r\n}\r\n\r\nexport function BranchIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <circle cx=\"4\" cy=\"3.5\" r=\"1.6\" />\r\n <circle cx=\"11.5\" cy=\"3.5\" r=\"1.6\" />\r\n <circle cx=\"4\" cy=\"12.5\" r=\"1.6\" />\r\n <path d=\"M4 5.1v5.8\" />\r\n <path d=\"M11.5 5.1c0 1.7-1.1 2.4-2.7 2.4H7.2\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function PullIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M8 2.5v8\" />\r\n <path d=\"M5 7.5l3 3 3-3\" />\r\n <path d=\"M2.5 13.5h11\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function PushIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M8 13V5\" />\r\n <path d=\"M5 8l3-3 3 3\" />\r\n <path d=\"M2.5 13.5h11\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function FetchIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M13.5 8a5.5 5.5 0 1 1-1.6-3.9\" />\r\n <path d=\"M13.5 2.5V6h-3.5\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function CheckIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M3 8.5l3.2 3.2L13 4.5\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function FolderIcon({ open = false, ...p }: SvgProps & { open?: boolean }): JSX.Element {\r\n return (\r\n <svg\r\n className={p.className}\r\n width={p.size ?? 14}\r\n height={p.size ?? 14}\r\n viewBox=\"0 0 16 16\"\r\n fill=\"currentColor\"\r\n stroke=\"none\"\r\n aria-hidden=\"true\"\r\n >\r\n <path d={open\r\n ? 'M1.5 4.8c0-.55.45-1 1-1h3.1c.3 0 .57.13.76.35L7.7 5.7c.19.22.47.35.76.35h5.04c.55 0 1 .45 1 1v4.15c0 .55-.45 1-1 1H2.5c-.55 0-1-.45-1-1V4.8Z'\r\n : 'M1.5 4.8c0-.55.45-1 1-1h3.1c.3 0 .57.13.76.35L7.7 5.7c.19.22.47.35.76.35h5.04c.55 0 1 .45 1 1V12.2c0 .55-.45 1-1 1H2.5c-.55 0-1-.45-1-1V4.8Z'}\r\n />\r\n </svg>\r\n )\r\n}\r\n\r\nexport function ChevronIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M6 4l4 4-4 4\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function FileIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M4 1.5h5l3.5 3.5v9.5H4z\" />\r\n <path d=\"M9 1.5V5h3.5\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function CopyIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <rect x=\"5.5\" y=\"4.5\" width=\"7\" height=\"8\" rx=\"1\" />\r\n <path d=\"M3.5 2.5h6.5V5\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function RefreshIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M13.5 8a5.5 5.5 0 1 1-1.6-3.9\" />\r\n <path d=\"M13.5 2.5V6h-3.5\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function ExternalIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M7 9l5-5\" />\r\n <path d=\"M8.5 3.5H4A1.5 1.5 0 0 0 2.5 5v7A1.5 1.5 0 0 0 4 13.5h7a1.5 1.5 0 0 0 1.5-1.5V7.5\" />\r\n <path d=\"M9.5 3.5H12v2.5\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function DownloadIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M8 2.5v8\" />\r\n <path d=\"M5 7.5l3 3 3-3\" />\r\n <path d=\"M2.5 13.5h11\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function SigmaIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M12.5 3H5l4.5 5L5 13h7.5\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function CursorIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M4 2.5l7.5 7.5-3.3.6-2.1 2.9-2.1-2.1 2.9-2.1.6-3.3Z\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function MonitorIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <rect x=\"2\" y=\"3\" width=\"12\" height=\"8.5\" rx=\"1\" />\r\n <path d=\"M5.5 14h5M8 11.5V14\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function LinkIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M6.5 9.5l3-3\" />\r\n <path d=\"M4.5 11.5l-.8.8a2.12 2.12 0 0 1-3-3l2.4-2.4a2.12 2.12 0 0 1 3 0\" />\r\n <path d=\"M11.5 4.5l.8-.8a2.12 2.12 0 0 1 3 3l-2.4 2.4a2.12 2.12 0 0 1-3 0\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function ListIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M6 4h7.5M6 8h7.5M6 12h7.5\" />\r\n <path d=\"M3 4h.01M3 8h.01M3 12h.01\" />\r\n </Svg>\r\n )\r\n}\r\n\r\nexport function CloseIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M4 4l8 8M12 4l-8 8\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** 翻开的书(书籍版式)。 */\r\nexport function BookIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M8 3.5C6.7 2.6 5 2.3 2.5 2.5v10c2.5-.2 4.2.1 5.5 1 1.3-.9 3-1.2 5.5-1v-10c-2.5-.2-4.2.1-5.5 1z\" />\r\n <path d=\"M8 3.5v10\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** 文档页(网页版式)。 */\r\nexport function PageIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <rect x=\"3\" y=\"2\" width=\"10\" height=\"12\" rx=\"1.4\" />\r\n <path d=\"M5.5 5.5h5M5.5 8h5M5.5 10.5h3\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** 字号(Aa)——阅读设置入口。 */\r\nexport function TypeIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M1.6 12.4 4.6 4l3 8.4\" />\r\n <path d=\"M2.7 9.6h3.8\" />\r\n <path d=\"M9.4 12.4l1.9-5 1.9 5\" />\r\n <path d=\"M10.1 10.7h2.4\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** 阅读设置(滑杆)。 */\r\nexport function SlidersIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M2 4.5h12M2 11.5h12\" />\r\n <circle cx=\"5.6\" cy=\"4.5\" r=\"1.7\" />\r\n <circle cx=\"10.4\" cy=\"11.5\" r=\"1.7\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** 专注阅读(四角内收的取景框)。 */\r\nexport function ZenIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M2 6V3.6A1.6 1.6 0 0 1 3.6 2H6\" />\r\n <path d=\"M10 2h2.4A1.6 1.6 0 0 1 14 3.6V6\" />\r\n <path d=\"M14 10v2.4a1.6 1.6 0 0 1-1.6 1.6H10\" />\r\n <path d=\"M6 14H3.6A1.6 1.6 0 0 1 2 12.4V10\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** 进入全屏(箭头向四角张开)。 */\r\nexport function ExpandIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M9.6 2H14v4.4\" />\r\n <path d=\"M6.4 14H2V9.6\" />\r\n <path d=\"M14 2 9.7 6.3\" />\r\n <path d=\"M2 14l4.3-4.3\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** 退出全屏(箭头向中心收拢)。 */\r\nexport function ShrinkIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M2 6h4V2\" />\r\n <path d=\"M14 10h-4v4\" />\r\n <path d=\"M6 6 2 2\" />\r\n <path d=\"M10 10l4 4\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** 荧光笔(阅读标注入口)。 */\r\nexport function PenIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M2.1 13.9l.9-3.1 7.6-7.6a1.7 1.7 0 0 1 2.4 0l.8.8a1.7 1.7 0 0 1 0 2.4l-7.6 7.6-3.1.9z\" />\r\n <path d=\"M9.8 3.6l2.6 2.6\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** 重点线(下划线)。 */\r\nexport function UnderlineIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M4.5 2.5v5a3.5 3.5 0 0 0 7 0v-5\" />\r\n <path d=\"M2.5 13.5h11\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** 想法 / 提问(气泡)。 */\r\nexport function ChatIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M2.5 4.2c0-.9.7-1.7 1.7-1.7h7.6c.9 0 1.7.7 1.7 1.7v5c0 .9-.7 1.7-1.7 1.7H7.4L4 13.6V10.9h-.2c-.7 0-1.3-.6-1.3-1.3z\" />\r\n <path d=\"M5.5 6.2h5M5.5 8.4h3.2\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** 删除。 */\r\nexport function TrashIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <path d=\"M2.6 4.4h10.8\" />\r\n <path d=\"M6 4.4V3.1c0-.4.3-.8.8-.8h2.4c.5 0 .8.4.8.8v1.3\" />\r\n <path d=\"M4 4.4l.7 8.4c0 .5.4.9.9.9h4.8c.5 0 .9-.4.9-.9l.7-8.4\" />\r\n <path d=\"M6.6 7v4.2M9.4 7v4.2\" />\r\n </Svg>\r\n )\r\n}\r\n\r\n/** 左侧文件树(带分栏的窗口)。 */\r\nexport function SidebarIcon(p: SvgProps): JSX.Element {\r\n return (\r\n <Svg {...p}>\r\n <rect x=\"1.8\" y=\"3\" width=\"12.4\" height=\"10\" rx=\"1.5\" />\r\n <path d=\"M6.4 3v10\" />\r\n </Svg>\r\n )\r\n}\r\n","/**\n * 由 scripts/gen-css-modules.mjs 从 src/client/styles.module.css 生成,**请勿手改**。\n * 改样式请改源 CSS,然后跑:node scripts/gen-css-modules.mjs\n */\nconst css = \"._0K34_a_root{flex-direction:column;flex:1 1 0;width:100%;min-height:0;display:flex;overflow:hidden}._0K34_a_topbar{background:#7f7f7f0a;border-bottom:1px solid #80808033;flex:none;align-items:center;gap:8px;min-height:33px;padding:4px 10px;font-size:13px;display:flex}._0K34_a_topbarTitle{flex:none;font-size:13px;font-weight:600}._0K34_a_crumbs{flex:1;align-items:center;gap:2px;min-width:0;display:flex;overflow:hidden}._0K34_a_crumb{color:#608cdcf2;white-space:nowrap}._0K34_a_crumbLast{color:inherit;font-weight:600}._0K34_a_crumbSep{color:#7f7f7fb3;flex:none;padding:0 1px}._0K34_a_tbBtn{color:inherit;cursor:pointer;background:0 0;border:1px solid #80808059;border-radius:6px;flex:none;align-items:center;gap:5px;padding:4px 9px;font-size:12px;display:inline-flex}._0K34_a_tbBtn:hover{background:#7f7f7f1f}._0K34_a_tbBtn:focus-visible{border-color:#608cdccc;outline:none}._0K34_a_tweakWrap{flex:none;position:relative}._0K34_a_tweakMenu{z-index:30;background:#fff;border:1px solid #80808059;border-radius:10px;flex-direction:column;gap:2px;width:min(360px,80vw);max-height:60vh;padding:6px;display:flex;position:absolute;top:calc(100% + 6px);right:0;overflow:auto;box-shadow:0 10px 28px #0f19322e}._0K34_a_tweakItem{width:100%;color:inherit;text-align:left;cursor:pointer;background:0 0;border:none;border-radius:6px;align-items:center;gap:8px;padding:5px 8px;font-size:12px;display:flex}._0K34_a_tweakItem:hover:not(:disabled){background:#608cdc1f}._0K34_a_tweakItem:disabled{opacity:.55;cursor:default}._0K34_a_tweakItemId{color:#2a5cb0f2;flex:none;min-width:34px;font-weight:600}._0K34_a_tweakItemTitle{text-overflow:ellipsis;white-space:nowrap;opacity:.85;flex:1;min-width:0;overflow:hidden}._0K34_a_tweakMenuHint{color:#6e6e78e6;padding:4px 8px 2px;font-size:11px}._0K34_a_body{flex:1 1 0;min-height:0;display:flex}._0K34_a_sidebar{background:#7f7f7f0d;border-right:1px solid #80808033;flex-direction:column;flex:none;width:280px;min-height:0;display:flex}._0K34_a_sidebarHeader{border-bottom:1px solid #80808033;flex:none;padding:8px}._0K34_a_search{box-sizing:border-box;width:100%;color:inherit;background:0 0;border:1px solid #80808059;border-radius:6px;padding:6px 10px;font-size:13px}._0K34_a_search:focus{border-color:#608cdccc;outline:none}._0K34_a_tree{flex:1;min-height:0;padding:6px;overflow-y:auto}._0K34_a_group{margin:0}._0K34_a_groupLabel{cursor:pointer;color:inherit;user-select:none;border-radius:5px;align-items:center;gap:5px;padding:5px 6px;font-size:13px;font-weight:600;list-style:none;display:flex}._0K34_a_groupLabel::-webkit-details-marker{display:none}._0K34_a_groupLabel:hover{background:#7f7f7f1f}._0K34_a_chevron{color:#7f7f7fe6;flex:none;transition:transform .12s;display:inline-flex}._0K34_a_group[open]>._0K34_a_groupLabel ._0K34_a_chevron{transform:rotate(90deg)}._0K34_a_groupChildren{border-left:1px solid #80808026;margin-left:9px;padding-left:12px}._0K34_a_leaf{text-align:left;width:100%;color:inherit;cursor:pointer;background:0 0;border:none;border-radius:5px;align-items:center;gap:6px;margin:1px 0;padding:4px 6px;font-size:13px;display:flex;position:relative}._0K34_a_leaf:hover{background:#7f7f7f1f}._0K34_a_leafActive{background:#608cdc2e}._0K34_a_leafActive:before{content:\\\"\\\";background:#608cdce6;border-radius:2px;width:2.5px;position:absolute;top:5px;bottom:5px;left:0}._0K34_a_leaf:focus-visible{outline:none;box-shadow:inset 0 0 0 1px #608cdcb3}._0K34_a_leafText{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}._0K34_a_fileChip{text-align:center;letter-spacing:.02em;box-sizing:border-box;border-radius:4px;flex:none;min-width:24px;padding:0 2px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:9px;font-weight:700;line-height:1.5}._0K34_a_chipMd{color:#608cdc;background:#608cdc38}._0K34_a_chipAdoc{color:#d29922;background:#d2992238}._0K34_a_chipYml{color:#966ec8;background:#966ec838}._0K34_a_chipTxt{color:#7f7f7ff2;background:#7f7f7f38}._0K34_a_chipSlides{color:#dca05a;background:#dca05a40}._0K34_a_chipPdf{color:#dc5a5a;background:#dc5a5a38}._0K34_a_chipOther{color:#7f7f7ff2;background:#7f7f7f2e}._0K34_a_flatList{flex-direction:column;display:flex}._0K34_a_main{flex-direction:column;flex:1;min-width:0;min-height:0;display:flex}._0K34_a_content{flex:1;min-height:0;overflow:hidden}._0K34_a_empty{color:#7f7f7fcc;text-align:center;justify-content:center;align-items:center;height:100%;padding:24px;font-size:14px;display:flex}._0K34_a_gateBox{text-align:left;max-width:min(760px,100%)}._0K34_a_cmdList{flex-direction:column;gap:6px;margin-top:12px;display:flex}._0K34_a_cmdRow{background:#0000000f;border-radius:8px;align-items:center;gap:8px;padding:6px 8px;display:flex}._0K34_a_cmdLabel{color:#7f7f7ff2;flex:none;width:88px;font-size:11px;line-height:1.4}._0K34_a_cmdCode{min-width:0;color:inherit;word-break:break-all;user-select:all;cursor:text;flex:auto;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;line-height:1.5}._0K34_a_cmdNote{opacity:.8;margin-top:10px;font-size:12px;line-height:1.6}._0K34_a_cmdNote code{word-break:break-all;background:#00000014;border-radius:4px;padding:1px 5px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px}._0K34_a_loadingDot{background:currentColor;border-radius:50%;width:8px;height:8px;margin-right:8px;animation:1s ease-in-out infinite _0K34_a_aero-loading-pulse}@keyframes _0K34_a_aero-loading-pulse{0%,to{opacity:.25;transform:scale(.8)}50%{opacity:1;transform:scale(1.15)}}._0K34_a_docRendering{color:#7f7f7fbf;text-align:center;margin:12px 0 0;font-size:13px}._0K34_a_docSegBar{z-index:3;background:color-mix(in srgb, currentColor 6%, transparent);backdrop-filter:blur(6px);border:1px solid #7f7f7f40;border-radius:8px;flex-wrap:wrap;align-items:center;gap:8px;margin:-6px 0 12px;padding:6px 10px;font-size:12px;display:flex;position:sticky;top:0}._0K34_a_docSegBtn{color:inherit;cursor:pointer;background:0 0;border:1px solid #7f7f7f59;border-radius:6px;padding:3px 10px;font-size:12px}._0K34_a_docSegBtn:hover:not(:disabled){background:color-mix(in srgb, currentColor 8%, transparent);border-color:#7f7f7f99}._0K34_a_docSegBtn:disabled{opacity:.4;cursor:default}._0K34_a_docSegInfo{text-overflow:ellipsis;white-space:nowrap;opacity:.85;flex:auto;min-width:0;overflow:hidden}._0K34_a_docSegSelect{max-width:42%;color:inherit;background:0 0;border:1px solid #7f7f7f59;border-radius:6px;padding:3px 6px;font-size:12px}._0K34_a_docScroll{scroll-behavior:smooth;box-sizing:border-box;flex:auto;min-width:0;height:100%;min-height:0;padding:16px clamp(12px,2vw,26px) 40px;overflow-y:auto}._0K34_a_docWrap{align-items:stretch;height:100%;min-height:0;display:flex;position:relative;container-type:inline-size}._0K34_a_docMeta{text-align:center;margin:0 0 1.3em}._0K34_a_docMetaKicker{font-family:var(--dsw-font-family,inherit);letter-spacing:.2em;color:var(--aero-ink-3,#818b98);font-size:11px;font-weight:500}._0K34_a_docMetaChips{flex-wrap:wrap;justify-content:center;gap:6px 8px;margin-top:.6em;display:flex}._0K34_a_docMetaChip{border:1px solid var(--aero-rule,#8080804d);font-family:var(--dsw-font-family,inherit);color:var(--aero-ink-2,#57606a);white-space:nowrap;border-radius:999px;align-items:center;gap:5px;padding:1px 9px;font-size:11.5px;line-height:1.7;display:inline-flex}._0K34_a_docMetaChipLabel{color:var(--aero-ink-3,#818b98)}._0K34_a_docMetaChip[data-tone=draft]{border-color:color-mix(in srgb, var(--dsw-alias-state-warn-primary,#f0b429) 45%, transparent);color:var(--dsw-alias-state-warn-label,#b7791f)}._0K34_a_docMetaChip[data-tone=reviewed]{border-color:color-mix(in srgb, var(--dsw-alias-state-business-primary,#2f6feb) 45%, transparent);color:var(--dsw-alias-state-business-primary,#2f6feb)}._0K34_a_docMetaChip[data-tone=done]{border-color:color-mix(in srgb, var(--dsw-alias-state-success-primary,#2f9e44) 45%, transparent);color:var(--dsw-alias-state-success-primary,#2f9e44)}._0K34_a_docMetaKeywords{font-family:var(--dsw-font-family,inherit);color:var(--aero-ink-3,#818b98);flex-wrap:wrap;justify-content:center;gap:8px;margin-top:.55em;font-size:11px;display:flex}._0K34_a_docMetaKeyword:before{content:\\\"#\\\";opacity:.7}._0K34_a_docOutline{border-left:1px solid var(--dsw-alias-border-l2,#80808033);background:color-mix(in srgb, var(--dsw-alias-bg-module-platform,#7f7f7f0f) 55%, transparent);box-sizing:border-box;flex:none;width:206px;height:100%;min-height:0;padding:12px 8px 32px 10px;font-size:12px;overflow-y:auto}._0K34_a_docOutlineHead{letter-spacing:.12em;color:var(--dsw-alias-label-tertiary,#818b98);align-items:center;gap:5px;padding:0 8px 8px;font-size:11px;font-weight:600;display:flex}._0K34_a_docOutlineList{flex-direction:column;gap:1px;margin:0;padding:0;list-style:none;display:flex}._0K34_a_docOutlineItem[data-level=\\\"1\\\"]{margin-top:8px}._0K34_a_docOutlineLink{width:100%;color:var(--dsw-alias-label-secondary,inherit);font:inherit;text-align:left;cursor:pointer;white-space:nowrap;text-overflow:ellipsis;background:0 0;border:none;border-radius:6px;padding:4px 8px;display:block;overflow:hidden}._0K34_a_docOutlineItem[data-level=\\\"2\\\"] ._0K34_a_docOutlineLink{padding-left:12px}._0K34_a_docOutlineItem[data-level=\\\"3\\\"] ._0K34_a_docOutlineLink{padding-left:22px}._0K34_a_docOutlineItem[data-level=\\\"4\\\"] ._0K34_a_docOutlineLink{padding-left:32px}._0K34_a_docOutlineNo{font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-tertiary,#818b98);margin-right:3px;font-weight:600}._0K34_a_docOutlineLink:hover{background:var(--dsw-alias-interactive-bg-hover,#7f7f7f1f);color:var(--dsw-alias-label-primary,inherit)}._0K34_a_docOutlineLinkActive{background:color-mix(in srgb, var(--dsw-alias-link,#4176e6) 14%, transparent);color:var(--dsw-alias-link,#4176e6);font-weight:600}@container (width<=860px){._0K34_a_docOutline{display:none}}._0K34_a_docLightbox{z-index:40;box-sizing:border-box;cursor:zoom-out;background:#0b0f17cc;flex-direction:column;justify-content:center;align-items:center;gap:10px;padding:22px;animation:.14s ease-out _0K34_a_aeroLightboxIn;display:flex;position:absolute;inset:0}@keyframes _0K34_a_aeroLightboxIn{0%{opacity:0}to{opacity:1}}._0K34_a_docLightboxFigure{flex-direction:column;align-items:center;gap:10px;max-width:100%;min-height:0;max-height:100%;margin:0;display:flex}._0K34_a_docLightboxFigure img{object-fit:contain;background:#fff;border-radius:6px;max-width:100%;min-height:0;max-height:100%;box-shadow:0 24px 64px -24px #000000b3}._0K34_a_docLightboxCap{color:#ffffffe0;text-align:center;max-width:min(880px,82%);font-size:12.5px;line-height:1.65}._0K34_a_docLightboxHint{color:#fff9;flex:none;align-items:center;gap:5px;font-size:11.5px;display:flex}._0K34_a_slideRoot{flex-direction:column;height:100%;min-height:0;display:flex}._0K34_a_slideStage{box-sizing:border-box;flex:1;justify-content:center;align-items:flex-start;min-height:0;padding:20px 28px;display:flex;overflow:auto}._0K34_a_slideBar{border-top:1px solid #80808033;flex:none;justify-content:center;align-items:center;gap:12px;padding:8px;display:flex}._0K34_a_slideCounter{color:#7f7f7fe6;text-align:center;min-width:60px;font-size:13px}._0K34_a_contextBar{background:#7f7f7f0a;border-top:1px solid #80808033;flex:none;align-items:center;gap:8px;padding:8px;display:flex}._0K34_a_contextInfo{flex:none;align-items:center;gap:6px;min-width:0;max-width:260px;display:flex}._0K34_a_contextDot{background:#5ac878f2;border-radius:50%;flex:none;width:8px;height:8px}._0K34_a_contextText{white-space:nowrap;text-overflow:ellipsis;font-size:12px;overflow:hidden}._0K34_a_contextMuted{color:#7f7f7fcc;font-size:12px}._0K34_a_questionInput{min-width:0;color:inherit;background:0 0;border:1px solid #80808059;border-radius:6px;flex:1;padding:6px 10px;font-size:13px}._0K34_a_questionInput:focus{border-color:#608cdccc;outline:none}._0K34_a_btn,._0K34_a_btnPrimary{color:inherit;cursor:pointer;background:0 0;border:1px solid #80808059;border-radius:6px;flex:none;padding:6px 12px;font-size:13px}._0K34_a_btn:hover{background:#7f7f7f1f}._0K34_a_btn:disabled,._0K34_a_btnPrimary:disabled{opacity:.45;cursor:not-allowed}._0K34_a_btnPrimary{color:#fff;background:#608cdce6;border-color:#608cdce6}._0K34_a_btnPrimary:hover:not(:disabled){background:#608cdc}._0K34_a_deckRoot{flex-direction:column;flex:1 1 0;width:100%;height:100%;min-height:0;display:flex}._0K34_a_deckToolbar{border-bottom:1px solid #80808038;flex-wrap:wrap;flex:none;align-items:center;gap:8px;padding:7px 10px;display:flex}._0K34_a_deckTitle{text-overflow:ellipsis;white-space:nowrap;max-width:42%;font-size:13px;font-weight:600;overflow:hidden}._0K34_a_deckStatus{color:#7f7f7ff2;align-items:center;gap:6px;font-size:12px;display:inline-flex}._0K34_a_deckHint{color:#7f7f7fbf;margin-left:2px;font-size:11px}._0K34_a_deckSpacer{flex:1 1 0}._0K34_a_deckBody{flex:1 1 0;min-height:0;position:relative}._0K34_a_deckFrame{background:#fff;border:0;width:100%;height:100%;display:block}._0K34_a_deckNotice{color:#7f7f7ff2;flex-direction:column;justify-content:center;align-items:center;gap:10px;height:100%;padding:24px;font-size:13px;display:flex;overflow:auto}._0K34_a_deckErrorTitle{color:inherit;font-size:14px;font-weight:600}._0K34_a_deckErrorMsg{text-align:center;max-width:640px}._0K34_a_deckLog{text-align:left;white-space:pre-wrap;word-break:break-all;background:#0000000f;border-radius:8px;max-width:min(720px,100%);max-height:220px;padding:10px 12px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;line-height:1.5;overflow:auto}._0K34_a_spinner{border:2px solid #7f7f7f59;border-top-color:#608cdce6;border-radius:50%;flex:none;width:14px;height:14px;animation:.9s linear infinite _0K34_a_aeroSpin;display:inline-block}@keyframes _0K34_a_aeroSpin{to{transform:rotate(360deg)}}._0K34_a_deckNoticeScroll{box-sizing:border-box;color:#7f7f7ff2;flex-direction:column;align-items:center;gap:12px;height:100%;padding:20px 24px 32px;font-size:13px;display:flex;overflow-y:auto}._0K34_a_deckNoticeHead{text-align:left;width:100%;max-width:720px;line-height:1.6}._0K34_a_deckNoticeBtns{align-items:center;gap:8px;width:100%;max-width:720px;display:flex}._0K34_a_envRoot{box-sizing:border-box;width:100%;max-width:720px}._0K34_a_envCard{text-align:left;background:#7f7f7f0d;border:1px solid #80808047;border-radius:10px;flex-direction:column;gap:10px;padding:14px 16px;display:flex}._0K34_a_envHead{align-items:center;gap:8px;display:flex}._0K34_a_envTitle{color:inherit;font-size:13px;font-weight:600}._0K34_a_envSummaryOk,._0K34_a_envSummaryBad{font-size:13px;font-weight:600;line-height:1.5}._0K34_a_envSummaryOk{color:#46aa6ef2}._0K34_a_envSummaryBad{color:#d75f5ff2}._0K34_a_envSummaryDetail{color:#7f7f7ff2;word-break:break-all;margin-top:4px;font-size:12px;font-weight:400}._0K34_a_envMuted{color:#7f7f7fd9;align-items:center;gap:6px;font-size:12px;display:flex}._0K34_a_envError{color:#d75f5ff2;word-break:break-all;font-size:12px}._0K34_a_envList{flex-direction:column;gap:8px;margin:0;padding:0;list-style:none;display:flex}._0K34_a_envItem{align-items:flex-start;gap:8px;display:flex}._0K34_a_envDotOk,._0K34_a_envDotWarn,._0K34_a_envDotFail{color:#fff;border-radius:50%;flex:none;justify-content:center;align-items:center;width:16px;height:16px;margin-top:1px;font-size:10px;font-weight:700;display:inline-flex}._0K34_a_envDotOk{background:#46aa6ee6}._0K34_a_envDotWarn{background:#dca550f2}._0K34_a_envDotFail{background:#d75f5ff2}._0K34_a_envItemBody{flex-direction:column;gap:2px;min-width:0;display:flex}._0K34_a_envItemLabel{color:inherit;align-items:center;gap:6px;font-size:12.5px;font-weight:600;display:flex}._0K34_a_envItemStatus{color:#7f7f7ff2;border:1px solid #80808059;border-radius:999px;padding:1px 5px;font-size:10px;font-weight:500}._0K34_a_envItemDetail{color:#7f7f7ff2;word-break:break-all;font-size:12px}._0K34_a_envItemHint{color:#7f7f7fd9;word-break:break-all;font-size:12px}._0K34_a_envActions{border-top:1px dashed #8080804d;flex-direction:column;gap:8px;padding-top:10px;display:flex}._0K34_a_envActionsTitle{color:inherit;font-size:12.5px;font-weight:600}._0K34_a_envAction{background:#7f7f7f0a;border:1px solid #8080803d;border-radius:8px;align-items:center;gap:10px;padding:8px 10px;display:flex}._0K34_a_envActionInfo{flex-direction:column;flex:auto;gap:3px;min-width:0;display:flex}._0K34_a_envActionLabel{color:inherit;font-size:12.5px;font-weight:600}._0K34_a_envActionCmd{flex-wrap:wrap;align-items:center;gap:6px;display:flex}._0K34_a_envActionCmd code{word-break:break-all;background:#00000014;border-radius:5px;padding:2px 6px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px}._0K34_a_envCopy{color:inherit;cursor:pointer;background:0 0;border:1px solid #80808059;border-radius:5px;flex:none;align-items:center;gap:4px;padding:2px 7px;font-size:11px;display:inline-flex}._0K34_a_envCopy:hover{background:#7f7f7f1f}._0K34_a_envDetails summary{cursor:pointer;color:#7f7f7ff2;font-size:12px}._0K34_a_prepContent{flex:1;min-height:0;display:flex}._0K34_a_prepPane{flex-direction:column;flex:1 1 0;min-width:0;min-height:0;display:flex;position:relative}._0K34_a_prepPane+._0K34_a_prepPane{border-left:1px solid #80808038}._0K34_a_prepPaneHead{color:#7f7f7ff2;background:#7f7f7f0a;border-bottom:1px solid #8080802e;flex:none;align-items:center;gap:8px;padding:5px 10px;font-size:12px;display:flex}._0K34_a_prepPanePath{text-overflow:ellipsis;white-space:nowrap;opacity:.85;min-width:0;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;overflow:hidden}._0K34_a_prepEditor{box-sizing:border-box;resize:none;width:100%;min-height:0;color:inherit;tab-size:4;white-space:pre;background:0 0;border:0;outline:none;flex:1;padding:12px 14px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:1.6;overflow:auto}._0K34_a_prepDocPane{flex:1;min-height:0;display:flex}._0K34_a_prepDocPane>._0K34_a_docWrap{flex:auto;height:auto}._0K34_a_prepSlidesScroll{box-sizing:border-box;flex-direction:column;flex:1;align-items:center;gap:14px;min-height:0;padding:16px;display:flex;overflow-y:auto}._0K34_a_prepSlide{box-sizing:border-box;background:#7f7f7f0d;border:1px solid #80808040;border-radius:10px;width:min(760px,100%);padding:20px 26px;box-shadow:0 1px 3px #0000001f}._0K34_a_prepSlideNo{color:#7f7f7fb3;margin-bottom:6px;font-size:11px}._0K34_a_prepCmdBar{background:#7f7f7f0a;border-top:1px solid #80808033;flex-direction:column;flex:none;gap:6px;padding:7px 10px;display:flex}._0K34_a_prepSkills{flex:none;gap:6px;display:flex;overflow-x:auto}._0K34_a_skillBtn{color:inherit;cursor:pointer;background:0 0;border:1px solid #80808059;border-radius:999px;flex:none;align-items:center;gap:5px;padding:4px 10px;font-size:12px;display:inline-flex}._0K34_a_skillBtn:hover:not(:disabled){background:#7f7f7f1f;border-color:#608cdcb3}._0K34_a_skillBtn:disabled{opacity:.4;cursor:not-allowed}._0K34_a_prepCmdRow{align-items:center;gap:8px;display:flex}._0K34_a_prepMode{border:1px solid #80808059;border-radius:6px;flex:none;display:inline-flex;overflow:hidden}._0K34_a_mode,._0K34_a_modeActive{color:inherit;cursor:pointer;background:0 0;border:none;padding:4px 9px;font-size:12px}._0K34_a_mode:hover{background:#7f7f7f1f}._0K34_a_modeActive{color:#fff;background:#608cdcd9}._0K34_a_saveDot{border-radius:50%;flex:none;width:8px;height:8px}._0K34_a_dotIdle{background:#7f7f7f80}._0K34_a_dotDirty{background:#dca05af2}._0K34_a_dotSaving{background:#608cdce6}._0K34_a_dotSaved{background:#5ac878f2}._0K34_a_dotError{background:#dc5a5af2}._0K34_a_saveLabel{white-space:nowrap;text-overflow:ellipsis;color:#7f7f7ff2;max-width:340px;font-size:12px;overflow:hidden}._0K34_a_tbBtnOn{color:#2a5cb0fa;background:#608cdc24;border-color:#608cdcbf}._0K34_a_readerWrap{flex:none;position:relative}._0K34_a_menuBackdrop{z-index:29;position:fixed;inset:0}._0K34_a_readerMenu{z-index:30;background:var(--dsw-alias-bg-layer-1,#fff);width:min(328px,86vw);color:var(--dsw-alias-label-primary,inherit);border:1px solid #80808059;border-radius:10px;flex-direction:column;gap:8px;padding:10px;display:flex;position:absolute;top:calc(100% + 6px);right:0;box-shadow:0 10px 28px #0f193238}._0K34_a_readerMenuHead{letter-spacing:.04em;opacity:.9;align-items:center;gap:6px;padding:0 2px 2px;font-size:12px;font-weight:600;display:flex}._0K34_a_readerRow{align-items:center;gap:8px;display:flex}._0K34_a_readerRowLabel{opacity:.75;flex:none;width:34px;font-size:12px}._0K34_a_readerSeg{flex-wrap:wrap;flex:1;align-items:center;gap:3px;min-width:0;display:flex}._0K34_a_readerSegBtn{color:inherit;cursor:pointer;background:0 0;border:1px solid #80808052;border-radius:6px;padding:3px 8px;font-size:12px;line-height:1.5}._0K34_a_readerSegBtn:hover:not(:disabled){background:#7f7f7f1f}._0K34_a_readerSegBtn:disabled{opacity:.45;cursor:default}._0K34_a_readerSegBtnOn{color:#2a5cb0fa;background:#608cdc29;border-color:#608cdccc;font-weight:600}._0K34_a_readerFontValue{text-align:center;font-variant-numeric:tabular-nums;opacity:.85;min-width:46px;font-size:12px}._0K34_a_readerHint{opacity:.7;border-top:1px dashed #8080804d;padding:4px 2px 0;font-size:11px;line-height:1.6}._0K34_a_root[data-zen=\\\"1\\\"] ._0K34_a_sidebar,._0K34_a_root[data-zen=\\\"1\\\"] ._0K34_a_contextBar,._0K34_a_root[data-zen=\\\"1\\\"] ._0K34_a_prepCmdBar,._0K34_a_root[data-sidebar=\\\"0\\\"] ._0K34_a_sidebar{display:none}._0K34_a_root:fullscreen{background:var(--dsw-alias-bg-layer-1,#fff);height:100vh}._0K34_a_root[data-fullscreen=\\\"1\\\"]{position:relative}._0K34_a_root[data-fullscreen=\\\"1\\\"] ._0K34_a_topbar{z-index:45;background:var(--dsw-alias-bg-layer-1,#fff);transition:transform .18s,opacity .18s;position:absolute;top:0;left:0;right:0;box-shadow:0 6px 16px -12px #0f193280}._0K34_a_root[data-fullscreen=\\\"1\\\"][data-fsbar=hidden] ._0K34_a_topbar{opacity:0;transform:translateY(-100%)}._0K34_a_root[data-fullscreen=\\\"1\\\"][data-fsbar=hidden]:after{content:\\\"\\\";pointer-events:none;z-index:46;background:linear-gradient(#608cdc59,#0000);height:3px;position:absolute;top:0;left:0;right:0}@media (hover:none){._0K34_a_root[data-fullscreen=\\\"1\\\"][data-fsbar=hidden] ._0K34_a_topbar{opacity:1;transform:none}}._0K34_a_docWrap:not([data-paper=theme]) ._0K34_a_docOutline{border-left-color:var(--aero-rule-ov,#80808033);background:color-mix(in srgb, var(--aero-paper-ov,transparent) 78%, transparent)}._0K34_a_docWrap:not([data-paper=theme]) ._0K34_a_docOutlineHead{color:var(--aero-ink-3-ov,#818b98)}._0K34_a_docWrap:not([data-paper=theme]) ._0K34_a_docOutlineLink{color:var(--aero-ink-2-ov,inherit)}._0K34_a_docWrap:not([data-paper=theme]) ._0K34_a_docOutlineLink:hover{background:var(--aero-hover-ov,#7f7f7f1f);color:var(--aero-ink-ov,inherit)}._0K34_a_docWrap:not([data-paper=theme]) ._0K34_a_docOutlineLinkActive{background:color-mix(in srgb, var(--aero-accent-ink-ov,#4176e6) 18%, transparent);color:var(--aero-accent-ink-ov,#4176e6)}@media (width<=520px){._0K34_a_readerMenu{width:min(300px,92vw)}._0K34_a_readerRowLabel{width:28px}}._0K34_a_annoColors{align-items:center;gap:5px;display:inline-flex}._0K34_a_annoColorBtn{cursor:pointer;background:#ffe066;border:1px solid #80808073;border-radius:50%;width:18px;height:18px;padding:0;transition:transform .1s;box-shadow:inset 0 0 0 2px #ffffff73}._0K34_a_annoColorBtn[data-color=yellow]{background:#ffe066}._0K34_a_annoColorBtn[data-color=green]{background:#a6e3a1}._0K34_a_annoColorBtn[data-color=blue]{background:#93c9f7}._0K34_a_annoColorBtn[data-color=pink]{background:#f7a8c4}._0K34_a_annoColorBtn:hover{transform:scale(1.14)}._0K34_a_annoColorBtn[data-on=\\\"1\\\"]{border-color:var(--dsw-alias-link,#4176e6);box-shadow:0 0 0 2px color-mix(in srgb, var(--dsw-alias-link,#4176e6) 45%, transparent)}._0K34_a_annoBar{z-index:46;background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-primary,inherit);white-space:nowrap;border:1px solid #80808052;border-radius:10px;align-items:center;gap:6px;padding:6px 8px;font-size:12px;display:flex;position:fixed;box-shadow:0 10px 26px #0f19323d}._0K34_a_annoBarSep{background:#8080804d;width:1px;height:18px}._0K34_a_annoBarBtn{color:inherit;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:6px;align-items:center;gap:4px;padding:3px 7px;font-size:12px;line-height:1.5;display:inline-flex}._0K34_a_annoBarBtn:hover{background:var(--dsw-alias-interactive-bg-hover,#7f7f7f1f);border-color:#80808052}._0K34_a_annoBarIcon{width:22px;height:22px;color:inherit;opacity:.6;cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;padding:0;display:inline-flex}._0K34_a_annoBarIcon:hover{opacity:1;background:var(--dsw-alias-interactive-bg-hover,#7f7f7f1f)}._0K34_a_annoPop{z-index:47;background:var(--dsw-alias-bg-layer-1,#fff);width:340px;max-width:calc(100vw - 16px);color:var(--dsw-alias-label-primary,inherit);border:1px solid #80808052;border-radius:12px;flex-direction:column;gap:8px;padding:10px;font-size:12px;display:flex;position:fixed;box-shadow:0 16px 40px #0f193242}._0K34_a_annoPopHead{align-items:center;gap:6px;display:flex}._0K34_a_annoPopDot{background:#ffe066;border-radius:50%;flex:none;width:10px;height:10px;box-shadow:0 0 0 1px #80808059}._0K34_a_annoPopDot[data-color=yellow]{background:#ffe066}._0K34_a_annoPopDot[data-color=green]{background:#a6e3a1}._0K34_a_annoPopDot[data-color=blue]{background:#93c9f7}._0K34_a_annoPopDot[data-color=pink]{background:#f7a8c4}._0K34_a_annoPopKicker{letter-spacing:.02em;font-weight:600}._0K34_a_annoPopSpacer{flex:1 1 0}._0K34_a_annoPopIcon{width:22px;height:22px;color:inherit;opacity:.6;cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;padding:0;display:inline-flex}._0K34_a_annoPopIcon:hover{opacity:1;background:var(--dsw-alias-interactive-bg-hover,#7f7f7f1f)}._0K34_a_annoPopQuote{background:var(--dsw-alias-bg-module-platform,#7f7f7f12);opacity:.92;border-left:3px solid #80808059;border-radius:4px;max-height:96px;margin:0;padding:7px 9px;font-size:12px;line-height:1.65;overflow-y:auto}._0K34_a_annoPopRow{align-items:center;gap:10px;display:flex}._0K34_a_annoPopSeg{color:inherit;cursor:pointer;background:0 0;border:1px solid #80808052;border-radius:6px;align-items:center;gap:4px;margin-left:auto;padding:3px 8px;font-size:12px;display:inline-flex}._0K34_a_annoPopSegOn{border-color:var(--dsw-alias-link,#4176e6);background:color-mix(in srgb, var(--dsw-alias-link,#4176e6) 14%, transparent)}._0K34_a_annoPopNote{box-sizing:border-box;width:100%;color:inherit;font:inherit;resize:vertical;background:0 0;border:1px solid #80808052;border-radius:8px;min-height:62px;padding:7px 9px;font-size:12.5px;line-height:1.65}._0K34_a_annoPopNote:focus{border-color:var(--dsw-alias-link,#4176e6);outline:none}._0K34_a_annoPopFoot{align-items:center;gap:8px;display:flex}._0K34_a_annoPopPrimary{background:var(--dsw-alias-link,#4176e6);color:#fff;cursor:pointer;border:1px solid #0000;border-radius:7px;padding:4px 14px;font-size:12px}._0K34_a_annoPopPrimary:hover{filter:brightness(1.06)}._0K34_a_annoPopBtn{color:inherit;cursor:pointer;background:0 0;border:1px solid #80808052;border-radius:7px;align-items:center;gap:4px;padding:4px 10px;font-size:12px;display:inline-flex}._0K34_a_annoPopBtn:hover{background:var(--dsw-alias-interactive-bg-hover,#7f7f7f1f)}._0K34_a_annoPopHint{opacity:.55;font-size:11px}._0K34_a_annoFab{z-index:30;background:var(--dsw-alias-bg-layer-1,#fff);width:38px;height:38px;color:var(--dsw-alias-label-secondary,inherit);cursor:pointer;border:1px solid #8080804d;border-radius:50%;justify-content:center;align-items:center;padding:0;transition:transform .12s,color .12s;display:inline-flex;position:absolute;bottom:16px;box-shadow:0 8px 22px #0f193233}._0K34_a_annoFab:hover{color:var(--dsw-alias-label-primary,inherit);transform:translateY(-1px)}._0K34_a_annoFabOn{border-color:var(--dsw-alias-link,#4176e6);color:var(--dsw-alias-link,#4176e6)}._0K34_a_annoFabBadge{box-sizing:border-box;color:#fff;text-align:center;font-variant-numeric:tabular-nums;background:#f0a020;border-radius:8px;min-width:16px;height:16px;padding:0 3px;font-size:10px;line-height:16px;position:absolute;top:-5px;right:-4px}._0K34_a_annoFabDot{width:7px;height:7px;box-shadow:0 0 0 1.5px var(--dsw-alias-bg-layer-1,#fff);background:#d94f8a;border-radius:50%;position:absolute;bottom:3px;right:3px}._0K34_a_annoPins{z-index:4;pointer-events:none;position:absolute;inset:0}._0K34_a_annoPin{color:#3c2d00e6;font-variant-numeric:tabular-nums;cursor:pointer;pointer-events:auto;background:#ffe066;border:1px solid #ffffffd9;border-radius:50%;width:19px;height:19px;padding:0;font-size:10px;line-height:1;position:absolute;box-shadow:0 2px 6px #0f193238}._0K34_a_annoPin[data-color=yellow]{color:#4a3800;background:#ffdf5c}._0K34_a_annoPin[data-color=green]{color:#1f3d18;background:#a6e3a1}._0K34_a_annoPin[data-color=blue]{color:#10334f;background:#93c9f7}._0K34_a_annoPin[data-color=pink]{color:#4a1330;background:#f7a8c4}._0K34_a_annoPin:hover{transform:scale(1.12)}._0K34_a_docMarks{box-sizing:border-box;border-left:1px solid var(--dsw-alias-border-l2,#80808033);background:color-mix(in srgb, var(--dsw-alias-bg-module-platform,#7f7f7f0f) 55%, transparent);flex-direction:column;flex:none;width:300px;height:100%;min-height:0;padding:10px 10px 8px;font-size:12px;display:flex}._0K34_a_docWrap:not([data-paper=theme]) ._0K34_a_docMarks{border-left-color:var(--aero-rule-ov,#80808033);background:color-mix(in srgb, var(--aero-paper-ov,transparent) 82%, transparent);color:var(--aero-ink-ov,inherit)}._0K34_a_docMarksHead{letter-spacing:.1em;color:var(--dsw-alias-label-tertiary,#818b98);align-items:center;gap:6px;padding:0 0 6px;font-size:11px;font-weight:600;display:flex}._0K34_a_docMarksCount{background:color-mix(in srgb, var(--dsw-alias-link,#4176e6) 18%, transparent);color:var(--dsw-alias-link,#4176e6);letter-spacing:0;border-radius:8px;padding:0 6px;font-size:10.5px}._0K34_a_docMarksHead ._0K34_a_annoPopIcon{margin-left:auto}._0K34_a_docMarksTitle{text-overflow:ellipsis;white-space:nowrap;opacity:.9;padding:0 0 8px;font-size:12px;font-weight:600;overflow:hidden}._0K34_a_docMarksFilters{border-bottom:1px dashed #8080804d;flex-wrap:wrap;gap:4px;padding-bottom:8px;display:flex}._0K34_a_docMarksChip{color:inherit;cursor:pointer;opacity:.8;background:0 0;border:1px solid #80808047;border-radius:999px;padding:2px 8px;font-size:11px}._0K34_a_docMarksChip:hover{opacity:1;background:var(--dsw-alias-interactive-bg-hover,#7f7f7f1f)}._0K34_a_docMarksChipOn{border-color:color-mix(in srgb, var(--dsw-alias-link,#4176e6) 65%, transparent);background:color-mix(in srgb, var(--dsw-alias-link,#4176e6) 14%, transparent);color:var(--dsw-alias-link,#4176e6);opacity:1}._0K34_a_docMarksList{flex-direction:column;flex:auto;gap:6px;min-height:0;padding:8px 2px 8px 0;display:flex;overflow-y:auto}._0K34_a_docMarksEmpty{opacity:.65;padding:10px 6px;font-size:11.5px;line-height:1.75}._0K34_a_docMarksItem{border:1px solid var(--dsw-alias-border-l2,#80808038);background:color-mix(in srgb, var(--dsw-alias-bg-layer-1,#fff) 70%, transparent);border-left-width:3px;border-radius:8px;flex-direction:column;gap:4px;padding:6px 8px;display:flex}._0K34_a_docMarksItem[data-color=yellow]{border-left-color:#f0c400}._0K34_a_docMarksItem[data-color=green]{border-left-color:#4caf50}._0K34_a_docMarksItem[data-color=blue]{border-left-color:#2b7cd3}._0K34_a_docMarksItem[data-color=pink]{border-left-color:#d94f8a}._0K34_a_docMarksQuoteBtn{color:inherit;text-align:left;cursor:pointer;background:0 0;border:none;flex-direction:column;gap:3px;padding:0;display:flex}._0K34_a_docMarksQuoteBtn:hover ._0K34_a_docMarksQuote{color:var(--dsw-alias-link,#4176e6)}._0K34_a_docMarksItemHead{align-items:center;gap:5px;display:flex}._0K34_a_docMarksItemKind{letter-spacing:.04em;opacity:.6;font-size:10.5px}._0K34_a_docMarksQuote{-webkit-line-clamp:3;-webkit-box-orient:vertical;font-size:12px;line-height:1.6;display:-webkit-box;overflow:hidden}._0K34_a_docMarksNote{-webkit-line-clamp:3;background:#f7a8c42e;border-radius:4px;-webkit-box-orient:vertical;margin-top:2px;padding:3px 6px;font-size:11.5px;line-height:1.6;display:-webkit-box;overflow:hidden}._0K34_a_docMarksItemFoot{justify-content:flex-end;gap:6px;display:flex}._0K34_a_docMarksMini{color:inherit;cursor:pointer;opacity:.8;background:0 0;border:1px solid #8080804d;border-radius:5px;padding:1px 7px;font-size:10.5px}._0K34_a_docMarksMini:hover{opacity:1;background:var(--dsw-alias-interactive-bg-hover,#7f7f7f1f)}._0K34_a_docMarksFoot{border-top:1px dashed #8080804d;align-items:center;gap:6px;padding-top:6px;display:flex}._0K34_a_docMarksFootBtn{color:inherit;cursor:pointer;background:0 0;border:1px solid #8080804d;border-radius:6px;padding:3px 9px;font-size:11px}._0K34_a_docMarksFootBtn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#7f7f7f1f)}._0K34_a_docMarksFootBtn:disabled{opacity:.4;cursor:default}._0K34_a_docMarksFootHint{opacity:.55;margin-left:auto;font-size:10.5px}._0K34_a_deckBody[data-panel=\\\"1\\\"]{align-items:stretch;display:flex}._0K34_a_deckBody[data-panel=\\\"1\\\"] ._0K34_a_deckFrame{flex:auto;width:auto;min-width:0}._0K34_a_deckBody[data-panel=\\\"1\\\"]>aside{flex:none}._0K34_a_docResume{z-index:7;border:1px solid var(--aero-rule,var(--dsw-alias-border-l2,#8080804d));background:var(--dsw-alias-bg-layer-1,#fff);max-width:min(600px,100% - 28px);color:var(--aero-ink,inherit);font-family:var(--dsw-font-family,inherit);border-radius:999px;align-items:center;gap:6px;padding:5px 6px 5px 12px;font-size:12px;line-height:1.4;animation:.16s ease-out _0K34_a_aero-resume-in;display:flex;position:absolute;top:10px;left:50%;transform:translate(-50%);box-shadow:0 6px 18px #0000001a}._0K34_a_docWrap[data-segbar=\\\"1\\\"] ._0K34_a_docResume{top:54px}._0K34_a_docWrap[data-paper=sepia] ._0K34_a_docResume{color:#3a3126;background:#f7efdd;border-color:#604c3047}._0K34_a_docWrap[data-paper=green] ._0K34_a_docResume{color:#22301d;background:#e7efe2;border-color:#3c5a2d47}._0K34_a_docWrap[data-paper=dark] ._0K34_a_docResume{color:#dfe3e8;background:#232830;border-color:#ffffff29}._0K34_a_docResumeText{white-space:nowrap;text-overflow:ellipsis;opacity:.92;align-items:baseline;gap:6px;min-width:0;display:inline-flex;overflow:hidden}._0K34_a_docResumeName{text-overflow:ellipsis;font-weight:600;overflow:hidden}._0K34_a_docResumeAge{opacity:.6;flex:none}._0K34_a_docResumeBtn{color:inherit;cursor:pointer;background:0 0;border:1px solid #7f7f7f59;border-radius:999px;flex:none;padding:2px 9px;font-family:inherit;font-size:11.5px}._0K34_a_docResumeBtn:hover{background:color-mix(in srgb, currentColor 8%, transparent);border-color:#7f7f7f99}._0K34_a_docResumeClose{width:18px;height:18px;color:inherit;opacity:.55;cursor:pointer;background:0 0;border:0;border-radius:50%;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}._0K34_a_docResumeClose:hover{opacity:1;background:color-mix(in srgb, currentColor 10%, transparent)}@keyframes _0K34_a_aero-resume-in{0%{opacity:0;transform:translate(-50%,-5px)}to{opacity:1;transform:translate(-50%)}}@container (width<=860px){._0K34_a_docMarks{width:252px}}@media print{._0K34_a_annoFab,._0K34_a_annoPins,._0K34_a_docMarks,._0K34_a_annoBar,._0K34_a_annoPop,._0K34_a_docResume{display:none!important}}\"\nconst styleId = \"@aero/study-kit/styles.module.css\"\nif (typeof document !== 'undefined' && document.querySelector('style[data-plugin-css=\"' + styleId + '\"]') === null) {\n const tag = document.createElement('style')\n tag.dataset.plugin = \"@aero/study-kit\"\n tag.dataset.pluginCss = styleId\n tag.textContent = css\n document.head.appendChild(tag)\n}\nconst classes: Record<string, string> = {\n \"aero-loading-pulse\": \"_0K34_a_aero-loading-pulse\",\n \"aero-resume-in\": \"_0K34_a_aero-resume-in\",\n \"aeroLightboxIn\": \"_0K34_a_aeroLightboxIn\",\n \"aeroSpin\": \"_0K34_a_aeroSpin\",\n \"annoBar\": \"_0K34_a_annoBar\",\n \"annoBarBtn\": \"_0K34_a_annoBarBtn\",\n \"annoBarIcon\": \"_0K34_a_annoBarIcon\",\n \"annoBarSep\": \"_0K34_a_annoBarSep\",\n \"annoColorBtn\": \"_0K34_a_annoColorBtn\",\n \"annoColors\": \"_0K34_a_annoColors\",\n \"annoFab\": \"_0K34_a_annoFab\",\n \"annoFabBadge\": \"_0K34_a_annoFabBadge\",\n \"annoFabDot\": \"_0K34_a_annoFabDot\",\n \"annoFabOn\": \"_0K34_a_annoFabOn\",\n \"annoPin\": \"_0K34_a_annoPin\",\n \"annoPins\": \"_0K34_a_annoPins\",\n \"annoPop\": \"_0K34_a_annoPop\",\n \"annoPopBtn\": \"_0K34_a_annoPopBtn\",\n \"annoPopDot\": \"_0K34_a_annoPopDot\",\n \"annoPopFoot\": \"_0K34_a_annoPopFoot\",\n \"annoPopHead\": \"_0K34_a_annoPopHead\",\n \"annoPopHint\": \"_0K34_a_annoPopHint\",\n \"annoPopIcon\": \"_0K34_a_annoPopIcon\",\n \"annoPopKicker\": \"_0K34_a_annoPopKicker\",\n \"annoPopNote\": \"_0K34_a_annoPopNote\",\n \"annoPopPrimary\": \"_0K34_a_annoPopPrimary\",\n \"annoPopQuote\": \"_0K34_a_annoPopQuote\",\n \"annoPopRow\": \"_0K34_a_annoPopRow\",\n \"annoPopSeg\": \"_0K34_a_annoPopSeg\",\n \"annoPopSegOn\": \"_0K34_a_annoPopSegOn\",\n \"annoPopSpacer\": \"_0K34_a_annoPopSpacer\",\n \"body\": \"_0K34_a_body\",\n \"btn\": \"_0K34_a_btn\",\n \"btnPrimary\": \"_0K34_a_btnPrimary\",\n \"chevron\": \"_0K34_a_chevron\",\n \"chipAdoc\": \"_0K34_a_chipAdoc\",\n \"chipMd\": \"_0K34_a_chipMd\",\n \"chipOther\": \"_0K34_a_chipOther\",\n \"chipPdf\": \"_0K34_a_chipPdf\",\n \"chipSlides\": \"_0K34_a_chipSlides\",\n \"chipTxt\": \"_0K34_a_chipTxt\",\n \"chipYml\": \"_0K34_a_chipYml\",\n \"cmdCode\": \"_0K34_a_cmdCode\",\n \"cmdLabel\": \"_0K34_a_cmdLabel\",\n \"cmdList\": \"_0K34_a_cmdList\",\n \"cmdNote\": \"_0K34_a_cmdNote\",\n \"cmdRow\": \"_0K34_a_cmdRow\",\n \"content\": \"_0K34_a_content\",\n \"contextBar\": \"_0K34_a_contextBar\",\n \"contextDot\": \"_0K34_a_contextDot\",\n \"contextInfo\": \"_0K34_a_contextInfo\",\n \"contextMuted\": \"_0K34_a_contextMuted\",\n \"contextText\": \"_0K34_a_contextText\",\n \"crumb\": \"_0K34_a_crumb\",\n \"crumbLast\": \"_0K34_a_crumbLast\",\n \"crumbs\": \"_0K34_a_crumbs\",\n \"crumbSep\": \"_0K34_a_crumbSep\",\n \"deckBody\": \"_0K34_a_deckBody\",\n \"deckErrorMsg\": \"_0K34_a_deckErrorMsg\",\n \"deckErrorTitle\": \"_0K34_a_deckErrorTitle\",\n \"deckFrame\": \"_0K34_a_deckFrame\",\n \"deckHint\": \"_0K34_a_deckHint\",\n \"deckLog\": \"_0K34_a_deckLog\",\n \"deckNotice\": \"_0K34_a_deckNotice\",\n \"deckNoticeBtns\": \"_0K34_a_deckNoticeBtns\",\n \"deckNoticeHead\": \"_0K34_a_deckNoticeHead\",\n \"deckNoticeScroll\": \"_0K34_a_deckNoticeScroll\",\n \"deckRoot\": \"_0K34_a_deckRoot\",\n \"deckSpacer\": \"_0K34_a_deckSpacer\",\n \"deckStatus\": \"_0K34_a_deckStatus\",\n \"deckTitle\": \"_0K34_a_deckTitle\",\n \"deckToolbar\": \"_0K34_a_deckToolbar\",\n \"docLightbox\": \"_0K34_a_docLightbox\",\n \"docLightboxCap\": \"_0K34_a_docLightboxCap\",\n \"docLightboxFigure\": \"_0K34_a_docLightboxFigure\",\n \"docLightboxHint\": \"_0K34_a_docLightboxHint\",\n \"docMarks\": \"_0K34_a_docMarks\",\n \"docMarksChip\": \"_0K34_a_docMarksChip\",\n \"docMarksChipOn\": \"_0K34_a_docMarksChipOn\",\n \"docMarksCount\": \"_0K34_a_docMarksCount\",\n \"docMarksEmpty\": \"_0K34_a_docMarksEmpty\",\n \"docMarksFilters\": \"_0K34_a_docMarksFilters\",\n \"docMarksFoot\": \"_0K34_a_docMarksFoot\",\n \"docMarksFootBtn\": \"_0K34_a_docMarksFootBtn\",\n \"docMarksFootHint\": \"_0K34_a_docMarksFootHint\",\n \"docMarksHead\": \"_0K34_a_docMarksHead\",\n \"docMarksItem\": \"_0K34_a_docMarksItem\",\n \"docMarksItemFoot\": \"_0K34_a_docMarksItemFoot\",\n \"docMarksItemHead\": \"_0K34_a_docMarksItemHead\",\n \"docMarksItemKind\": \"_0K34_a_docMarksItemKind\",\n \"docMarksList\": \"_0K34_a_docMarksList\",\n \"docMarksMini\": \"_0K34_a_docMarksMini\",\n \"docMarksNote\": \"_0K34_a_docMarksNote\",\n \"docMarksQuote\": \"_0K34_a_docMarksQuote\",\n \"docMarksQuoteBtn\": \"_0K34_a_docMarksQuoteBtn\",\n \"docMarksTitle\": \"_0K34_a_docMarksTitle\",\n \"docMeta\": \"_0K34_a_docMeta\",\n \"docMetaChip\": \"_0K34_a_docMetaChip\",\n \"docMetaChipLabel\": \"_0K34_a_docMetaChipLabel\",\n \"docMetaChips\": \"_0K34_a_docMetaChips\",\n \"docMetaKeyword\": \"_0K34_a_docMetaKeyword\",\n \"docMetaKeywords\": \"_0K34_a_docMetaKeywords\",\n \"docMetaKicker\": \"_0K34_a_docMetaKicker\",\n \"docOutline\": \"_0K34_a_docOutline\",\n \"docOutlineHead\": \"_0K34_a_docOutlineHead\",\n \"docOutlineItem\": \"_0K34_a_docOutlineItem\",\n \"docOutlineLink\": \"_0K34_a_docOutlineLink\",\n \"docOutlineLinkActive\": \"_0K34_a_docOutlineLinkActive\",\n \"docOutlineList\": \"_0K34_a_docOutlineList\",\n \"docOutlineNo\": \"_0K34_a_docOutlineNo\",\n \"docRendering\": \"_0K34_a_docRendering\",\n \"docResume\": \"_0K34_a_docResume\",\n \"docResumeAge\": \"_0K34_a_docResumeAge\",\n \"docResumeBtn\": \"_0K34_a_docResumeBtn\",\n \"docResumeClose\": \"_0K34_a_docResumeClose\",\n \"docResumeName\": \"_0K34_a_docResumeName\",\n \"docResumeText\": \"_0K34_a_docResumeText\",\n \"docScroll\": \"_0K34_a_docScroll\",\n \"docSegBar\": \"_0K34_a_docSegBar\",\n \"docSegBtn\": \"_0K34_a_docSegBtn\",\n \"docSegInfo\": \"_0K34_a_docSegInfo\",\n \"docSegSelect\": \"_0K34_a_docSegSelect\",\n \"docWrap\": \"_0K34_a_docWrap\",\n \"dotDirty\": \"_0K34_a_dotDirty\",\n \"dotError\": \"_0K34_a_dotError\",\n \"dotIdle\": \"_0K34_a_dotIdle\",\n \"dotSaved\": \"_0K34_a_dotSaved\",\n \"dotSaving\": \"_0K34_a_dotSaving\",\n \"empty\": \"_0K34_a_empty\",\n \"envAction\": \"_0K34_a_envAction\",\n \"envActionCmd\": \"_0K34_a_envActionCmd\",\n \"envActionInfo\": \"_0K34_a_envActionInfo\",\n \"envActionLabel\": \"_0K34_a_envActionLabel\",\n \"envActions\": \"_0K34_a_envActions\",\n \"envActionsTitle\": \"_0K34_a_envActionsTitle\",\n \"envCard\": \"_0K34_a_envCard\",\n \"envCopy\": \"_0K34_a_envCopy\",\n \"envDetails\": \"_0K34_a_envDetails\",\n \"envDotFail\": \"_0K34_a_envDotFail\",\n \"envDotOk\": \"_0K34_a_envDotOk\",\n \"envDotWarn\": \"_0K34_a_envDotWarn\",\n \"envError\": \"_0K34_a_envError\",\n \"envHead\": \"_0K34_a_envHead\",\n \"envItem\": \"_0K34_a_envItem\",\n \"envItemBody\": \"_0K34_a_envItemBody\",\n \"envItemDetail\": \"_0K34_a_envItemDetail\",\n \"envItemHint\": \"_0K34_a_envItemHint\",\n \"envItemLabel\": \"_0K34_a_envItemLabel\",\n \"envItemStatus\": \"_0K34_a_envItemStatus\",\n \"envList\": \"_0K34_a_envList\",\n \"envMuted\": \"_0K34_a_envMuted\",\n \"envRoot\": \"_0K34_a_envRoot\",\n \"envSummaryBad\": \"_0K34_a_envSummaryBad\",\n \"envSummaryDetail\": \"_0K34_a_envSummaryDetail\",\n \"envSummaryOk\": \"_0K34_a_envSummaryOk\",\n \"envTitle\": \"_0K34_a_envTitle\",\n \"fileChip\": \"_0K34_a_fileChip\",\n \"flatList\": \"_0K34_a_flatList\",\n \"gateBox\": \"_0K34_a_gateBox\",\n \"group\": \"_0K34_a_group\",\n \"groupChildren\": \"_0K34_a_groupChildren\",\n \"groupLabel\": \"_0K34_a_groupLabel\",\n \"leaf\": \"_0K34_a_leaf\",\n \"leafActive\": \"_0K34_a_leafActive\",\n \"leafText\": \"_0K34_a_leafText\",\n \"loadingDot\": \"_0K34_a_loadingDot\",\n \"main\": \"_0K34_a_main\",\n \"menuBackdrop\": \"_0K34_a_menuBackdrop\",\n \"mode\": \"_0K34_a_mode\",\n \"modeActive\": \"_0K34_a_modeActive\",\n \"prepCmdBar\": \"_0K34_a_prepCmdBar\",\n \"prepCmdRow\": \"_0K34_a_prepCmdRow\",\n \"prepContent\": \"_0K34_a_prepContent\",\n \"prepDocPane\": \"_0K34_a_prepDocPane\",\n \"prepEditor\": \"_0K34_a_prepEditor\",\n \"prepMode\": \"_0K34_a_prepMode\",\n \"prepPane\": \"_0K34_a_prepPane\",\n \"prepPaneHead\": \"_0K34_a_prepPaneHead\",\n \"prepPanePath\": \"_0K34_a_prepPanePath\",\n \"prepSkills\": \"_0K34_a_prepSkills\",\n \"prepSlide\": \"_0K34_a_prepSlide\",\n \"prepSlideNo\": \"_0K34_a_prepSlideNo\",\n \"prepSlidesScroll\": \"_0K34_a_prepSlidesScroll\",\n \"questionInput\": \"_0K34_a_questionInput\",\n \"readerFontValue\": \"_0K34_a_readerFontValue\",\n \"readerHint\": \"_0K34_a_readerHint\",\n \"readerMenu\": \"_0K34_a_readerMenu\",\n \"readerMenuHead\": \"_0K34_a_readerMenuHead\",\n \"readerRow\": \"_0K34_a_readerRow\",\n \"readerRowLabel\": \"_0K34_a_readerRowLabel\",\n \"readerSeg\": \"_0K34_a_readerSeg\",\n \"readerSegBtn\": \"_0K34_a_readerSegBtn\",\n \"readerSegBtnOn\": \"_0K34_a_readerSegBtnOn\",\n \"readerWrap\": \"_0K34_a_readerWrap\",\n \"root\": \"_0K34_a_root\",\n \"saveDot\": \"_0K34_a_saveDot\",\n \"saveLabel\": \"_0K34_a_saveLabel\",\n \"search\": \"_0K34_a_search\",\n \"sidebar\": \"_0K34_a_sidebar\",\n \"sidebarHeader\": \"_0K34_a_sidebarHeader\",\n \"skillBtn\": \"_0K34_a_skillBtn\",\n \"slideBar\": \"_0K34_a_slideBar\",\n \"slideCounter\": \"_0K34_a_slideCounter\",\n \"slideRoot\": \"_0K34_a_slideRoot\",\n \"slideStage\": \"_0K34_a_slideStage\",\n \"spinner\": \"_0K34_a_spinner\",\n \"tbBtn\": \"_0K34_a_tbBtn\",\n \"tbBtnOn\": \"_0K34_a_tbBtnOn\",\n \"topbar\": \"_0K34_a_topbar\",\n \"topbarTitle\": \"_0K34_a_topbarTitle\",\n \"tree\": \"_0K34_a_tree\",\n \"tweakItem\": \"_0K34_a_tweakItem\",\n \"tweakItemId\": \"_0K34_a_tweakItemId\",\n \"tweakItemTitle\": \"_0K34_a_tweakItemTitle\",\n \"tweakMenu\": \"_0K34_a_tweakMenu\",\n \"tweakMenuHint\": \"_0K34_a_tweakMenuHint\",\n \"tweakWrap\": \"_0K34_a_tweakWrap\"\n}\nexport default classes\n","/**\n * 阅读标注的 UI:选区取色工具条、便签编辑浮层、标记面板、右侧边注圆点、悬浮入口。\n *\n * 与 annotations.ts 的分工:那里管「数据 + 锚点 + 落到 DOM 的 mark」,这里只画控件。\n * 「学习资料」与「备课」共用同一套组件(两边都渲染 DocViewer),课件播放器复用\n * 面板与便签浮层,只是定位回调换成「跳到某页」。\n *\n * 交互约定(对齐微信读书,学生不需要学):\n * · 选中正文 → 选区上方浮出工具条:四种荧光色 / 重点线 / 写想法 / 问 AI;\n * · 点已有标记 → 弹出同一个编辑浮层(改色、切线、写想法、删除、问 AI);\n * · 有想法的标注在正文右缘留一个彩色圆点,点它直接打开浮层;\n * · 右下角「✍ N」打开标记列表:定位、逐条删除、复制全部(Markdown)。\n */\nimport { useCallback, useEffect, useMemo, useRef, useState, type MouseEvent } from 'react'\nimport {\n ANNO_COLORS, ANNO_COLOR_LABEL, exportMarkdown, summarizeQuote,\n type AnnoAnchor, type AnnoColor, type AnnoStyle, type Annotation, type AnnotationPatch, type NotePin,\n} from './annotations.js'\nimport { ChatIcon, CloseIcon, PenIcon, TrashIcon, UnderlineIcon } from './icons.js'\nimport css from './styles.module.css.gen.ts'\n\n/**\n * 我们的控件一律吃掉 mousedown 的默认行为。\n *\n * 否则点按钮会让正文选区先塌掉 → DocViewer 的 selectionchange 监听判定「没选中」→\n * 工具条在 click 之前就被卸载,按钮永远点不动(这是浮层工具条最经典的坑)。\n */\nfunction stopSelectionCollapse(e: MouseEvent): void {\n e.preventDefault()\n}\n\n/** 四色荧光笔(工具条与浮层共用)。 */\nfunction ColorSwatches({ active, onPick }: {\n readonly active?: AnnoColor\n readonly onPick: (color: AnnoColor) => void\n}): JSX.Element {\n return (\n <div className={css.annoColors} role=\"group\" aria-label=\"荧光色\">\n {ANNO_COLORS.map((color) => (\n <button\n key={color}\n type=\"button\"\n className={css.annoColorBtn}\n data-color={color}\n data-on={color === active ? '1' : '0'}\n title={ANNO_COLOR_LABEL[color]}\n aria-label={ANNO_COLOR_LABEL[color]}\n aria-pressed={color === active}\n onMouseDown={stopSelectionCollapse}\n onClick={() => onPick(color)}\n />\n ))}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// 选区工具条\n// ---------------------------------------------------------------------------\n\nexport interface SelectionState {\n /** 选区中心(视口坐标)——工具条以它为水平中心。 */\n readonly x: number\n /** 选区上沿(视口坐标)——工具条贴在它上方。 */\n readonly y: number\n readonly anchor: AnnoAnchor\n}\n\nconst BAR_WIDTH = 268\nconst BAR_HEIGHT = 40\n\n/** 把浮层夹在视口内(不越出左右/上下边界)。 */\nfunction clampLeft(centerX: number, width: number): number {\n const half = width / 2\n return Math.min(Math.max(half + 8, centerX), window.innerWidth - half - 8)\n}\n\nexport function SelectionBar({ sel, onPick, onNote, onAsk, onDismiss }: {\n readonly sel: SelectionState\n readonly onPick: (color: AnnoColor, style: AnnoStyle) => void\n readonly onNote: () => void\n readonly onAsk: (() => void) | null\n readonly onDismiss: () => void\n}): JSX.Element {\n const above = sel.y - BAR_HEIGHT - 10 > 8\n const top = above ? sel.y - BAR_HEIGHT - 10 : sel.y + 26\n const left = clampLeft(sel.x, BAR_WIDTH)\n return (\n <div\n className={css.annoBar}\n style={{ left: `${String(left)}px`, top: `${String(top)}px` }}\n data-aero-mark-ui=\"\"\n role=\"toolbar\"\n aria-label=\"标注所选文字\"\n onMouseDown={stopSelectionCollapse}\n >\n <ColorSwatches onPick={(color) => onPick(color, 'highlight')} />\n <span className={css.annoBarSep} />\n <button\n type=\"button\"\n className={css.annoBarBtn}\n title=\"画重点线(下划线)\"\n onClick={() => onPick('yellow', 'underline')}\n >\n <UnderlineIcon size={13} />\n 重点线\n </button>\n <button type=\"button\" className={css.annoBarBtn} title=\"对这段写一句自己的想法 / 提问\" onClick={onNote}>\n <ChatIcon size={13} />\n 写想法\n </button>\n {onAsk !== null && (\n <button type=\"button\" className={css.annoBarBtn} title=\"把这段连同我的标注发给 AI 讲解\" onClick={onAsk}>\n 问 AI\n </button>\n )}\n <button type=\"button\" className={css.annoBarIcon} title=\"取消\" aria-label=\"取消\" onClick={onDismiss}>\n <CloseIcon size={12} />\n </button>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// 便签 / 编辑浮层\n// ---------------------------------------------------------------------------\n\nexport interface EditorState {\n readonly id: string\n /** 浮层落点(视口坐标)。 */\n readonly left: number\n readonly top: number\n}\n\n/** 浮层落点(不含标注 id):调用方把 id 补上即可。 */\nexport interface EditorAnchor {\n readonly left: number\n readonly top: number\n}\n\nconst POP_WIDTH = 340\nconst POP_HEIGHT = 250\n\n/** 浮层落点:优先贴标记下方,下面放不下就翻到上方,左右夹在视口内。 */\nexport function popoverAt(rect: { left: number; right: number; top: number; bottom: number }): EditorAnchor {\n const left = Math.min(Math.max(8, rect.left), Math.max(8, window.innerWidth - POP_WIDTH - 8))\n const below = rect.bottom + 8\n const above = rect.top - POP_HEIGHT - 8\n const top = below + POP_HEIGHT > window.innerHeight - 8 && above > 8 ? above : below\n return { left, top }\n}\n\ninterface EditorProps {\n readonly anno: Annotation\n readonly at: Pick<EditorState, 'left' | 'top'>\n readonly onPatch: (patch: AnnotationPatch) => void\n readonly onDelete: () => void\n readonly onAsk: ((note: string) => void) | null\n readonly onClose: () => void\n}\n\n/**\n * 标注编辑浮层:改色、切线(荧光笔 ⇄ 重点线)、写想法。\n *\n * 保存策略:改色/切线立即生效(点了就能看见);文字用「保存」或 Ctrl/⌘+Enter 提交,\n * 关闭时若有未保存的改动则自动补交一次——学生写着写着点外面走开,不该丢。\n */\nexport function NoteEditor({ anno, at, onPatch, onDelete, onAsk, onClose }: EditorProps): JSX.Element {\n const [note, setNote] = useState(anno.note)\n const noteRef = useRef(note)\n noteRef.current = note\n const savedRef = useRef(anno.note)\n const inputRef = useRef<HTMLTextAreaElement>(null)\n\n useEffect(() => {\n inputRef.current?.focus()\n const el = inputRef.current\n if (el === null) return\n el.setSelectionRange(el.value.length, el.value.length)\n }, [])\n\n const commit = useCallback((): void => {\n const next = noteRef.current.trim()\n if (next !== savedRef.current) {\n savedRef.current = next\n onPatch({ note: next })\n }\n }, [onPatch])\n\n // 卸载时补交未保存的文字(同一 effect 清空时读 ref,不会读到闭包里的旧值)。\n useEffect(() => () => {\n const next = noteRef.current.trim()\n if (next !== savedRef.current) onPatch({ note: next })\n }, [onPatch])\n\n const style: AnnoStyle = anno.style\n return (\n <div\n className={css.annoPop}\n style={{ left: `${String(at.left)}px`, top: `${String(at.top)}px` }}\n data-aero-mark-ui=\"\"\n role=\"dialog\"\n aria-label=\"编辑标注\"\n >\n <div className={css.annoPopHead}>\n <span className={css.annoPopDot} data-color={anno.color} />\n <span className={css.annoPopKicker}>{style === 'underline' ? '重点线' : `${ANNO_COLOR_LABEL[anno.color]}标记`}</span>\n <span className={css.annoPopSpacer} />\n <button type=\"button\" className={css.annoPopIcon} title=\"删除这条标记\" aria-label=\"删除\" onClick={onDelete}>\n <TrashIcon size={12} />\n </button>\n <button\n type=\"button\"\n className={css.annoPopIcon}\n title=\"关闭\"\n aria-label=\"关闭\"\n onClick={() => {\n commit()\n onClose()\n }}\n >\n <CloseIcon size={12} />\n </button>\n </div>\n\n <blockquote className={css.annoPopQuote}>{summarizeQuote(anno.quote, 160)}</blockquote>\n\n <div className={css.annoPopRow}>\n <ColorSwatches active={anno.color} onPick={(color) => onPatch({ color })} />\n <button\n type=\"button\"\n className={style === 'underline' ? `${css.annoPopSeg} ${css.annoPopSegOn}` : css.annoPopSeg}\n title={style === 'underline' ? '取消重点线,改为荧光笔' : '改为重点线(下划线)'}\n aria-pressed={style === 'underline'}\n onClick={() => onPatch({ style: style === 'underline' ? 'highlight' : 'underline' })}\n >\n <UnderlineIcon size={12} />\n 重点线\n </button>\n </div>\n\n <textarea\n ref={inputRef}\n className={css.annoPopNote}\n placeholder=\"写一句自己的想法,或把不懂的地方记成提问…(Ctrl/⌘ + Enter 保存)\"\n value={note}\n rows={3}\n onChange={(e) => setNote(e.target.value)}\n onKeyDown={(e) => {\n if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {\n e.preventDefault()\n commit()\n onClose()\n } else if (e.key === 'Escape') {\n e.preventDefault()\n commit()\n onClose()\n }\n }}\n />\n\n <div className={css.annoPopFoot}>\n <button\n type=\"button\"\n className={css.annoPopPrimary}\n onClick={() => {\n commit()\n onClose()\n }}\n >\n 保存\n </button>\n {onAsk !== null && (\n <button\n type=\"button\"\n className={css.annoPopBtn}\n title=\"把这段文字与我的想法一起发给 AI\"\n onClick={() => {\n commit()\n onAsk(noteRef.current.trim())\n }}\n >\n <ChatIcon size={12} /> 问 AI\n </button>\n )}\n <span className={css.annoPopSpacer} />\n <span className={css.annoPopHint}>点颜色即可换色</span>\n </div>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// 标记面板(右侧抽屉)\n// ---------------------------------------------------------------------------\n\ntype Filter = 'all' | 'note' | 'highlight' | 'underline'\n\nconst FILTERS: readonly { id: Filter; label: string }[] = [\n { id: 'all', label: '全部' },\n { id: 'note', label: '有想法' },\n { id: 'highlight', label: '荧光笔' },\n { id: 'underline', label: '重点线' },\n]\n\nfunction matches(anno: Annotation, filter: Filter): boolean {\n switch (filter) {\n case 'all': return true\n case 'note': return anno.note.trim() !== ''\n case 'highlight': return anno.style === 'highlight'\n case 'underline': return anno.style === 'underline'\n }\n}\n\ninterface PanelProps {\n readonly title: string\n readonly annos: readonly Annotation[]\n /** 导出用的文档键(同一次打开只导出当前文档)。 */\n readonly exportKey: string\n readonly showPage: boolean\n readonly onLocate: (anno: Annotation) => void\n readonly onAsk: ((anno: Annotation) => void) | null\n readonly onDelete: (anno: Annotation) => void\n readonly onClear: () => void\n readonly onClose: () => void\n}\n\n/** 标记列表:定位 / 删除 / 问 AI / 复制全部(Markdown,贴给 AI 或自己复习)。 */\nexport function MarksPanel({\n title, annos, exportKey, showPage, onLocate, onAsk, onDelete, onClear, onClose,\n}: PanelProps): JSX.Element {\n const [filter, setFilter] = useState<Filter>('all')\n const [copied, setCopied] = useState(false)\n const timerRef = useRef<number | null>(null)\n const visible = useMemo(() => annos.filter((a) => matches(a, filter)), [annos, filter])\n const noteCount = annos.filter((a) => a.note.trim() !== '').length\n\n useEffect(() => () => {\n if (timerRef.current !== null) window.clearTimeout(timerRef.current)\n }, [])\n\n const copyAll = useCallback(() => {\n const text = exportMarkdown([exportKey])\n try {\n const task = navigator.clipboard?.writeText(text)\n if (task === undefined) return\n void task.then(() => {\n setCopied(true)\n if (timerRef.current !== null) window.clearTimeout(timerRef.current)\n timerRef.current = window.setTimeout(() => setCopied(false), 1800)\n }).catch(() => { /* 剪贴板不可用:静默(可在控制台用 exportMarkdown 取) */ })\n } catch {\n /* 忽略 */\n }\n }, [exportKey])\n\n const clearAll = useCallback(() => {\n if (annos.length === 0) return\n if (!window.confirm(`清空本${showPage ? '课件' : '文档'}的 ${String(annos.length)} 条标记?此操作不可撤销。`)) return\n onClear()\n }, [annos.length, onClear, showPage])\n\n return (\n <aside className={css.docMarks} data-aero-mark-ui=\"\" aria-label=\"标记与提问\">\n <div className={css.docMarksHead}>\n <PenIcon size={12} />\n <span>标记与提问</span>\n <span className={css.docMarksCount}>{annos.length}</span>\n <button type=\"button\" className={css.annoPopIcon} title=\"收起面板\" aria-label=\"收起\" onClick={onClose}>\n <CloseIcon size={12} />\n </button>\n </div>\n <div className={css.docMarksTitle} title={title}>{title}</div>\n <div className={css.docMarksFilters} role=\"group\" aria-label=\"筛选\">\n {FILTERS.map((f) => (\n <button\n key={f.id}\n type=\"button\"\n className={f.id === filter ? `${css.docMarksChip} ${css.docMarksChipOn}` : css.docMarksChip}\n aria-pressed={f.id === filter}\n onClick={() => setFilter(f.id)}\n >\n {f.label}\n </button>\n ))}\n </div>\n\n <div className={css.docMarksList}>\n {annos.length === 0 && (\n <div className={css.docMarksEmpty}>\n 还没有标记。\n <br />\n 在正文里选中一段文字,选区上方会浮出取色条:点一种荧光色即高亮,点「重点线」画下划线,\n 点「写想法」把自己的提问记在这一段旁边。\n </div>\n )}\n {annos.length > 0 && visible.length === 0 && <div className={css.docMarksEmpty}>这个筛选下没有标记。</div>}\n {visible.map((anno) => (\n <div key={anno.id} className={css.docMarksItem} data-color={anno.color}>\n <button type=\"button\" className={css.docMarksQuoteBtn} title=\"定位到正文的这一处\" onClick={() => onLocate(anno)}>\n <span className={css.docMarksItemHead}>\n <span className={css.annoPopDot} data-color={anno.color} />\n <span className={css.docMarksItemKind}>\n {showPage && anno.page > 0 ? `第 ${String(anno.page)} 页 · ` : ''}\n {anno.style === 'underline' ? '重点线' : '标记'}\n </span>\n </span>\n <span className={css.docMarksQuote}>{summarizeQuote(anno.quote)}</span>\n {anno.note.trim() !== '' && <span className={css.docMarksNote}>{anno.note.trim()}</span>}\n </button>\n <div className={css.docMarksItemFoot}>\n {onAsk !== null && (\n <button type=\"button\" className={css.docMarksMini} title=\"就这一处问 AI\" onClick={() => onAsk(anno)}>\n 问 AI\n </button>\n )}\n <button type=\"button\" className={css.docMarksMini} title=\"删除这条标记\" onClick={() => onDelete(anno)}>\n 删除\n </button>\n </div>\n </div>\n ))}\n </div>\n\n <div className={css.docMarksFoot}>\n <button type=\"button\" className={css.docMarksFootBtn} disabled={annos.length === 0} onClick={copyAll}>\n {copied ? '已复制' : '复制全部'}\n </button>\n <button type=\"button\" className={css.docMarksFootBtn} disabled={annos.length === 0} onClick={clearAll}>\n 清空\n </button>\n {noteCount > 0 && <span className={css.docMarksFootHint}>{noteCount} 条有想法</span>}\n </div>\n </aside>\n )\n}\n\n// ---------------------------------------------------------------------------\n// 右侧边注圆点(「有想法」的标注在纸面右缘留一个入口)\n// ---------------------------------------------------------------------------\n\nexport function NotePinLayer({ pins, onOpen }: {\n readonly pins: readonly NotePin[]\n readonly onOpen: (id: string) => void\n}): JSX.Element | null {\n if (pins.length === 0) return null\n return (\n <div className={css.annoPins} data-aero-mark-ui=\"\" aria-label=\"我的批注\">\n {pins.map((pin) => (\n <button\n key={pin.id}\n type=\"button\"\n className={css.annoPin}\n data-color={pin.color}\n style={{ top: `${String(pin.top)}px`, left: `${String(pin.left)}px` }}\n title={pin.note}\n aria-label={`批注:${pin.note}`}\n onMouseDown={stopSelectionCollapse}\n onClick={() => onOpen(pin.id)}\n >\n {pin.index}\n </button>\n ))}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// 悬浮入口(右下角「✍ N」)\n// ---------------------------------------------------------------------------\n\nexport function MarksFab({ count, noted, open, right, onClick }: {\n readonly count: number\n readonly noted: number\n readonly open: boolean\n readonly right: number\n readonly onClick: () => void\n}): JSX.Element {\n return (\n <button\n type=\"button\"\n className={open ? `${css.annoFab} ${css.annoFabOn}` : css.annoFab}\n style={{ right: `${String(right)}px` }}\n title={count === 0 ? '标记与提问:选中正文即可取色标注' : `标记与提问(共 ${String(count)} 条${noted > 0 ? `,${String(noted)} 条有想法` : ''})`}\n aria-label=\"标记与提问\"\n aria-pressed={open}\n data-aero-mark-ui=\"\"\n onMouseDown={stopSelectionCollapse}\n onClick={onClick}\n >\n <PenIcon size={15} />\n {count > 0 && <span className={css.annoFabBadge}>{count}</span>}\n {noted > 0 && <span className={css.annoFabDot} />}\n </button>\n )\n}\n\n// ---------------------------------------------------------------------------\n// 把一条标注组装成「问 AI」的文本(两个工作台共用同一份措辞)\n// ---------------------------------------------------------------------------\n\nexport function annotationQuestion(quote: string, note: string): string {\n const trimmed = note.trim()\n const lines: string[] = []\n lines.push('【我在资料里标注了这段话】')\n lines.push(quote.replace(/\\s+/g, ' ').trim())\n lines.push('')\n lines.push('【我的问题】')\n lines.push(trimmed !== '' ? trimmed : '这段话怎么理解?请结合上下文讲清楚它的含义、适用条件,以及我容易误解的地方。')\n return lines.join('\\n')\n}\n","import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, type CSSProperties } from 'react'\r\nimport type { DocRenderResult } from '../types.js'\r\nimport { ensureGlobalCss, truncate, type ReadingContext } from './prose.js'\r\nimport { enhanceDoc, isSectionNumberingTarget, parseAdocHeader, sectionNumbers, stripManualSectionNo, type DocMeta } from './docEnhance.js'\r\nimport { useReaderPrefs, FONT_STEPS } from './readerPrefs.js'\r\nimport {\r\n describeAge, loadPos, clearPos, savePos, positionAt, targetTop, RESUME_MIN_PX,\r\n type HeadingMark,\r\n} from './readingPos.js'\r\nimport {\r\n anchorFromRange, docKeyOf, markRectOf, notePins, paintAnnotation, paintAnnotations,\r\n removeAnnotation, scrollToAnnotation, updateAnnotation, useAnnotations,\r\n type AnnoColor, type AnnoStyle, type AnnotationPatch, type NotePin,\r\n} from './annotations.js'\r\nimport {\r\n MarksFab, MarksPanel, NoteEditor, NotePinLayer, SelectionBar, annotationQuestion, popoverAt,\r\n type EditorState, type SelectionState,\r\n} from './DocMarks.js'\r\nimport { CloseIcon, ListIcon } from './icons.js'\r\nimport css from './styles.module.css.gen.ts'\r\n\r\ninterface Props {\r\n relPath: string\r\n result: DocRenderResult\r\n onReadingChange: (ctx: ReadingContext) => void\r\n /** 打开知识库内另一文档(相对 KB 根路径)——正文内链接的阅读器内导航。 */\r\n onOpenDoc?: (relPath: string) => void\r\n /** 打开**同一文档的另一段**(超长文档被宿主分段,见 src/docsplit.ts 与 /aero-kb/doc?seg=)。 */\r\n onOpenSegment?: (seg: number) => void\r\n /** 会话工作目录参数(取源文档头部属性做「资料名片」用)。 */\r\n cwdParam?: string\r\n /**\r\n * 「问 AI」出口:把标注的原文 + 自己的想法交给所在工作台(各台自己组上下文并发送)。\r\n * 不传则不显示「问 AI」按钮(例如无输入区的只读场景)。\r\n */\r\n onAsk?: (text: string) => void\r\n}\r\n\r\n/** 标记面板宽度(px)——与 styles.module.css 的 .docMarks 保持一致(悬浮按钮让位要用)。 */\r\nconst MARKS_PANEL_WIDTH = 300\r\n/** 右侧「本页目录」宽度(px),与 styles.module.css 的 .docOutline 一致。 */\r\nconst OUTLINE_WIDTH = 206\r\n\r\n/** 目录项最大层级(h4 以下不再进目录,避免目录比正文还长)。 */\r\nconst OUTLINE_MAX_LEVEL = 4\r\n\r\n/**\r\n * 阅读位置落库的节流间隔(ms)。\r\n *\r\n * 写成「首帧立即写 + 之后节流」而不是纯 debounce:debounce 只在停下后写,\r\n * 停手前最后一段滚动(或者边滚边点另一份文档)会整段丢掉;而每帧写一次\r\n * localStorage 又会把整库 JSON 序列化几十次/秒。200ms ≈ 每秒 5 次,\r\n * 丢也最多丢半行,滚动一停最新位置立刻在库里。\r\n */\r\nconst POS_SAVE_THROTTLE_MS = 200\r\n\r\n/**\r\n * 恢复后自我纠偏的时间窗(ms)。\r\n *\r\n * 恢复发生在「分片注入完成」那一刻,此时图注图片往往还没加载完,正文比最终状态矮,\r\n * 恢复点会随图片撑高而漂移。3 秒内跟着图片 load 再对齐几次,用户一动手立刻停手。\r\n */\r\nconst POS_CORRECTION_WINDOW_MS = 3000\r\n\r\n/** 「已回到上次读到处」提示条的存活时间(ms):够看清一行字,又不会挡着读书。 */\r\nconst RESUME_HINT_MS = 9000\r\n\r\n/**\r\n * 正文分片注入的粒度(每片大致节点数)。\r\n *\r\n * 为什么分片:一篇公式密集的教案渲染出来可能有三四万个节点,一次性 innerHTML 挂到\r\n * 已布局的 DOM 上,浏览器要在一帧里建完布局树 + 样式,主线程被占满(实测单帧最长\r\n * 595 ms、整篇 2 s 以上),用户看到的就是「点了没反应」。按片插入把这段工作摊到多帧,\r\n * 首屏立刻可见、页面全程可交互。\r\n */\r\nconst INJECT_NODE_BUDGET = 4000\r\n\r\nfunction sectionExcerpt(heading: HTMLElement): string {\r\n const parts: string[] = [(heading.textContent ?? '').trim()]\r\n let el = heading.nextElementSibling\r\n let count = 0\r\n while (el !== null && count < 14) {\r\n if (/^H[1-6]$/i.test(el.tagName)) break\r\n const t = (el.textContent ?? '').trim()\r\n if (t.length > 0) parts.push(t)\r\n el = el.nextElementSibling\r\n count++\r\n }\r\n return parts.join('\\n')\r\n}\r\n\r\n/** 知识库根目录 → 「资料名片」的眉题(这是哪一类材料)。 */\r\nfunction kickerOf(relPath: string): string {\r\n const head = relPath.split('/')[0] ?? ''\r\n switch (head) {\r\n case 'knowledge-base': return '贯通式教材 · 知识库正文'\r\n case 'lesson-plan': return '正式教案 · AsciiDoc'\r\n case 'textbook': return '教材原文'\r\n case 'teaching-case': return '课件源文件'\r\n default: return head === '' ? '学习资料' : head\r\n }\r\n}\r\n\r\n/** 状态徽标的配色档(骨架/草稿/已审核/定稿)。 */\r\nfunction statusTone(status: string): string {\r\n if (status.includes('定稿') || status.includes('审定') || status.includes('发布')) return 'done'\r\n if (status.includes('已审核') || status.includes('审核')) return 'reviewed'\r\n if (status.includes('草稿') || status.includes('撰写')) return 'draft'\r\n return 'skeleton'\r\n}\r\n\r\ninterface MetaChip {\r\n readonly key: string\r\n readonly label: string\r\n readonly value: string\r\n readonly tone?: string\r\n}\r\n\r\n/** 从 :kb-*: 属性构造资料名片。没有任何属性时返回空数组(不渲染名片)。 */\r\nfunction metaChips(meta: DocMeta | null): MetaChip[] {\r\n if (meta === null) return []\r\n const a = meta.attrs\r\n const chips: MetaChip[] = []\r\n const push = (key: string, label: string, raw: string | undefined, tone?: string): void => {\r\n if (raw === undefined || raw.trim() === '') return\r\n chips.push(tone === undefined ? { key, label, value: raw.trim() } : { key, label, value: raw.trim(), tone })\r\n }\r\n push('id', '编号', a['kb-id'])\r\n push('status', '状态', a['kb-status'], statusTone(a['kb-status'] ?? ''))\r\n push('level', '层级', a['kb-level'])\r\n push('regime', '速域', a['kb-regime']?.replaceAll(';', ' · '))\r\n push('textbook', '教材', a['kb-textbook'] === undefined ? undefined : `§${a['kb-textbook'].replaceAll(';', '、')}`)\r\n push('sources', '来源', a['kb-sources']?.replaceAll(';', ' · '))\r\n push('prereq', '前置', a['kb-prereq']?.replaceAll(';', ' · '))\r\n return chips\r\n}\r\n\r\nexport function DocViewer({ relPath, result, onReadingChange, onOpenDoc, onOpenSegment, cwdParam, onAsk }: Props): JSX.Element {\r\n const containerRef = useRef<HTMLDivElement>(null)\r\n const bodyRef = useRef<HTMLDivElement>(null)\r\n const wrapRef = useRef<HTMLDivElement>(null)\r\n const onReadingRef = useRef(onReadingChange)\r\n onReadingRef.current = onReadingChange\r\n const prefs = useReaderPrefs()\r\n const [activeId, setActiveId] = useState<string | null>(null)\r\n const [zoom, setZoom] = useState<{ src: string; caption: string } | null>(null)\r\n const [meta, setMeta] = useState<DocMeta | null>(null)\r\n /** 已完整注入 DOM 的 HTML(分片注入完成前不等于 result.html)。 */\r\n const [renderedHtml, setRenderedHtml] = useState<string | null>(null)\r\n\r\n const html = result.html\r\n const isAdoc = result.kind === 'adoc'\r\n const segments = result.segments ?? []\r\n const seg = result.seg ?? 0\r\n const hasSegments = segments.length > 1\r\n\r\n // -------------------------------------------------------------------------\r\n // 阅读位置(上次读到哪里)\r\n //\r\n // 详见 readingPos.ts:位置 = 顶部可见标题 id + 章内像素偏移,改字号/版心后仍指向\r\n // 同一段文字;进度只是锚点失效时的兜底。DocViewer 只负责「量 DOM、写库、回滚」,\r\n // 位置键就是下面标注用的同一个 `docKey`(`<relPath>#<seg>`,见 docKey.ts)。\r\n // -------------------------------------------------------------------------\r\n /** 恢复成功后的提示条(含章节名与保存时间);null = 不显示。 */\r\n const [resume, setResume] = useState<{ label: string; at: number } | null>(null)\r\n /** 程序性滚动(恢复 / 纠偏 / 从头读)正在进行:这期间的 scroll 事件不算「用户在那儿」。 */\r\n const restoringRef = useRef(false)\r\n /** 用户自己动过滚动条:一旦发生就停止纠偏——绝不能让自动恢复和手抢滚动。 */\r\n const userScrolledRef = useRef(false)\r\n /** 每份文档只恢复一次(正文即便重渲染也不许把正在读的人拽回去)。 */\r\n const restoredRef = useRef(false)\r\n\r\n /**\r\n * 标题位置缓存。\r\n *\r\n * 为什么必须缓存:保存阅读位置是**滚动节流**触发的(POS_SAVE_THROTTLE_MS),而每次\r\n * 写位置都要知道\"标题在内容坐标里的位置\"。旧实现每次都 `querySelectorAll('h1..h6')`\r\n * 再逐个 `getBoundingClientRect()`——长章节(知识手册一节几十个标题、参考书上百个)\r\n * 滚动时每秒几十次、上千次强制布局读,正文一滚就掉帧。\r\n *\r\n * 失效条件(滚动**不**使其失效):正文重排才会让位置变化——分段注入完成、图片落位、\r\n * 字号/版心/行距变更、窗口 resize。前两者由正文容器的 ResizeObserver 兜住(高度一变\r\n * 就作废),字号/版心最终也体现在高度上;窗口 resize 另挂一个监听兜底。\r\n */\r\n const headingCacheRef = useRef<HeadingMark[] | null>(null)\r\n\r\n /** 量出所有标题在内容坐标里的顶端位置(一次批量读矩形,中间不写样式);带缓存。 */\r\n const measureHeadings = useCallback((): HeadingMark[] => {\r\n const cached = headingCacheRef.current\r\n if (cached !== null) return cached\r\n const container = containerRef.current\r\n if (container === null) return []\r\n const containerTop = container.getBoundingClientRect().top\r\n const scrollTop = container.scrollTop\r\n const out: HeadingMark[] = []\r\n for (const h of container.querySelectorAll<HTMLElement>('h1[id],h2[id],h3[id],h4[id],h5[id],h6[id]')) {\r\n out.push({\r\n id: h.id,\r\n text: (h.textContent ?? '').replace(/\\s+/g, ' ').trim(),\r\n top: h.getBoundingClientRect().top - containerTop + scrollTop,\r\n })\r\n }\r\n headingCacheRef.current = out\r\n return out\r\n }, [])\r\n\r\n /**\r\n * 立即把内容坐标写进滚动条。\r\n *\r\n * `.docScroll` 带 `scroll-behavior: smooth`:`scrollTop = x` 与\r\n * `scrollTo({ behavior: 'auto' })` 都会沿用 CSS 的平滑滚动,恢复位置时观众会看到\r\n * 正文从顶部一路爬下来(纠偏还会追着爬,永远追不上)。这里把 `scroll-behavior`\r\n * 临时改成 `auto`(内联样式优先级高于类规则),滚完再还原——比只依赖\r\n * `behavior: 'instant'` 更稳:那个值在部分内核里还不认,会被当成 'auto' 平滑滚。\r\n */\r\n const scrollContentTo = useCallback((top: number): void => {\r\n const container = containerRef.current\r\n if (container === null) return\r\n restoringRef.current = true\r\n const previous = container.style.scrollBehavior\r\n container.style.scrollBehavior = 'auto'\r\n container.scrollTop = Math.max(0, Math.round(top))\r\n container.style.scrollBehavior = previous\r\n // scroll 事件在本帧的渲染步骤里派发,早于 rAF 回调:下一帧解除标记即可覆盖它。\r\n window.requestAnimationFrame(() => {\r\n restoringRef.current = false\r\n })\r\n }, [])\r\n\r\n // -------------------------------------------------------------------------\r\n // 阅读标注(荧光笔 / 重点线 / 便签提问)\r\n // -------------------------------------------------------------------------\r\n const docKey = docKeyOf(relPath, seg)\r\n const annos = useAnnotations(docKey)\r\n /** 选区工具条(含已落成的锚点;点按钮时选区可能已塌,因此锚点必须提前存好)。 */\r\n const [sel, setSel] = useState<SelectionState | null>(null)\r\n /** 便签编辑浮层(id + 视口落点)。 */\r\n const [editor, setEditor] = useState<EditorState | null>(null)\r\n const [panelOpen, setPanelOpen] = useState(false)\r\n /** 正文右缘的批注圆点(有想法的标注才出现)。 */\r\n const [pins, setPins] = useState<NotePin[]>([])\r\n /**\r\n * 「刚建好的标注,绘制完成后自动打开它的浮层」。\r\n * 用 ref 而不是 state:绘制在 effect 里跑,写成 state 依赖会多画一遍。\r\n */\r\n const pendingEditorRef = useRef<string | null>(null)\r\n /** pin 计算要读最新的标注表(避免为了它多注册一个 effect 依赖)。 */\r\n const annosRef = useRef(annos)\r\n annosRef.current = annos\r\n\r\n const outline = useMemo(\r\n () => result.sections.filter((s) => s.level <= OUTLINE_MAX_LEVEL && s.title !== ''),\r\n [result.sections],\r\n )\r\n\r\n /**\r\n * 节标题编号(`1 / 1.1 / 1.1.1`):正文标题与右侧目录共用同一份,\r\n * 保证「目录里看到的号」与「正文里看到的号」永远一致(见 docEnhance.ts)。\r\n * 只对知识手册的 adoc 生效;其它文档(教案、参考书 md)为 null,行为与以前完全一致。\r\n */\r\n const sectionNos = useMemo(\r\n () => (isSectionNumberingTarget(relPath, result.kind) ? sectionNumbers(result.sections) : null),\r\n [relPath, result.kind, result.sections],\r\n )\r\n\r\n useEffect(() => {\r\n ensureGlobalCss()\r\n }, [])\r\n\r\n // 资料名片:AsciiDoc 的头部属性(:kb-id: 等)不会出现在渲染结果里,\r\n // 因此单独取一次源文档头部解析(教师端/学生端都允许读知识库正文)。\r\n useEffect(() => {\r\n if (!isAdoc) {\r\n setMeta(null)\r\n return\r\n }\r\n let cancelled = false\r\n const cwd = cwdParam === undefined || cwdParam === '' ? '' : cwdParam\r\n fetch(`/aero-kb/source?p=${encodeURIComponent(relPath)}${cwd}`)\r\n .then((r) => (r.ok ? r.json() as Promise<{ ok?: boolean; text?: string }> : Promise.reject(new Error(`HTTP ${r.status}`))))\r\n .then((d) => {\r\n if (cancelled) return\r\n setMeta(typeof d.text === 'string' && d.text !== '' ? parseAdocHeader(d.text) : null)\r\n })\r\n .catch(() => {\r\n if (!cancelled) setMeta(null)\r\n })\r\n return () => {\r\n cancelled = true\r\n }\r\n }, [relPath, isAdoc, cwdParam])\r\n\r\n // 正文增强(图注落地、宽表包装、固定小节打标、外链新窗口)与**分片注入**:\r\n // 先在游离节点里一次性解析 HTML(不进布局树),再按节点预算分帧挂到正文容器上,\r\n // 全部挂完才做 DOM 增强并解除滚动跟踪的等待。\r\n useEffect(() => {\r\n const body = bodyRef.current\r\n if (body === null) return\r\n setRenderedHtml(null)\r\n body.innerHTML = ''\r\n const staging = document.createElement('div')\r\n staging.innerHTML = html\r\n const top = Array.from(staging.childNodes)\r\n // 按子树节点数分片:顶层块大小差异极大(一行文字 vs 整张表),按节点数才均衡。\r\n const slices: ChildNode[][] = []\r\n let cur: ChildNode[] = []\r\n let weight = 0\r\n for (const n of top) {\r\n const w = n.nodeType === 1 ? 1 + (n as Element).querySelectorAll('*').length : 1\r\n if (weight > 0 && weight + w > INJECT_NODE_BUDGET) {\r\n slices.push(cur)\r\n cur = []\r\n weight = 0\r\n }\r\n cur.push(n)\r\n weight += w\r\n }\r\n if (cur.length > 0) slices.push(cur)\r\n\r\n let i = 0\r\n let cancelled = false\r\n let timer: number | null = null\r\n const step = (): void => {\r\n if (cancelled) return\r\n const frag = document.createDocumentFragment()\r\n for (const n of slices[i] ?? []) frag.appendChild(n)\r\n i++\r\n body.appendChild(frag)\r\n if (i < slices.length) {\r\n timer = window.setTimeout(step, 0)\r\n return\r\n }\r\n enhanceDoc(body, sectionNos)\r\n setActiveId(null)\r\n setRenderedHtml(html)\r\n }\r\n step()\r\n return () => {\r\n cancelled = true\r\n if (timer !== null) window.clearTimeout(timer)\r\n }\r\n }, [html, relPath, sectionNos])\r\n\r\n /**\r\n * 标题位置缓存的失效钩子(见 measureHeadings 的说明):\r\n * · 正文重排(分段注入完成、图片落位、字号/版心/行距变更)→ 正文容器高度变 → 作废;\r\n * · 窗口 resize(换版心/换字号后不一定改高度,例如窄屏换宽屏)→ 作废兜底。\r\n * 滚动本身不触发这里,所以\"边滚边存位置\"不再反复量全文。\r\n */\r\n useEffect(() => {\r\n headingCacheRef.current = null\r\n const body = bodyRef.current\r\n if (body === null) return\r\n const invalidate = (): void => {\r\n headingCacheRef.current = null\r\n }\r\n const observer = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(invalidate)\r\n observer?.observe(body)\r\n window.addEventListener('resize', invalidate)\r\n return () => {\r\n observer?.disconnect()\r\n window.removeEventListener('resize', invalidate)\r\n }\r\n }, [html, relPath, sectionNos])\r\n\r\n // -------------------------------------------------------------------------\r\n // 阅读位置:恢复(注入完成那一帧)+ 保存(滚动节流)+ 提示条\r\n //\r\n // 时机是这件事的全部难点:\r\n // · 恢复放在 useLayoutEffect 里、且等 `renderedHtml === html`(分片注入全部挂完):\r\n // 早于一帧内容还没进 DOM,scrollHeight 是 0,写了也会被后面的挂载冲掉;\r\n // 晚一帧(普通 effect)则会先画出开头、再跳过去,翻页感很明显。\r\n // · 保存只认「用户自己滚」:程序性滚动有 restoringRef 挡着,用户一动手\r\n // (滚轮/触摸/按键/拖滚动条)就把 userScrolledRef 立起来,纠偏立刻停手。\r\n // -------------------------------------------------------------------------\r\n useLayoutEffect(() => {\r\n const container = containerRef.current\r\n const body = bodyRef.current\r\n if (container === null || body === null || renderedHtml !== html) return\r\n if (restoredRef.current) return\r\n restoredRef.current = true\r\n\r\n const saved = loadPos(docKey)\r\n if (saved === null) return\r\n const max = Math.max(0, container.scrollHeight - container.clientHeight)\r\n // 一屏装得下的文档没有「位置」可留(也不用清理:保存路径遇到同样的条件会自己清)。\r\n if (max < RESUME_MIN_PX) return\r\n const want = targetTop(saved, measureHeadings(), container.scrollHeight, container.clientHeight)\r\n // 上次就停在开头:不打扰,也不弹提示(提示条只回应「你确实读到里面去了」)。\r\n if (want < RESUME_MIN_PX) return\r\n\r\n scrollContentTo(want)\r\n setResume({ label: saved.label, at: saved.at })\r\n\r\n // 图片陆续到达会把内容撑高,恢复点随之偏下:窗口内跟着对齐,用户一动就停。\r\n const correct = (): void => {\r\n if (userScrolledRef.current) return\r\n const c = containerRef.current\r\n if (c === null) return\r\n const limit = Math.max(0, c.scrollHeight - c.clientHeight)\r\n const next = Math.min(limit, targetTop(saved, measureHeadings(), c.scrollHeight, c.clientHeight))\r\n if (Math.abs(c.scrollTop - next) > 2) scrollContentTo(next)\r\n }\r\n let raf = window.requestAnimationFrame(() => {\r\n correct()\r\n raf = window.requestAnimationFrame(correct)\r\n })\r\n const pending = Array.from(body.querySelectorAll('img')).filter((img) => !img.complete)\r\n for (const img of pending) img.addEventListener('load', correct, { once: true })\r\n const timer = window.setTimeout(() => {\r\n for (const img of pending) img.removeEventListener('load', correct)\r\n window.cancelAnimationFrame(raf)\r\n }, POS_CORRECTION_WINDOW_MS)\r\n return () => {\r\n window.cancelAnimationFrame(raf)\r\n window.clearTimeout(timer)\r\n for (const img of pending) img.removeEventListener('load', correct)\r\n }\r\n }, [docKey, renderedHtml, html, measureHeadings, scrollContentTo])\r\n\r\n useEffect(() => {\r\n const container = containerRef.current\r\n if (container === null || renderedHtml !== html) return\r\n let timer: number | null = null\r\n let lastAt = 0\r\n\r\n const write = (): void => {\r\n timer = null\r\n const c = containerRef.current\r\n if (c === null || restoringRef.current) return\r\n const max = Math.max(0, c.scrollHeight - c.clientHeight)\r\n // 文档改短/改版后不到一屏:旧位置已经没有意义,顺手清掉,免得下次白恢复。\r\n if (max < RESUME_MIN_PX) {\r\n clearPos(docKey)\r\n return\r\n }\r\n savePos(docKey, { ...positionAt(measureHeadings(), c.scrollTop, c.scrollHeight, c.clientHeight), at: Date.now() })\r\n lastAt = Date.now()\r\n }\r\n const onScroll = (): void => {\r\n if (restoringRef.current) return\r\n const wait = POS_SAVE_THROTTLE_MS - (Date.now() - lastAt)\r\n if (wait <= 0) {\r\n write()\r\n return\r\n }\r\n if (timer !== null) return\r\n timer = window.setTimeout(write, wait)\r\n }\r\n container.addEventListener('scroll', onScroll, { passive: true })\r\n return () => {\r\n container.removeEventListener('scroll', onScroll)\r\n if (timer !== null) window.clearTimeout(timer)\r\n // 切文档 / 关标签时补记一次:节流窗口里最后那半行不能丢。\r\n write()\r\n }\r\n }, [docKey, renderedHtml, html, measureHeadings])\r\n\r\n // 用户动过滚动条 = 纠偏到此为止。用捕获阶段的按下/滚轮/按键,比只看 scroll 更早生效\r\n // (滚轮按下时 scroll 还没发生,先停手就不会和第一下滚动较劲)。\r\n useEffect(() => {\r\n const container = containerRef.current\r\n if (container === null || renderedHtml !== html) return\r\n const stop = (): void => {\r\n userScrolledRef.current = true\r\n }\r\n const events: readonly (keyof HTMLElementEventMap)[] = ['wheel', 'touchstart', 'pointerdown', 'keydown']\r\n for (const name of events) container.addEventListener(name, stop, { capture: true, passive: true })\r\n return () => {\r\n for (const name of events) container.removeEventListener(name, stop, { capture: true })\r\n }\r\n }, [renderedHtml, html])\r\n\r\n // 提示条自己消失:它只是「位置记住了」的一次回执,不该长期占着正文上沿。\r\n useEffect(() => {\r\n if (resume === null) return\r\n const timer = window.setTimeout(() => setResume(null), RESUME_HINT_MS)\r\n return () => window.clearTimeout(timer)\r\n }, [resume])\r\n\r\n /** 「从头读」:忘掉这份文档的位置并回到开头(提示条同时收起)。 */\r\n const readFromTop = useCallback((): void => {\r\n clearPos(docKey)\r\n setResume(null)\r\n scrollContentTo(0)\r\n }, [docKey, scrollContentTo])\r\n\r\n // -------------------------------------------------------------------------\r\n // 标注:绘制(幂等:先摘旧 mark 再按当前文本重画)+ 正文右缘的批注圆点\r\n //\r\n // 绘制放在「分片注入完成」之后(renderedHtml === html):此时正文是完整的一份,\r\n // 文本偏移与落笔时的坐标系一致;在注入途中画会被后续分片冲掉。\r\n // -------------------------------------------------------------------------\r\n const recomputePins = useCallback((): void => {\r\n const body = bodyRef.current\r\n const scroller = containerRef.current\r\n if (body === null || scroller === null) {\r\n setPins([])\r\n return\r\n }\r\n setPins(notePins(body, scroller, annosRef.current))\r\n }, [])\r\n\r\n useEffect(() => {\r\n const body = bodyRef.current\r\n if (body === null || renderedHtml !== html) return\r\n paintAnnotations(body, annos)\r\n // 「写想法」新建的标注:此刻 mark 才存在,顺手把浮层打开并定位到它。\r\n const pending = pendingEditorRef.current\r\n if (pending !== null) {\r\n pendingEditorRef.current = null\r\n const rect = markRectOf(body, pending)\r\n if (rect !== null) setEditor({ id: pending, ...popoverAt(rect) })\r\n }\r\n recomputePins()\r\n }, [annos, renderedHtml, html, recomputePins])\r\n\r\n // 字号/版式/窗口宽度变化会让圆点错位:跟着正文尺寸重算(不重画 mark,成本很低)。\r\n useEffect(() => {\r\n const body = bodyRef.current\r\n if (body === null || typeof ResizeObserver === 'undefined') return\r\n let raf = 0\r\n const observer = new ResizeObserver(() => {\r\n if (raf !== 0) return\r\n raf = window.requestAnimationFrame(() => {\r\n raf = 0\r\n recomputePins()\r\n })\r\n })\r\n observer.observe(body)\r\n return () => {\r\n observer.disconnect()\r\n if (raf !== 0) window.cancelAnimationFrame(raf)\r\n }\r\n }, [renderedHtml, html, recomputePins])\r\n\r\n // 选区 → 取色工具条。mouseup / keyup / selectionchange 都要看(拖选、双击选词、\r\n // 三击选段、Shift+方向键 都是不同来源),同一帧只算一次。\r\n useEffect(() => {\r\n const body = bodyRef.current\r\n if (body === null || renderedHtml !== html) return\r\n let raf = 0\r\n const read = (): void => {\r\n raf = 0\r\n const s = window.getSelection()\r\n if (s === null || s.rangeCount === 0 || s.isCollapsed) {\r\n setSel(null)\r\n return\r\n }\r\n const range = s.getRangeAt(0)\r\n if (!body.contains(range.commonAncestorContainer)) {\r\n setSel(null)\r\n return\r\n }\r\n const anchor = anchorFromRange(body, range)\r\n if (anchor === null) {\r\n setSel(null)\r\n return\r\n }\r\n const rect = range.getBoundingClientRect()\r\n if (rect.width === 0 && rect.height === 0) {\r\n setSel(null)\r\n return\r\n }\r\n setSel({ x: rect.left + rect.width / 2, y: rect.top, anchor })\r\n }\r\n const schedule = (e: Event): void => {\r\n // 自己控件上的鼠标事件不重算:点工具条时选区还在,但已经不需要再跟了。\r\n const target = e.target\r\n if (target instanceof Element && target.closest('[data-aero-mark-ui]') !== null) return\r\n if (raf !== 0) return\r\n raf = window.requestAnimationFrame(read)\r\n }\r\n document.addEventListener('mouseup', schedule)\r\n document.addEventListener('keyup', schedule)\r\n document.addEventListener('selectionchange', schedule)\r\n const container = containerRef.current\r\n // 正文一滚就收起工具条与编辑浮层:两者都是「贴着某段文字」的 fixed 浮层,\r\n // 文字滚走之后会指错地方。浮层里的文字在卸载时自动补交(见 NoteEditor)。\r\n const onScroll = (): void => {\r\n setSel(null)\r\n setEditor(null)\r\n }\r\n container?.addEventListener('scroll', onScroll, { passive: true })\r\n return () => {\r\n document.removeEventListener('mouseup', schedule)\r\n document.removeEventListener('keyup', schedule)\r\n document.removeEventListener('selectionchange', schedule)\r\n container?.removeEventListener('scroll', onScroll)\r\n if (raf !== 0) window.cancelAnimationFrame(raf)\r\n }\r\n }, [renderedHtml, html])\r\n\r\n const clearSelection = useCallback((): void => {\r\n window.getSelection()?.removeAllRanges()\r\n setSel(null)\r\n }, [])\r\n\r\n /** 取色/划线:直接落一条标记(同一段已有标记则改它,不叠两条)。 */\r\n const applyMark = useCallback((color: AnnoColor, style: AnnoStyle): void => {\r\n if (sel === null) return\r\n paintAnnotation(docKey, sel.anchor, color, style, '')\r\n clearSelection()\r\n }, [sel, docKey, clearSelection])\r\n\r\n /** 写想法:先落一条荧光黄标记,绘制完成后自动打开它的编辑浮层。 */\r\n const applyNote = useCallback((): void => {\r\n if (sel === null) return\r\n const anno = paintAnnotation(docKey, sel.anchor, 'yellow', 'highlight', '')\r\n pendingEditorRef.current = anno.id\r\n clearSelection()\r\n }, [sel, docKey, clearSelection])\r\n\r\n /** 定位到某条标注并打开浮层(点击 mark / 批注圆点 / 面板条目共用)。 */\r\n const openEditorFor = useCallback((id: string): void => {\r\n const body = bodyRef.current\r\n if (body === null) return\r\n const rect = markRectOf(body, id)\r\n if (rect !== null) setEditor({ id, ...popoverAt(rect) })\r\n }, [])\r\n\r\n const currentAnno = useMemo(\r\n () => (editor === null ? null : annos.find((a) => a.id === editor.id) ?? null),\r\n [editor, annos],\r\n )\r\n\r\n const patchAnno = useCallback((patch: AnnotationPatch): void => {\r\n if (editor === null) return\r\n updateAnnotation(docKey, editor.id, patch)\r\n }, [docKey, editor])\r\n\r\n const deleteAnno = useCallback((id: string): void => {\r\n removeAnnotation(docKey, id)\r\n setEditor(null)\r\n }, [docKey])\r\n\r\n /** 问 AI:把标注原文 + 自己的想法交给工作台(各台自己拼阅读上下文并发送)。 */\r\n const askAnno = useCallback((quote: string, note: string): void => {\r\n onAsk?.(annotationQuestion(quote, note))\r\n }, [onAsk])\r\n\r\n // Esc 收尾:浮层 / 工具条 / 面板任一打开时先关它,不惊动阅读器的其它 Esc 行为。\r\n useEffect(() => {\r\n if (sel === null && editor === null && !panelOpen) return\r\n const onKey = (e: KeyboardEvent): void => {\r\n if (e.key !== 'Escape') return\r\n e.preventDefault()\r\n e.stopPropagation()\r\n clearSelection()\r\n setEditor(null)\r\n setPanelOpen(false)\r\n }\r\n window.addEventListener('keydown', onKey, true)\r\n return () => window.removeEventListener('keydown', onKey, true)\r\n }, [sel, editor, panelOpen, clearSelection])\r\n\r\n useEffect(() => {\r\n const container = containerRef.current\r\n if (container === null || renderedHtml !== html) return\r\n\r\n const headings = Array.from(\r\n container.querySelectorAll<HTMLElement>('h1[id],h2[id],h3[id],h4[id],h5[id],h6[id]'),\r\n )\r\n\r\n const emitFor = (h: HTMLElement | null) => {\r\n if (h === null) {\r\n const text = container.textContent ?? ''\r\n onReadingRef.current({ relPath, title: result.title, section: result.title, excerpt: truncate(text, 900) })\r\n return\r\n }\r\n const sectionTitle = (h.textContent ?? '').replace(/\\s+/g, ' ').trim()\r\n onReadingRef.current({ relPath, title: result.title, section: sectionTitle, excerpt: truncate(sectionExcerpt(h), 900) })\r\n }\r\n\r\n if (headings.length === 0) {\r\n emitFor(null)\r\n return\r\n }\r\n\r\n let current: HTMLElement | null = null\r\n let raf: number | null = null\r\n // 滚动跟踪:一帧只算一次(rAF 合并同一帧的多个 scroll 事件),\r\n // 且容器矩形只读一次——早期版本在每个标题上各读一次容器矩形,\r\n // 长文档(数百个标题、数万节点)每次滚动都触发成百上千次强制重排。\r\n const measure = (): void => {\r\n raf = null\r\n const containerTop = container.getBoundingClientRect().top\r\n const scrollTop = container.scrollTop\r\n const line = Math.min(120, container.clientHeight * 0.25)\r\n let target: HTMLElement | null = null\r\n for (const h of headings) {\r\n if (h.getBoundingClientRect().top - containerTop + scrollTop <= scrollTop + line) target = h\r\n else break\r\n }\r\n if (target !== current) {\r\n current = target\r\n emitFor(target)\r\n setActiveId(target === null ? null : target.id)\r\n }\r\n }\r\n const onScroll = (): void => {\r\n if (raf !== null) return\r\n raf = window.requestAnimationFrame(measure)\r\n }\r\n\r\n container.addEventListener('scroll', onScroll, { passive: true })\r\n measure()\r\n return () => {\r\n container.removeEventListener('scroll', onScroll)\r\n if (raf !== null) window.cancelAnimationFrame(raf)\r\n }\r\n }, [relPath, html, renderedHtml, result.title])\r\n\r\n // 放大视图:Esc 关闭\r\n useEffect(() => {\r\n if (zoom === null) return\r\n const onKey = (e: KeyboardEvent): void => {\r\n if (e.key === 'Escape') setZoom(null)\r\n }\r\n window.addEventListener('keydown', onKey)\r\n return () => window.removeEventListener('keydown', onKey)\r\n }, [zoom])\r\n\r\n const onDocClick = useCallback((e: React.MouseEvent<HTMLDivElement>): void => {\r\n const target = e.target as HTMLElement\r\n // 点已有的荧光标记 → 打开它的编辑浮层(改色 / 切线 / 写想法 / 删除 / 问 AI)\r\n const mark = target.closest('mark.aero-anno')\r\n if (mark !== null) {\r\n const id = mark.getAttribute('data-anno')\r\n if (id !== null && id !== '') setEditor({ id, ...popoverAt(mark.getBoundingClientRect()) })\r\n return\r\n }\r\n // 图放大:点击带 data-aero-zoom 的正文图\r\n if (target.tagName === 'IMG' && target.hasAttribute('data-aero-zoom')) {\r\n const block = target.closest('.imageblock')\r\n const caption = block?.querySelector('.aero-caption')?.textContent ?? target.getAttribute('alt') ?? ''\r\n setZoom({ src: (target as HTMLImageElement).src, caption: caption.replace(/\\s+/g, ' ').trim() })\r\n return\r\n }\r\n const a = target.closest('a[data-kbdoc]')\r\n if (a === null) return\r\n e.preventDefault()\r\n const rel = a.getAttribute('data-kbdoc')\r\n if (rel !== null && rel.length > 0 && onOpenDoc !== undefined) onOpenDoc(rel)\r\n }, [onOpenDoc])\r\n\r\n /** 目录跳转:滚到标题(留 12px 呼吸位),滚动本身会刷新阅读上下文与高亮。 */\r\n const gotoSection = useCallback((id: string): void => {\r\n const container = containerRef.current\r\n if (container === null) return\r\n const el = container.querySelector<HTMLElement>(`[id=\"${CSS.escape(id)}\"]`)\r\n if (el === null) return\r\n const top = el.getBoundingClientRect().top - container.getBoundingClientRect().top + container.scrollTop - 12\r\n container.scrollTo({ top: Math.max(0, top), behavior: 'smooth' })\r\n setActiveId(id)\r\n }, [])\r\n\r\n const chips = useMemo(() => metaChips(meta), [meta])\r\n // 面板与目录互斥:正文右侧一次只放一栏(窄屏时两栏会挤掉正文)。\r\n const showPanel = panelOpen\r\n const showOutline = prefs.outlineOpen && outline.length >= 3 && !showPanel\r\n const noteCount = useMemo(() => annos.filter((a) => a.note.trim() !== '').length, [annos])\r\n // 悬浮入口的右偏移:躲开右侧那一栏(目录 206 / 面板 300),两栏都关时贴边。\r\n const fabRight = showPanel ? MARKS_PANEL_WIDTH + 14 : (showOutline ? OUTLINE_WIDTH + 14 : 14)\r\n\r\n return (\r\n <div ref={wrapRef} className={css.docWrap} data-aero-doc-wrap=\"\" data-paper={prefs.paper} data-segbar={hasSegments ? '1' : '0'}>\r\n <div ref={containerRef} className={css.docScroll}>\r\n {/* 超长文档分段导航(宿主按渲染体积切段,见 src/docsplit.ts):\r\n 粘在滚动容器顶部,翻段不丢位置,也能直接跳到任意一段。 */}\r\n {hasSegments && (\r\n <div className={css.docSegBar} data-aero-segbar=\"\">\r\n <button\r\n type=\"button\"\r\n className={css.docSegBtn}\r\n onClick={() => onOpenSegment?.(seg - 1)}\r\n disabled={seg <= 0 || onOpenSegment === undefined}\r\n title=\"上一段\"\r\n >\r\n 上一段\r\n </button>\r\n <span className={css.docSegInfo} title={segments[seg]?.title ?? ''}>\r\n 第 {seg + 1} / {segments.length} 段\r\n {segments[seg]?.title !== undefined && segments[seg]!.title !== '' ? ` · ${segments[seg]!.title}` : ''}\r\n </span>\r\n <select\r\n className={css.docSegSelect}\r\n value={String(seg)}\r\n onChange={(e) => onOpenSegment?.(Number(e.target.value))}\r\n disabled={onOpenSegment === undefined}\r\n title=\"跳转到指定段\"\r\n >\r\n {segments.map((s) => (\r\n <option key={s.index} value={String(s.index)}>\r\n 第 {s.index + 1} 段 · {s.title}\r\n </option>\r\n ))}\r\n </select>\r\n <button\r\n type=\"button\"\r\n className={css.docSegBtn}\r\n onClick={() => onOpenSegment?.(seg + 1)}\r\n disabled={seg >= segments.length - 1 || onOpenSegment === undefined}\r\n title=\"下一段\"\r\n >\r\n 下一段\r\n </button>\r\n </div>\r\n )}\r\n {/* 阅读偏好以 data-* / 内联变量交给 doc-theme.css 解析(见该文件「用户阅读偏好」小节):\r\n 字号倍率、字体族、行距、版心宽度、底色都在那一处集中定义,避免样式散进 TSX。\r\n 字号额外走内联的 --aero-scale:倍率表(FONT_STEPS)是唯一真源,CSS 只做乘法,\r\n 加档位时不必同步改样式表(data-scale 仅作调试/回溯用)。 */}\r\n <article\r\n className={prefs.layout === 'book' ? 'aero-doc aero-doc--book' : 'aero-doc aero-doc--web'}\r\n data-scale={String(Math.round((FONT_STEPS[prefs.fontStep] ?? 1) * 100))}\r\n style={{ '--aero-scale': String(FONT_STEPS[prefs.fontStep] ?? 1) } as CSSProperties}\r\n data-font={prefs.font}\r\n data-leading={prefs.leading}\r\n data-measure={prefs.measure}\r\n data-paper={prefs.paper}\r\n >\r\n {chips.length > 0 && (\r\n <header className={css.docMeta}>\r\n <div className={css.docMetaKicker}>{kickerOf(relPath)}</div>\r\n <div className={css.docMetaChips}>\r\n {chips.map((c) => (\r\n <span key={c.key} className={css.docMetaChip} data-tone={c.tone ?? 'plain'} title={`${c.label}:${c.value}`}>\r\n <span className={css.docMetaChipLabel}>{c.label}</span>\r\n {c.value}\r\n </span>\r\n ))}\r\n </div>\r\n {meta?.attrs['kb-keywords'] !== undefined && meta.attrs['kb-keywords'].trim() !== '' && (\r\n <div className={css.docMetaKeywords}>\r\n {meta.attrs['kb-keywords'].split(';').map((k) => k.trim()).filter((k) => k !== '').map((k) => (\r\n <span key={k} className={css.docMetaKeyword}>{k}</span>\r\n ))}\r\n </div>\r\n )}\r\n </header>\r\n )}\r\n {/* 正文由分片注入 effect 填充(React 不管这块子节点,避免整体重排)。 */}\r\n <div ref={bodyRef} className=\"aero-doc-body\" onClick={onDocClick} />\r\n {renderedHtml !== html && (\r\n <div className={css.docRendering} data-aero-rendering=\"\">正在排版…</div>\r\n )}\r\n </article>\r\n\r\n {/* 批注圆点:放在滚动容器内,随正文一起滚(坐标由 notePins 换算到内容坐标)。\r\n 面板打开时不画——右缘已经被面板占了。 */}\r\n {!showPanel && <NotePinLayer pins={pins} onOpen={openEditorFor} />}\r\n </div>\r\n\r\n {/* 「已回到上次读到处」回执:切回一份读过的文档时,正文直接落回上次的位置,\r\n 这一条只是告诉人「为什么不是开头」,并给一次「从头读」的反悔机会。\r\n 它绝对定位、不占版心(正文行宽/字号不能因为一条提示而变),也不会盖住分段条。 */}\r\n {resume !== null && (\r\n <div className={css.docResume} data-aero-resume=\"\">\r\n <span className={css.docResumeText} role=\"status\">\r\n 已回到上次读到处\r\n {resume.label !== '' && <span className={css.docResumeName}>{resume.label}</span>}\r\n <span className={css.docResumeAge}>{describeAge(resume.at)}</span>\r\n </span>\r\n <button\r\n type=\"button\"\r\n className={css.docResumeBtn}\r\n onClick={readFromTop}\r\n title=\"滚到开头,并忘掉这份文档的阅读位置\"\r\n >\r\n 从头读\r\n </button>\r\n <button\r\n type=\"button\"\r\n className={css.docResumeClose}\r\n onClick={() => setResume(null)}\r\n title=\"知道了(阅读位置继续保留)\"\r\n aria-label=\"关闭提示\"\r\n >\r\n <CloseIcon size={11} />\r\n </button>\r\n </div>\r\n )}\r\n\r\n {showPanel && (\r\n <MarksPanel\r\n title={result.title}\r\n annos={annos}\r\n exportKey={docKey}\r\n showPage={false}\r\n onLocate={(anno) => {\r\n const body = bodyRef.current\r\n if (body !== null) scrollToAnnotation(body, anno.id)\r\n }}\r\n onAsk={onAsk === undefined ? null : (anno) => askAnno(anno.quote, anno.note)}\r\n onDelete={(anno) => deleteAnno(anno.id)}\r\n onClear={() => {\r\n for (const anno of annos) removeAnnotation(docKey, anno.id)\r\n setEditor(null)\r\n }}\r\n onClose={() => setPanelOpen(false)}\r\n />\r\n )}\r\n\r\n {showOutline && (\r\n <nav className={css.docOutline} aria-label=\"本页目录\">\r\n <div className={css.docOutlineHead}>\r\n <ListIcon size={12} />\r\n <span>本页目录</span>\r\n </div>\r\n <ul className={css.docOutlineList}>\r\n {outline.map((s) => {\r\n const no = sectionNos?.get(s.id)\r\n // 作者手写的「1. 」在正文里已被替换成统一编号,目录里同步摘掉,避免出现两个号。\r\n const label = stripManualSectionNo(s.title)\r\n return (\r\n <li key={s.id} className={css.docOutlineItem} data-level={Math.min(s.level, 4)}>\r\n <button\r\n type=\"button\"\r\n className={activeId === s.id ? `${css.docOutlineLink} ${css.docOutlineLinkActive}` : css.docOutlineLink}\r\n onClick={() => gotoSection(s.id)}\r\n title={no === undefined ? label : `${no}. ${label}`}\r\n >\r\n {no !== undefined && <span className={css.docOutlineNo}>{`${no}. `}</span>}\r\n {label}\r\n </button>\r\n </li>\r\n )\r\n })}\r\n </ul>\r\n </nav>\r\n )}\r\n\r\n {zoom !== null && (\r\n <div className={css.docLightbox} role=\"dialog\" aria-modal=\"true\" onClick={() => setZoom(null)}>\r\n <figure className={css.docLightboxFigure}>\r\n <img src={zoom.src} alt={zoom.caption} />\r\n {zoom.caption !== '' && <figcaption className={css.docLightboxCap}>{zoom.caption}</figcaption>}\r\n </figure>\r\n <div className={css.docLightboxHint}>\r\n <CloseIcon size={11} /> 点击任意处或按 Esc 关闭\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* 标注入口:右下角悬浮笔。学生第一眼要能看见「这里可以标记」。 */}\r\n <MarksFab\r\n count={annos.length}\r\n noted={noteCount}\r\n open={showPanel}\r\n right={fabRight}\r\n onClick={() => {\r\n setPanelOpen((open) => !open)\r\n setEditor(null)\r\n clearSelection()\r\n }}\r\n />\r\n\r\n {/* 选中正文 → 选区上方的取色工具条 */}\r\n {sel !== null && (\r\n <SelectionBar\r\n sel={sel}\r\n onPick={applyMark}\r\n onNote={applyNote}\r\n onAsk={onAsk === undefined ? null : () => askAnno(sel.anchor.quote, '')}\r\n onDismiss={clearSelection}\r\n />\r\n )}\r\n\r\n {/* 点已有标记 / 写想法 → 编辑浮层 */}\r\n {editor !== null && currentAnno !== null && (\r\n <NoteEditor\r\n key={editor.id}\r\n anno={currentAnno}\r\n at={editor}\r\n onPatch={patchAnno}\r\n onDelete={() => deleteAnno(editor.id)}\r\n onAsk={onAsk === undefined ? null : (note) => askAnno(currentAnno.quote, note)}\r\n onClose={() => setEditor(null)}\r\n />\r\n )}\r\n </div>\r\n )\r\n}\r\n","/**\r\n * Slidev 环境体检面板。\r\n *\r\n * 课件「一直显示正在准备」的根因几乎都在宿主机环境(缺 @slidev/cli、版本过旧、\r\n * 主题依赖没装)。本面板把后端体检结果摊开给用户看:缺什么、为什么、怎么修;\r\n * 并且**只有在用户于确认框中明确同意后**才调用一键安装接口\r\n * (POST /aero-kb/slidev/env,带体检返回的同意票据)。\r\n */\r\nimport { useCallback, useEffect, useState } from 'react'\r\nimport type { SlidevEnvAction, SlidevEnvFixResult, SlidevEnvReport } from '../types.js'\r\nimport { CheckIcon, CopyIcon, DownloadIcon, RefreshIcon } from './icons.js'\r\nimport css from './styles.module.css.gen.ts'\r\n\r\ninterface Props {\r\n /** 课件 slides.md 相对路径(用于追加该课件的主题/依赖检查)。 */\r\n relPath: string\r\n /** 形如 `&cwd=…` 的查询串(可为空串)。 */\r\n cwdParam: string\r\n /** 体检通过后回调(上层可据此重挂载播放器)。 */\r\n onReady?: () => void\r\n}\r\n\r\ninterface EnvResponse {\r\n ok: boolean\r\n report?: SlidevEnvReport\r\n error?: string\r\n}\r\n\r\nconst STATUS_TEXT: Record<string, string> = { ok: '正常', warn: '注意', fail: '缺失' }\r\n\r\nasync function fetchEnv(relPath: string, cwdParam: string, force: boolean): Promise<SlidevEnvReport> {\r\n const qs = `?p=${encodeURIComponent(relPath)}${cwdParam}${force ? '&force=1' : ''}`\r\n const r = await fetch(`/aero-kb/slidev/env${qs}`)\r\n const body = (await r.json()) as EnvResponse\r\n if (!r.ok || !body.ok || body.report === undefined) {\r\n throw new Error(body.error !== undefined && body.error !== '' ? body.error : `HTTP ${r.status}`)\r\n }\r\n return body.report\r\n}\r\n\r\n/** 确认框里展示的「将要执行的命令与写入位置」——用户点确认前必须看到这些。 */\r\nfunction describeAction(a: SlidevEnvAction): string {\r\n return [\r\n `即将执行:${a.command}`,\r\n a.cwd !== '' ? `执行目录:${a.cwd}` : '执行目录:宿主机当前目录',\r\n `写入范围:${a.writes}`,\r\n a.scope === 'global' ? '⚠️ 这是全局安装,会修改本机 npm 全局环境(影响所有项目)。' : '仅影响本仓库内文件。',\r\n '',\r\n '确认执行吗?',\r\n ].join('\\n')\r\n}\r\n\r\nexport function SlidevEnvPanel({ relPath, cwdParam, onReady }: Props): JSX.Element {\r\n const [report, setReport] = useState<SlidevEnvReport | null>(null)\r\n const [error, setError] = useState<string | null>(null)\r\n const [busy, setBusy] = useState(false)\r\n const [running, setRunning] = useState('')\r\n const [output, setOutput] = useState('')\r\n const [copied, setCopied] = useState('')\r\n\r\n const load = useCallback(async (force: boolean) => {\r\n setBusy(true)\r\n setError(null)\r\n try {\r\n const r = await fetchEnv(relPath, cwdParam, force)\r\n setReport(r)\r\n } catch (e) {\r\n setError(e instanceof Error ? e.message : String(e))\r\n } finally {\r\n setBusy(false)\r\n }\r\n }, [relPath, cwdParam])\r\n\r\n useEffect(() => {\r\n void load(false)\r\n }, [load])\r\n\r\n const copy = useCallback((text: string) => {\r\n const done = (): void => {\r\n setCopied(text)\r\n window.setTimeout(() => setCopied(''), 1500)\r\n }\r\n try {\r\n void navigator.clipboard.writeText(text).then(done, () => { /* 剪贴板不可用时静默 */ })\r\n } catch {\r\n /* 忽略 */\r\n }\r\n }, [])\r\n\r\n const install = useCallback(async (action: SlidevEnvAction) => {\r\n // 同意关口:把命令与写入范围摆给用户,确认前不发任何请求。\r\n if (!window.confirm(describeAction(action))) return\r\n setRunning(action.id)\r\n setOutput('')\r\n setError(null)\r\n try {\r\n const r = await fetch(`/aero-kb/slidev/env?p=${encodeURIComponent(relPath)}${cwdParam}`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ actionId: action.id, token: action.token, confirm: true, p: relPath }),\r\n })\r\n const body = (await r.json()) as { ok: boolean; result?: SlidevEnvFixResult; error?: string }\r\n if (!r.ok || !body.ok || body.result === undefined) throw new Error(body.error !== undefined && body.error !== '' ? body.error : `HTTP ${r.status}`)\r\n setOutput(body.result.output)\r\n setReport(body.result.report)\r\n if (!body.result.ok) setError(`安装未成功(退出码 ${String(body.result.code)}):${body.result.error}`)\r\n else if (body.result.report.ready) onReady?.()\r\n } catch (e) {\r\n setError(e instanceof Error ? e.message : String(e))\r\n } finally {\r\n setRunning('')\r\n }\r\n }, [relPath, cwdParam, onReady])\r\n\r\n const failing = report?.checks.filter((c) => c.status === 'fail') ?? []\r\n const warnOnly = report !== null && report.ready && report.checks.some((c) => c.status === 'warn')\r\n\r\n return (\r\n <div className={css.envRoot}>\r\n <div className={css.envCard}>\r\n <div className={css.envHead}>\r\n <span className={css.envTitle}>Slidev 环境体检</span>\r\n <span className={css.deckSpacer} />\r\n <button className={css.btn} onClick={() => { void load(true) }} disabled={busy || running !== ''} title=\"重新探测本机环境\">\r\n <RefreshIcon size={12} /> {busy ? '检查中…' : '重新检查'}\r\n </button>\r\n </div>\r\n\r\n {report === null && error === null && <div className={css.envMuted}>正在检查本机 Slidev 构建环境…</div>}\r\n {error !== null && <div className={css.envError}>{error}</div>}\r\n\r\n {report !== null && (\r\n <>\r\n <div className={report.ready ? css.envSummaryOk : css.envSummaryBad}>\r\n {report.ready\r\n ? (warnOnly ? '✅ 构建链就绪(有注意事项,见下)' : '✅ 本机 Slidev 构建环境就绪')\r\n : '❌ 本机 Slidev 构建环境不完整,课件无法渲染'}\r\n {!report.ready && report.summary !== '' && <div className={css.envSummaryDetail}>{report.summary}</div>}\r\n </div>\r\n\r\n <ul className={css.envList}>\r\n {report.checks.map((c) => (\r\n <li key={c.id} className={css.envItem}>\r\n <span className={c.status === 'ok' ? css.envDotOk : c.status === 'warn' ? css.envDotWarn : css.envDotFail}>\r\n {c.status === 'ok' ? <CheckIcon size={10} /> : '!'}\r\n </span>\r\n <span className={css.envItemBody}>\r\n <span className={css.envItemLabel}>\r\n {c.label}\r\n <span className={css.envItemStatus}>{STATUS_TEXT[c.status] ?? c.status}</span>\r\n </span>\r\n <span className={css.envItemDetail}>{c.detail}</span>\r\n {c.hint !== '' && <span className={css.envItemHint}>建议:{c.hint}</span>}\r\n </span>\r\n </li>\r\n ))}\r\n </ul>\r\n\r\n {failing.length > 0 && report.actions.length === 0 && (\r\n <div className={css.envMuted}>以上缺失项需要在宿主机手动处理后重新检查。</div>\r\n )}\r\n\r\n {report.actions.length > 0 && (\r\n <div className={css.envActions}>\r\n <div className={css.envActionsTitle}>可代为准备(需你确认后才会执行)</div>\r\n {report.actions.map((a) => (\r\n <div key={a.id} className={css.envAction}>\r\n <div className={css.envActionInfo}>\r\n <div className={css.envActionLabel}>{a.label}</div>\r\n <div className={css.envItemDetail}>{a.reason}</div>\r\n <div className={css.envActionCmd}>\r\n <code>{a.cwd === '' ? a.command : `cd \"${a.cwd}\" && ${a.command}`}</code>\r\n <button className={css.envCopy} onClick={() => copy(a.cwd === '' ? a.command : `cd \"${a.cwd}\"; ${a.command}`)} title=\"复制命令自行执行\">\r\n <CopyIcon size={11} /> {copied === (a.cwd === '' ? a.command : `cd \"${a.cwd}\"; ${a.command}`) ? '已复制' : '复制'}\r\n </button>\r\n </div>\r\n <div className={css.envItemHint}>\r\n {a.scope === 'global' ? '⚠️ ' : ''}写入范围:{a.writes}\r\n </div>\r\n </div>\r\n <button\r\n className={css.btnPrimary}\r\n disabled={a.disabled || running !== ''}\r\n title={a.disabled ? a.disabledReason : '弹出确认框,确认后在本机执行安装'}\r\n onClick={() => { void install(a) }}\r\n >\r\n <DownloadIcon size={12} /> {running === a.id ? '安装中…' : '一键安装'}\r\n </button>\r\n </div>\r\n ))}\r\n {running !== '' && (\r\n <div className={css.envMuted}>\r\n <span className={css.spinner} /> 正在执行安装(全局安装视网络可能需要 1–3 分钟)…\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {output !== '' && (\r\n <details className={css.envDetails}>\r\n <summary>安装日志</summary>\r\n <pre className={css.deckLog}>{output}</pre>\r\n </details>\r\n )}\r\n </>\r\n )}\r\n </div>\r\n </div>\r\n )\r\n}\r\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport type { SlidevMetaResponse } from '../types.js'\nimport type { ReadingContext } from './prose.js'\nimport {\n addPageAnnotation, buildTextIndex, deckKeyOf, rangeFromOffsets, removeAnnotation,\n updateAnnotation, useAnnotations, MAX_QUOTE_CHARS,\n type AnnoColor, type AnnoStyle, type Annotation, type AnnotationPatch,\n} from './annotations.js'\nimport {\n MarksPanel, NoteEditor, SelectionBar, annotationQuestion, popoverAt,\n type EditorState, type SelectionState,\n} from './DocMarks.js'\nimport { ExternalIcon, MonitorIcon, PenIcon, RefreshIcon } from './icons.js'\nimport { SlidevEnvPanel } from './SlidevEnvPanel.js'\nimport css from './styles.module.css.gen.ts'\n\n/** 构建等待上限:超过则提示(首次构建需复制主题镜像 + vite 打包)。 */\nconst BUILD_WAIT_MAX_MS = 9 * 60_000\n\n/** 课件页内高亮的叠加层标记(注入 iframe,样式见 ensureDeckStyle)。 */\nconst LAYER_ATTR = 'data-aero-deck-layer'\n\ninterface Props {\n relPath: string\n /** 目录树里展示的课件名(取 slides.md 前置 YAML 的 title)。 */\n name: string\n /** 形如 `&cwd=…` 的查询串(可为空串)。 */\n cwdParam: string\n onReadingChange: (ctx: ReadingContext) => void\n /** 「问 AI」出口(与 DocViewer 同一约定):不传则不显示问 AI 按钮。 */\n onAsk?: (text: string) => void\n}\n\n/** 拉取 Slidev 课件构建状态(rebuild=1 表示强制重建)。 */\nasync function fetchMeta(relPath: string, cwdParam: string, rebuild: boolean): Promise<SlidevMetaResponse> {\n const qs = `?p=${encodeURIComponent(relPath)}${cwdParam}${rebuild ? '&rebuild=1' : ''}`\n const r = await fetch(`/aero-kb/slidev/meta${qs}`)\n const body = (await r.json()) as SlidevMetaResponse\n if (!r.ok || !body.ok) {\n throw new Error(body.error !== '' ? body.error : `HTTP ${r.status}`)\n }\n return body\n}\n\n// ---------------------------------------------------------------------------\n// 课件标注的 DOM 侧(都在 iframe 文档内操作)\n//\n// 课件改不动 DOM:Slidev 是 Vue 应用,往幻灯片里塞 <mark> 会让它的 vnode 与真实\n// DOM 失配(切页后文字错位)。因此课件标注**不碰幻灯片内容**,只在其上盖一层\n// `position:fixed` 的半透明色块——用 Range.getClientRects() 量出选中文字的每一行\n// 矩形,再把色块贴上去。Slidev 自己怎么重排、动效怎么跑都不受影响。\n// ---------------------------------------------------------------------------\n\nconst DECK_STYLE = `\n[${LAYER_ATTR}] { position: fixed; inset: 0; pointer-events: none; z-index: 40; }\n[${LAYER_ATTR}] > i {\n position: fixed; display: block; border-radius: 3px;\n mix-blend-mode: multiply;\n background: var(--aero-deck-mark, #ffe06699);\n}\n[${LAYER_ATTR}] > i[data-style='underline'] {\n height: 3px !important; border-radius: 2px; mix-blend-mode: normal;\n background: var(--aero-deck-mark, #ffe066);\n}\n[${LAYER_ATTR}] > i[data-color='yellow'] { --aero-deck-mark: #ffe06699; }\n[${LAYER_ATTR}] > i[data-color='green'] { --aero-deck-mark: #9fe08c99; }\n[${LAYER_ATTR}] > i[data-color='blue'] { --aero-deck-mark: #8ccbf799; }\n[${LAYER_ATTR}] > i[data-color='pink'] { --aero-deck-mark: #f7a8c499; }\n/**\n * 让幻灯片里的文字**可以选中**。\n *\n * Slidev 给 .slidev-page 设了 user-select:none(放映时点击翻页不希望顺手选中文字),\n * 于是学生根本拖不出选区——课件标注必须有这一条覆盖,否则整条链路在真机上不成立\n * (实测:range 建得出来,但 selection.toString() 恒为空)。隐藏的 v-click 元素保持\n * 不可选,免得选中看不见的内容。\n */\n.slidev-page, .slidev-page * {\n -webkit-user-select: text !important;\n user-select: text !important;\n}\n.slidev-page .slidev-vclick-hidden, .slidev-page .slidev-vclick-hidden * {\n -webkit-user-select: none !important;\n user-select: none !important;\n}\n`\n\n/** 给 iframe 文档装上叠加层与样式(幂等;样式内容一律按当前代码覆盖)。 */\nfunction ensureLayer(doc: Document): HTMLElement {\n if (doc.head !== null) {\n const existing = doc.head.querySelector<HTMLStyleElement>('style[data-aero-deck-style]')\n if (existing === null) {\n const style = doc.createElement('style')\n style.setAttribute('data-aero-deck-style', '')\n style.textContent = DECK_STYLE\n doc.head.appendChild(style)\n } else if (existing.textContent !== DECK_STYLE) {\n // 与 prose.ts 的 upsertStyle 同理:整页刷新后旧样式还在,不覆盖就永远用上一代。\n existing.textContent = DECK_STYLE\n }\n }\n let layer = doc.body.querySelector<HTMLElement>(`[${LAYER_ATTR}]`)\n if (layer === null) {\n layer = doc.createElement('div')\n layer.setAttribute(LAYER_ATTR, '')\n doc.body.appendChild(layer)\n }\n return layer\n}\n\n/**\n * 在当前页里找 quote 的可见矩形。\n *\n * 「当前页」不靠类名判断:Slidev 各版本/主题的页容器类名不一样(`.slidev-page`、\n * `.slidev-slide`、自定义布局…),而**所有渲染出来的矩形**只有当前页落在视口内\n * (其余页 display:none 或被平移出视口)。因此:全文找匹配 → 量矩形 → 只留视口内的。\n */\nfunction findQuoteRects(doc: Document, quote: string): DOMRect[] {\n const needle = quote.replace(/\\s+/g, ' ').trim()\n if (needle === '') return []\n const body = doc.body\n if (body === null) return []\n const index = buildTextIndex(body)\n const win = doc.defaultView\n if (win === null) return []\n const w = win.innerWidth\n const h = win.innerHeight\n let from = 0\n let tries = 0\n while (tries < 40) {\n const at = index.text.indexOf(needle, from)\n if (at < 0) break\n tries++\n const range = rangeFromOffsets(index, at, at + needle.length, doc)\n if (range !== null) {\n const rects = Array.from(range.getClientRects()).filter(\n (r) => r.width > 2 && r.height > 2 && r.right > 0 && r.bottom > 0 && r.left < w && r.top < h,\n )\n if (rects.length > 0) return rects\n }\n from = at + 1\n }\n return []\n}\n\n/** 重画当前页的全部标注色块。 */\nfunction paintDeck(doc: Document, page: number, annos: readonly Annotation[]): void {\n const layer = ensureLayer(doc)\n layer.textContent = ''\n if (page <= 0) return\n const mine = annos.filter((a) => a.page === page)\n if (mine.length === 0) return\n for (const anno of mine) {\n const rects = findQuoteRects(doc, anno.quote)\n for (const rect of rects) {\n const box = doc.createElement('i')\n box.setAttribute('data-anno', anno.id)\n box.setAttribute('data-color', anno.color)\n box.setAttribute('data-style', anno.style)\n box.style.left = `${String(Math.round(rect.left))}px`\n box.style.top = `${String(Math.round(rect.top))}px`\n box.style.width = `${String(Math.round(rect.width))}px`\n box.style.height = `${String(Math.round(rect.height))}px`\n layer.appendChild(box)\n }\n }\n}\n\n/**\n * Slidev 课件播放器:宿主按需构建出静态 SPA(/aero-kb/slidev/<key>/),\n * 右侧 iframe 嵌入放映视图;支持新窗口/演讲者视图/重新构建。\n *\n * 阅读标注:iframe 与宿主同源,因此可以直接读其中的选区、并在其上盖一层色块\n * (见上面 DOM 段的说明)。标注按**页**锚定——课件的内容随翻页整体替换,\n * 「文本偏移」在课件里没有意义,页号 + 原文才是稳定的坐标。\n *\n * 构建链缺失(no-toolchain)或构建失败时**不再停在「正在准备」转圈**:\n * 展开「Slidev 环境体检」面板,逐项说明缺什么,并在用户确认后代为安装。\n */\nexport function SlidevDeckViewer({ relPath, name, cwdParam, onReadingChange, onAsk }: Props): JSX.Element {\n const [meta, setMeta] = useState<SlidevMetaResponse | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [frameKey, setFrameKey] = useState(0)\n const [envOpen, setEnvOpen] = useState(false)\n const iframeRef = useRef<HTMLIFrameElement | null>(null)\n const startedRef = useRef(Date.now())\n /** 当前放映页(1 起;0 = 还没读到)。 */\n const [page, setPage] = useState(0)\n const deckKey = deckKeyOf(relPath)\n const annos = useAnnotations(deckKey)\n const annosRef = useRef(annos)\n annosRef.current = annos\n const [sel, setSel] = useState<SelectionState | null>(null)\n const [editor, setEditor] = useState<EditorState | null>(null)\n const [panelOpen, setPanelOpen] = useState(false)\n\n /** iframe 里当前的选中文案(父窗口坐标系下的落点一并给出)。 */\n const readSelection = useCallback((): void => {\n const frame = iframeRef.current\n if (frame === null) return\n let doc: Document | null = null\n try {\n doc = frame.contentDocument\n } catch {\n return\n }\n if (doc === null) return\n const selection = doc.getSelection()\n if (selection === null || selection.isCollapsed || selection.rangeCount === 0) {\n setSel(null)\n return\n }\n const quote = selection.toString()\n if (quote.trim() === '' || quote.length > MAX_QUOTE_CHARS) {\n setSel(null)\n return\n }\n const range = selection.getRangeAt(0)\n const rect = range.getBoundingClientRect()\n if (rect.width === 0 && rect.height === 0) {\n setSel(null)\n return\n }\n const base = frame.getBoundingClientRect()\n setSel({\n x: base.left + rect.left + rect.width / 2,\n y: base.top + rect.top,\n anchor: { start: 0, end: quote.length, quote, prefix: '', suffix: '' },\n })\n }, [])\n\n // 轮询构建状态(building/queued → 2s 后重试;ready/error/no-toolchain → 停止)\n useEffect(() => {\n let stopped = false\n let timer: number | undefined\n const tick = async (): Promise<void> => {\n try {\n const body = await fetchMeta(relPath, cwdParam, false)\n if (stopped) return\n if (!body.isDeck) {\n setError('该文件不是 Slidev 课件(需要 slides.md)')\n return\n }\n setMeta(body)\n setError(null)\n // 构建链缺失属于「终态」:立即摊开体检面板,而不是让用户对着转圈猜。\n if (body.status === 'no-toolchain') setEnvOpen(true)\n if (body.status === 'ready' || body.status === 'error' || body.status === 'no-toolchain') return\n if (Date.now() - startedRef.current > BUILD_WAIT_MAX_MS) {\n setError('构建等待超时(超过 9 分钟)。可点击「重新构建」重试,或查看下方构建日志。')\n return\n }\n } catch (e) {\n if (!stopped) setError(e instanceof Error ? e.message : String(e))\n return\n }\n if (!stopped) timer = window.setTimeout(() => { void tick() }, 2000)\n }\n void tick()\n return () => {\n stopped = true\n if (timer !== undefined) window.clearTimeout(timer)\n }\n }, [relPath, cwdParam])\n\n // 跟踪 iframe 当前页号,作为「带着这段问 AI」的阅读上下文\n useEffect(() => {\n if (meta === null || meta.status !== 'ready') return\n onReadingChange({ relPath, title: name, section: 'Slidev 播放器(点击画面后可用 ←/→ 翻页)', excerpt: '' })\n let stopped = false\n let timer: number | undefined\n const read = (): void => {\n try {\n const win = iframeRef.current?.contentWindow\n if (win !== null && win !== undefined && iframeRef.current !== null) {\n // hash 路由:取 hash 末尾页码(#/2、#/presenter/1,或带 base 前缀的 #/aero-kb/slidev/<key>/2)\n let no: string | undefined\n const mh = /(\\d+)\\/?$/.exec(win.location.hash)\n if (mh !== null && mh[1] !== undefined) {\n no = mh[1]\n } else {\n const mp = /\\/(\\d+)\\/?$/.exec(win.location.pathname)\n if (mp !== null && mp[1] !== undefined) no = mp[1]\n }\n if (no !== undefined) {\n const n = Number(no)\n setPage((prev) => (prev === n ? prev : n))\n onReadingChange({ relPath, title: name, section: `课件第 ${no} 页`, excerpt: '' })\n }\n }\n } catch {\n /* iframe 卸载等竞态,忽略 */\n }\n if (!stopped) timer = window.setTimeout(read, 1500)\n }\n read()\n return () => {\n stopped = true\n if (timer !== undefined) window.clearTimeout(timer)\n }\n }, [meta?.status, relPath, name, onReadingChange])\n\n // 在 iframe 里挂选区监听(同源;SPA 换页不会重载文档,监听一直有效)。\n useEffect(() => {\n if (meta?.status !== 'ready') return\n const frame = iframeRef.current\n if (frame === null) return\n let detach: (() => void) | null = null\n const attach = (): void => {\n detach?.()\n detach = null\n let doc: Document | null = null\n try {\n doc = frame.contentDocument\n } catch {\n return\n }\n if (doc === null) return\n const onUp = (): void => readSelection()\n const onSel = (): void => {\n if (doc !== null && (doc.getSelection()?.isCollapsed ?? true)) setSel(null)\n }\n doc.addEventListener('mouseup', onUp)\n doc.addEventListener('keyup', onUp)\n doc.addEventListener('selectionchange', onSel)\n detach = () => {\n doc?.removeEventListener('mouseup', onUp)\n doc?.removeEventListener('keyup', onUp)\n doc?.removeEventListener('selectionchange', onSel)\n }\n }\n attach()\n frame.addEventListener('load', attach)\n return () => {\n frame.removeEventListener('load', attach)\n detach?.()\n }\n }, [meta?.status, frameKey, readSelection])\n\n // 重画页内色块:翻页、标注变化、尺寸变化后都要来一遍(Slidev 切页有动效,\n // 多补两次把动效结束后的位置也追上)。\n useEffect(() => {\n if (meta?.status !== 'ready') return\n const frame = iframeRef.current\n if (frame === null) return\n let timers: number[] = []\n const run = (): void => {\n let doc: Document | null = null\n try {\n doc = frame.contentDocument\n } catch {\n return\n }\n if (doc === null || doc.body === null) return\n paintDeck(doc, page, annos)\n }\n const schedule = (): void => {\n run()\n timers = [window.setTimeout(run, 250), window.setTimeout(run, 700)]\n }\n schedule()\n const win = frame.contentWindow\n win?.addEventListener('resize', run)\n return () => {\n for (const t of timers) window.clearTimeout(t)\n win?.removeEventListener('resize', run)\n }\n }, [meta?.status, page, annos, frameKey])\n\n /** 跳到某页(面板里点标注 / 定位用):改 Slidev 的 hash 路由,不重建播放器。 */\n const goToPage = useCallback((target: number): void => {\n const frame = iframeRef.current\n if (frame === null || target <= 0) return\n try {\n const win = frame.contentWindow\n if (win !== null) win.location.hash = `#/${String(target)}`\n } catch {\n /* 保险:跨源时忽略 */\n }\n }, [])\n\n const clearSelection = useCallback((): void => {\n try {\n iframeRef.current?.contentDocument?.getSelection()?.removeAllRanges()\n } catch {\n /* 忽略 */\n }\n setSel(null)\n }, [])\n\n /** 取色 / 划线:落一条「本页 + 原文」的标注。 */\n const applyMark = useCallback((color: AnnoColor, style: AnnoStyle): void => {\n if (sel === null || page <= 0) return\n addPageAnnotation(deckKey, page, sel.anchor.quote, color, style, '')\n clearSelection()\n }, [sel, page, deckKey, clearSelection])\n\n /** 写想法:落一条标注后自动打开浮层。 */\n const applyNote = useCallback((): void => {\n if (sel === null || page <= 0) return\n const anno = addPageAnnotation(deckKey, page, sel.anchor.quote, 'yellow', 'highlight', '')\n clearSelection()\n const frame = iframeRef.current\n const base = frame?.getBoundingClientRect()\n const rect = (() => {\n try {\n return frame?.contentDocument?.querySelector<HTMLElement>(`[${LAYER_ATTR}] > i[data-anno=\"${CSS.escape(anno.id)}\"]`)?.getBoundingClientRect() ?? null\n } catch {\n return null\n }\n })()\n if (base !== undefined && rect !== null && rect !== undefined) {\n setEditor({ id: anno.id, ...popoverAt({ left: base.left + rect.left, top: base.top + rect.top, right: base.left + rect.right, bottom: base.top + rect.bottom }) })\n } else {\n setEditor({ id: anno.id, left: 60, top: 90 })\n }\n }, [sel, page, deckKey, clearSelection])\n\n /** 点击面板条目 / 打开某条标注的编辑浮层。 */\n const openEditorFor = useCallback((id: string): void => {\n const frame = iframeRef.current\n const base = frame?.getBoundingClientRect()\n const anno = annosRef.current.find((a) => a.id === id)\n if (anno !== undefined && anno.page !== page) goToPage(anno.page)\n let rect: DOMRect | null = null\n try {\n rect = frame?.contentDocument?.querySelector<HTMLElement>(`[${LAYER_ATTR}] > i[data-anno=\"${CSS.escape(id)}\"]`)?.getBoundingClientRect() ?? null\n } catch {\n rect = null\n }\n if (base !== undefined && rect !== null) {\n setEditor({ id, ...popoverAt({ left: base.left + rect.left, top: base.top + rect.top, right: base.left + rect.right, bottom: base.top + rect.bottom }) })\n } else {\n setEditor({ id, left: 60, top: 90 })\n }\n }, [page, goToPage])\n\n const currentAnno = annos.find((a) => a.id === editor?.id) ?? null\n\n const patchAnno = useCallback((patch: AnnotationPatch): void => {\n if (editor === null) return\n updateAnnotation(deckKey, editor.id, patch)\n }, [deckKey, editor])\n\n const deleteAnno = useCallback((id: string): void => {\n removeAnnotation(deckKey, id)\n setEditor(null)\n }, [deckKey])\n\n const askAnno = useCallback((quote: string, note: string): void => {\n onAsk?.(annotationQuestion(quote, note))\n }, [onAsk])\n\n const onRebuild = useCallback(async () => {\n setMeta(null)\n setError(null)\n setFrameKey((k) => k + 1)\n startedRef.current = Date.now()\n try {\n const body = await fetchMeta(relPath, cwdParam, true)\n setMeta(body)\n if (body.status === 'no-toolchain') setEnvOpen(true)\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e))\n }\n }, [relPath, cwdParam])\n\n // 体检通过(例如刚装好 CLI):收起面板并重新走一次构建。\n const onEnvReady = useCallback(() => {\n setEnvOpen(false)\n void onRebuild()\n }, [onRebuild])\n\n const openWindow = useCallback((url: string) => {\n window.open(url, '_blank', 'noopener')\n }, [])\n\n const fullscreen = useCallback(() => {\n const p = iframeRef.current?.requestFullscreen()\n if (p !== undefined) {\n void p.catch(() => { /* 全屏被浏览器拒绝时静默 */ })\n }\n }, [])\n\n const status = meta?.status\n const building = status === 'building' || status === 'queued'\n /** 构建链缺失 / 构建失败:用明确的失败说明替换「正在准备」。 */\n const blocked = status === 'no-toolchain' || status === 'error' || error !== null\n\n return (\n <div className={css.deckRoot}>\n <div className={css.deckToolbar}>\n <span className={css.deckTitle} title={relPath}>{name}</span>\n {building && (\n <span className={css.deckStatus}>\n <span className={css.spinner} />\n {status === 'queued' ? '排队中,等待构建…' : '正在构建 Slidev 课件(首次约 1–3 分钟)…'}\n </span>\n )}\n {status === 'ready' && meta !== null && (\n <>\n <span className={css.deckHint}>选中课件里的文字即可取色标记 · ←/→ 翻页 · O 总览 · F 全屏</span>\n <span className={css.deckSpacer} />\n <button\n className={panelOpen ? `${css.btn} ${css.tbBtnOn}` : css.btn}\n onClick={() => {\n setPanelOpen((open) => !open)\n setEditor(null)\n clearSelection()\n }}\n title=\"本门课件的标记与提问:逐页列出、可定位/删除/复制全部\"\n aria-pressed={panelOpen}\n >\n <PenIcon size={12} /> 标记{annos.length > 0 ? ` ${String(annos.length)}` : ''}\n </button>\n <button className={css.btn} onClick={() => setFrameKey((k) => k + 1)} title=\"重新加载播放器\">\n <RefreshIcon size={12} /> 重载\n </button>\n <button className={css.btn} onClick={() => { void onRebuild() }} title=\"强制重新构建(源文件变化时通常会自动重建)\">\n <RefreshIcon size={12} /> 重新构建\n </button>\n <button className={css.btn} onClick={fullscreen} title=\"全屏放映\">\n <MonitorIcon size={12} /> 全屏\n </button>\n {meta.presenterUrl !== '' && (\n <button className={css.btn} onClick={() => openWindow(`${meta.presenterUrl}?v=${meta.builtAt}`)} title=\"在新窗口打开演讲者视图(含备注/下一页预览)\">\n <MonitorIcon size={12} /> 演讲者视图\n </button>\n )}\n <button className={css.btnPrimary} onClick={() => openWindow(`${meta.slidesUrl}?v=${meta.builtAt}`)} title=\"在新标签页放映\">\n <ExternalIcon size={12} /> 新窗口打开\n </button>\n </>\n )}\n </div>\n\n <div className={css.deckBody} data-panel={panelOpen ? '1' : '0'}>\n {status === 'ready' && meta !== null ? (\n <iframe\n key={frameKey}\n ref={iframeRef}\n className={css.deckFrame}\n src={`${meta.slidesUrl}?v=${meta.builtAt}`}\n title={name}\n allowFullScreen\n />\n ) : blocked || envOpen ? (\n <div className={css.deckNoticeScroll}>\n {status === 'no-toolchain' && (\n <div className={css.deckNoticeHead}>\n 本机 Slidev 构建链未就绪,课件暂时无法渲染。下面是自动体检结果——\n 缺什么、怎么装都在这里;安装需要你确认后才会执行。\n </div>\n )}\n {status === 'error' && (\n <div className={css.deckNoticeHead}>\n Slidev 课件构建失败(环境体检可能仍显示正常,请看下方构建日志定位语法/资源问题)。\n </div>\n )}\n {error !== null && status !== 'error' && status !== 'no-toolchain' && (\n <div className={css.deckNoticeHead}>Slidev 课件加载失败:{error}</div>\n )}\n {status === 'error' && meta !== null && meta.log !== '' && <pre className={css.deckLog}>{meta.log}</pre>}\n <div className={css.deckNoticeBtns}>\n <button className={css.btnPrimary} onClick={() => { void onRebuild() }}>\n <RefreshIcon size={12} /> 重新构建\n </button>\n <button className={css.btn} onClick={() => setEnvOpen((v) => !v)}>\n {envOpen ? '收起环境体检' : '检查 Slidev 环境'}\n </button>\n </div>\n {envOpen && <SlidevEnvPanel relPath={relPath} cwdParam={cwdParam} onReady={onEnvReady} />}\n </div>\n ) : (\n <div className={css.deckNotice}>\n <span className={css.spinner} />\n <div>正在准备 Slidev 课件…</div>\n {meta !== null && meta.log !== '' && <pre className={css.deckLog}>{meta.log}</pre>}\n </div>\n )}\n\n {panelOpen && status === 'ready' && (\n <MarksPanel\n title={name}\n annos={annos}\n exportKey={deckKey}\n showPage\n onLocate={(anno) => {\n goToPage(anno.page)\n openEditorFor(anno.id)\n }}\n onAsk={onAsk === undefined ? null : (anno) => askAnno(anno.quote, anno.note)}\n onDelete={(anno) => deleteAnno(anno.id)}\n onClear={() => {\n for (const anno of annos) removeAnnotation(deckKey, anno.id)\n setEditor(null)\n }}\n onClose={() => setPanelOpen(false)}\n />\n )}\n\n {sel !== null && (\n <SelectionBar\n sel={sel}\n onPick={applyMark}\n onNote={applyNote}\n onAsk={onAsk === undefined ? null : () => askAnno(sel.anchor.quote, '')}\n onDismiss={clearSelection}\n />\n )}\n\n {editor !== null && currentAnno !== null && (\n <NoteEditor\n key={editor.id}\n anno={currentAnno}\n at={editor}\n onPatch={patchAnno}\n onDelete={() => deleteAnno(editor.id)}\n onAsk={onAsk === undefined ? null : (note) => askAnno(currentAnno.quote, note)}\n onClose={() => setEditor(null)}\n />\n )}\n </div>\n </div>\n )\n}\n","/**\r\n * 把文字填进会话输入区并**真的发出去**(工作台各处的「问 AI」共用)。\r\n *\r\n * 两个坑,都是实测出来的:\r\n *\r\n * 1. `setDraft(text)` 之后不能立刻提交。草稿真身在 Lexical 编辑器里,`setDraft` 只是把文本\r\n * 交给编辑器;要等编辑器完成一次更新、草稿回到输入状态之后才算\"在输入框里\"。同一个 tick\r\n * 里紧跟 `submit()`,提交机读到的还是空草稿,于是既不发送也不报错——现象就是\"点了按钮,\r\n * 输入框里有字,但消息发不出去\"。\r\n *\r\n * 2. 即使等草稿发布之后再调 `inputActions.submit()`,在工作台视图里也**仍然是空操作**\r\n * (实测:输入框里明明有草稿,调 submit 后既不发送、也没有任何提示;而把光标点进输入框\r\n * 按一次回车,DSH 立刻正常走发送流程)。原因在 DSH 的输入机内部(provide 出来的动作面\r\n * 与当前挂载的输入外壳不是同一个),插件侧改不动。\r\n *\r\n * 因此这里采用\"草稿已发布 → 在输入框里按回车\"的路径:这正是用户自己的发送手势,实测有效。\r\n * 只有连输入框都找不到时,才退回官方 `submit()`。\r\n *\r\n * @param actions - 会话输入区动作(`inputActions`),仅作为最后的兜底。\r\n * @param text - 刚填进去的文本(用于在 DOM 里认出\"装着这段草稿的那个输入框\")。\r\n * @param readDraft - 读取\"已发布草稿\"的函数,通常是 `() => draftRef.current`。\r\n * @param tries - 最多轮询次数。\r\n * @param intervalMs - 轮询间隔(毫秒)。\r\n */\r\nexport interface DraftActions {\r\n submit(): void\r\n}\r\n\r\n/** 草稿特征串:用来在 DOM 里认出装着这段草稿的输入框。 */\r\nfunction probeOf(text: string): string {\r\n return text.replace(/\\s+/g, ' ').trim().slice(0, 24)\r\n}\r\n\r\n/** 找到装着这段草稿的输入框;优先取工作台之外的(工作台自己的可编辑区不参与发送)。 */\r\nfunction editorHolding(probe: string): HTMLElement | null {\r\n if (probe === '') return null\r\n const all = [...document.querySelectorAll<HTMLElement>('[contenteditable=\"true\"]')]\r\n const contains = (el: HTMLElement): boolean => (el.textContent ?? '').replace(/\\s+/g, ' ').includes(probe)\r\n for (const el of all) if (el.closest('[data-aero-workbench]') === null && contains(el)) return el\r\n for (const el of all) if (contains(el)) return el\r\n return null\r\n}\r\n\r\n/** 在输入框里按一次回车——输入区自己的发送手势(keyCode/which 是给编辑器的兼容信号)。 */\r\nfunction pressEnter(el: HTMLElement): void {\r\n el.focus()\r\n const init: KeyboardEventInit & { keyCode?: number; which?: number } = {\r\n key: 'Enter',\r\n code: 'Enter',\r\n keyCode: 13,\r\n which: 13,\r\n bubbles: true,\r\n cancelable: true,\r\n composed: true,\r\n }\r\n el.dispatchEvent(new KeyboardEvent('keydown', init))\r\n}\r\n\r\nexport function sendFilledDraft(\r\n actions: DraftActions,\r\n text: string,\r\n readDraft: () => string,\r\n tries = 20,\r\n intervalMs = 25,\r\n): void {\r\n const probe = probeOf(text)\r\n let left = Math.max(1, tries)\r\n const attempt = (): void => {\r\n left -= 1\r\n const published = readDraft().replace(/\\s+/g, ' ')\r\n const ready = published.trim() !== '' && (probe === '' || published.includes(probe))\r\n if (!ready && left > 1) {\r\n window.setTimeout(attempt, intervalMs)\r\n return\r\n }\r\n const editor = editorHolding(probe)\r\n if (editor !== null) pressEnter(editor)\r\n else actions.submit()\r\n }\r\n window.setTimeout(attempt, 0)\r\n}\r\n","/**\n * 由 scripts/gen-css-modules.mjs 从 src/client/git.module.css 生成,**请勿手改**。\n * 改样式请改源 CSS,然后跑:node scripts/gen-css-modules.mjs\n */\nconst css = \".l0zRla_statusBtn{color:inherit;cursor:pointer;background:0 0;border:1px solid #80808059;border-radius:6px;align-items:center;gap:6px;padding:5px 10px;font-size:13px;display:inline-flex}.l0zRla_statusBtn:hover{background:#7f7f7f1f}.l0zRla_statusBtn:focus-visible{border-color:#608cdccc;outline:none}.l0zRla_dot{border-radius:50%;flex:none;width:8px;height:8px}.l0zRla_dotunknown{background:#7f7f7f80}.l0zRla_dotclean{background:#2ea043e6}.l0zRla_dotdirty{background:#d29922f2}.l0zRla_dotbehind{background:#608cdcf2}.l0zRla_dotahead{background:#966ec8f2}.l0zRla_syncUp,.l0zRla_syncDown{font-variant-numeric:tabular-nums;font-size:11px;line-height:1}.l0zRla_syncUp{color:#966ec8f2}.l0zRla_syncDown{color:#608cdcf2}.l0zRla_panel{background:#7f7f7f0a;border-left:1px solid #80808033;flex-direction:column;flex:none;width:340px;min-height:0;display:flex}.l0zRla_header{border-bottom:1px solid #80808033;flex:none;justify-content:space-between;align-items:center;gap:8px;padding:9px 10px 7px 12px;display:flex}.l0zRla_title{font-size:13px;font-weight:600}.l0zRla_closeBtn{width:24px;height:24px;color:inherit;cursor:pointer;background:0 0;border:none;border-radius:6px;place-items:center;font-size:12px;display:grid}.l0zRla_closeBtn:hover{background:#7f7f7f24}.l0zRla_repoTabs{border-bottom:1px solid #80808033;flex-wrap:wrap;flex:none;gap:4px;padding:8px 10px 6px;display:flex}.l0zRla_repoTab{color:inherit;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:999px;align-items:center;gap:5px;padding:4px 9px;font-size:12px;display:inline-flex}.l0zRla_repoTab:hover{background:#7f7f7f1f}.l0zRla_repoTabActive{background:#608cdc29;border-color:#608cdc73}.l0zRla_tabDotDirty,.l0zRla_tabDotBehind{border-radius:50%;flex:none;width:6px;height:6px}.l0zRla_tabDotDirty{background:#d29922f2}.l0zRla_tabDotBehind{background:#608cdcf2}.l0zRla_body{flex-direction:column;flex:1;gap:10px;min-height:0;padding:10px 12px 16px;display:flex;overflow-y:auto}.l0zRla_repoHead{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.l0zRla_branchPill{background:#7f7f7f24;border-radius:999px;align-items:center;gap:5px;padding:3px 9px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;display:inline-flex}.l0zRla_syncPill{color:#7f7f7ff2;font-size:12px}.l0zRla_actions{flex-wrap:wrap;gap:6px;display:flex}.l0zRla_actionBtn{color:inherit;cursor:pointer;background:0 0;border:1px solid #80808059;border-radius:6px;align-items:center;gap:5px;padding:5px 11px;font-size:12px;display:inline-flex}.l0zRla_actionBtn:hover:not(:disabled){background:#7f7f7f1f}.l0zRla_actionBtn:disabled{opacity:.45;cursor:not-allowed}.l0zRla_actionBtn:focus-visible{border-color:#608cdccc;outline:none}.l0zRla_actionDanger{color:#dc5a5a;border-color:#dc5a5aa6}.l0zRla_actionDanger:hover:not(:disabled){background:#dc5a5a1f}.l0zRla_commitBox{background:#7f7f7f0d;border:1px solid #80808038;border-radius:8px;flex-direction:column;gap:6px;padding:10px;display:flex}.l0zRla_commitInput{box-sizing:border-box;width:100%;color:inherit;background:0 0;border:1px solid #80808059;border-radius:6px;padding:7px 9px;font-size:13px}.l0zRla_commitInput:focus{border-color:#608cdccc;outline:none}.l0zRla_commitBtn{color:#fff;cursor:pointer;background:#2ea043d9;border:none;border-radius:6px;align-self:flex-end;align-items:center;gap:5px;padding:5px 12px;font-size:12px;font-weight:600;display:inline-flex}.l0zRla_commitBtn:hover:not(:disabled){background:#2ea043}.l0zRla_commitBtn:disabled{opacity:.5;cursor:not-allowed}.l0zRla_commitBtn.l0zRla_actionDanger{background:#dc5a5ae6;border:none}.l0zRla_commitBtn.l0zRla_actionDanger:hover:not(:disabled){background:#dc5a5a}.l0zRla_sectionLabel{color:#7f7f7ff2;margin-top:2px;font-size:12px;font-weight:600}.l0zRla_changeList,.l0zRla_logList{border:1px solid #80808033;border-radius:8px;flex-direction:column;display:flex;overflow:hidden}.l0zRla_changeRow{border-bottom:1px solid #8080801f;align-items:center;gap:7px;padding:4px 8px;font-size:12px;display:flex}.l0zRla_changeRow:last-child{border-bottom:none}.l0zRla_chgBadge{text-align:center;border-radius:4px;flex:none;min-width:20px;padding:1px 5px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px}.l0zRla_chgM{color:#d29922;background:#d2992233}.l0zRla_chgA{color:#2ea043;background:#2ea04333}.l0zRla_chgD{color:#dc5a5a;background:#dc5a5a33}.l0zRla_chgR{color:#966ec8;background:#966ec833}.l0zRla_chgU{color:#7f7f7f;background:#7f7f7f33}.l0zRla_changePath{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;overflow:hidden}.l0zRla_stagedMark{color:#2ea043e6;flex:none;font-size:11px}.l0zRla_logRow{border-bottom:1px solid #8080801f;gap:8px;padding:6px 8px;font-size:12px;display:flex}.l0zRla_logRow:last-child{border-bottom:none}.l0zRla_logHash{color:#608cdce6;flex:none;padding-top:1px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.l0zRla_logMain{flex:1;min-width:0}.l0zRla_logMsg{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.l0zRla_logMeta{color:#7f7f7fd9;margin-top:1px;font-size:11px}.l0zRla_muted{color:#7f7f7fd9;padding:6px 8px;font-size:12px}.l0zRla_errorBox{color:#dc5a5a;white-space:pre-wrap;background:#dc5a5a1f;border:1px solid #dc5a5a66;border-radius:8px;padding:8px 10px;font-size:12px}.l0zRla_output{color:#dcdcdceb;white-space:pre-wrap;word-break:break-word;background:#00000047;border-radius:8px;max-height:220px;margin:0;padding:10px 12px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11.5px;line-height:1.55;overflow:auto}.l0zRla_spinner{border:2px solid #7f7f7f59;border-top-color:currentColor;border-radius:50%;flex:none;width:12px;height:12px;animation:.7s linear infinite l0zRla_aero-git-spin}@keyframes l0zRla_aero-git-spin{to{transform:rotate(360deg)}}\"\nconst styleId = \"@aero/study-kit/git.module.css\"\nif (typeof document !== 'undefined' && document.querySelector('style[data-plugin-css=\"' + styleId + '\"]') === null) {\n const tag = document.createElement('style')\n tag.dataset.plugin = \"@aero/study-kit\"\n tag.dataset.pluginCss = styleId\n tag.textContent = css\n document.head.appendChild(tag)\n}\nconst classes: Record<string, string> = {\n \"actionBtn\": \"l0zRla_actionBtn\",\n \"actionDanger\": \"l0zRla_actionDanger\",\n \"actions\": \"l0zRla_actions\",\n \"aero-git-spin\": \"l0zRla_aero-git-spin\",\n \"body\": \"l0zRla_body\",\n \"branchPill\": \"l0zRla_branchPill\",\n \"changeList\": \"l0zRla_changeList\",\n \"changePath\": \"l0zRla_changePath\",\n \"changeRow\": \"l0zRla_changeRow\",\n \"chgA\": \"l0zRla_chgA\",\n \"chgBadge\": \"l0zRla_chgBadge\",\n \"chgD\": \"l0zRla_chgD\",\n \"chgM\": \"l0zRla_chgM\",\n \"chgR\": \"l0zRla_chgR\",\n \"chgU\": \"l0zRla_chgU\",\n \"closeBtn\": \"l0zRla_closeBtn\",\n \"commitBox\": \"l0zRla_commitBox\",\n \"commitBtn\": \"l0zRla_commitBtn\",\n \"commitInput\": \"l0zRla_commitInput\",\n \"dot\": \"l0zRla_dot\",\n \"dotahead\": \"l0zRla_dotahead\",\n \"dotbehind\": \"l0zRla_dotbehind\",\n \"dotclean\": \"l0zRla_dotclean\",\n \"dotdirty\": \"l0zRla_dotdirty\",\n \"dotunknown\": \"l0zRla_dotunknown\",\n \"errorBox\": \"l0zRla_errorBox\",\n \"header\": \"l0zRla_header\",\n \"logHash\": \"l0zRla_logHash\",\n \"logList\": \"l0zRla_logList\",\n \"logMain\": \"l0zRla_logMain\",\n \"logMeta\": \"l0zRla_logMeta\",\n \"logMsg\": \"l0zRla_logMsg\",\n \"logRow\": \"l0zRla_logRow\",\n \"muted\": \"l0zRla_muted\",\n \"output\": \"l0zRla_output\",\n \"panel\": \"l0zRla_panel\",\n \"repoHead\": \"l0zRla_repoHead\",\n \"repoTab\": \"l0zRla_repoTab\",\n \"repoTabActive\": \"l0zRla_repoTabActive\",\n \"repoTabs\": \"l0zRla_repoTabs\",\n \"sectionLabel\": \"l0zRla_sectionLabel\",\n \"spinner\": \"l0zRla_spinner\",\n \"stagedMark\": \"l0zRla_stagedMark\",\n \"statusBtn\": \"l0zRla_statusBtn\",\n \"syncDown\": \"l0zRla_syncDown\",\n \"syncPill\": \"l0zRla_syncPill\",\n \"syncUp\": \"l0zRla_syncUp\",\n \"tabDotBehind\": \"l0zRla_tabDotBehind\",\n \"tabDotDirty\": \"l0zRla_tabDotDirty\",\n \"title\": \"l0zRla_title\"\n}\nexport default classes\n","import { useCallback, useEffect, useRef, useState } from 'react'\r\nimport type { GitOpResponse, GitRepoSummary, GitReposResponse, GitStatusResponse } from '../types.js'\r\nimport type { ViewGate } from './viewActive.js'\r\nimport { BranchIcon, CheckIcon, FetchIcon, PullIcon, PushIcon } from './icons.js'\r\nimport css from './git.module.css.gen.ts'\r\n\r\n/**\r\n * 顶栏「Git」按钮:轮询四仓概况,按状态显示彩色圆点(GitHub 同步指示风格)。\r\n *\r\n * `gate` 是所属工作台的可视性门:标签被保活隐藏时**跳过轮询**(每次 `/aero-kb/git/repos`\r\n * 都要起 git 子进程,后台空转纯属浪费)。省略时不门控(单文件/嵌入式场景)。\r\n */\r\nexport function GitStatusButton({ cwd, refreshKey, onClick, gate }: {\r\n cwd: string | undefined\r\n refreshKey: number\r\n onClick: () => void\r\n gate?: ViewGate\r\n}): JSX.Element {\r\n const [repos, setRepos] = useState<readonly GitRepoSummary[] | null>(null)\r\n const [state, setState] = useState<'unknown' | 'clean' | 'dirty' | 'behind' | 'ahead'>('unknown')\r\n\r\n useEffect(() => {\r\n let cancelled = false\r\n const qs = cwd !== undefined && cwd !== '' ? `?cwd=${encodeURIComponent(cwd)}` : ''\r\n const load = (): void => {\r\n fetch(`/aero-kb/git/repos${qs}`)\r\n .then((r) => (r.ok ? r.json() as Promise<GitReposResponse> : Promise.reject(new Error(`HTTP ${r.status}`))))\r\n .then((d) => {\r\n if (cancelled || !d.ok) return\r\n setRepos(d.repos)\r\n })\r\n .catch(() => { /* 静默失败:圆点保持 unknown */ })\r\n }\r\n load()\r\n const timer = gate === undefined ? setInterval(load, 60_000) : gate.interval(load, 60_000)\r\n return () => {\r\n cancelled = true\r\n clearInterval(timer)\r\n }\r\n }, [cwd, refreshKey, gate])\r\n\r\n useEffect(() => {\r\n if (repos === null || repos.length === 0) {\r\n setState('unknown')\r\n return\r\n }\r\n if (repos.some((r) => r.dirty)) setState('dirty')\r\n else if (repos.some((r) => r.behind > 0)) setState('behind')\r\n else if (repos.some((r) => r.ahead > 0)) setState('ahead')\r\n else setState('clean')\r\n }, [repos])\r\n\r\n const ahead = repos?.reduce((s, r) => s + r.ahead, 0) ?? 0\r\n const behind = repos?.reduce((s, r) => s + r.behind, 0) ?? 0\r\n\r\n return (\r\n <button className={css.statusBtn} onClick={onClick} title=\"打开 Git 面板(拉取/推送/提交)\">\r\n <BranchIcon size={14} />\r\n <span>Git</span>\r\n <span className={`${css.dot} ${css[`dot${state}`]}`} />\r\n {ahead > 0 && <span className={css.syncUp}>↑{ahead}</span>}\r\n {behind > 0 && <span className={css.syncDown}>↓{behind}</span>}\r\n </button>\r\n )\r\n}\r\n\r\nfunction relativeTime(iso: string): string {\r\n const t = new Date(iso).getTime()\r\n if (!Number.isFinite(t)) return iso\r\n const diff = Date.now() - t\r\n const m = Math.floor(diff / 60_000)\r\n if (m < 1) return '刚刚'\r\n if (m < 60) return `${m} 分钟前`\r\n const h = Math.floor(m / 60)\r\n if (h < 24) return `${h} 小时前`\r\n const d = Math.floor(h / 24)\r\n if (d < 30) return `${d} 天前`\r\n return new Date(t).toLocaleDateString('zh-CN')\r\n}\r\n\r\nconst CHANGE_COLORS: Record<string, string | undefined> = {\r\n M: css.chgM,\r\n A: css.chgA,\r\n D: css.chgD,\r\n R: css.chgR,\r\n C: css.chgR,\r\n '??': css.chgU,\r\n}\r\n\r\ntype Op = 'fetch' | 'pull' | 'push' | 'commit'\r\n\r\nexport function GitPanel({ cwd, onChanged, onClose }: {\r\n cwd: string | undefined\r\n /** 操作成功后通知宿主(刷新目录/案例清单/按钮圆点)。 */\r\n onChanged: () => void\r\n onClose: () => void\r\n}): JSX.Element {\r\n const qs = cwd !== undefined && cwd !== '' ? `?cwd=${encodeURIComponent(cwd)}` : ''\r\n const [repos, setRepos] = useState<readonly GitRepoSummary[]>([])\r\n const [reposError, setReposError] = useState<string | null>(null)\r\n const [selectedId, setSelectedId] = useState<string | null>(null)\r\n const [status, setStatus] = useState<GitStatusResponse | null>(null)\r\n const [statusError, setStatusError] = useState<string | null>(null)\r\n const [busy, setBusy] = useState<Op | null>(null)\r\n const [armed, setArmed] = useState<Op | null>(null)\r\n const [message, setMessage] = useState('')\r\n const [output, setOutput] = useState<string | null>(null)\r\n const [opError, setOpError] = useState<string | null>(null)\r\n const armedTimer = useRef<ReturnType<typeof setTimeout> | null>(null)\r\n\r\n const loadRepos = useCallback((): void => {\r\n setReposError(null)\r\n fetch(`/aero-kb/git/repos${qs}`)\r\n .then((r) => (r.ok ? r.json() as Promise<GitReposResponse> : Promise.reject(new Error(`HTTP ${r.status}`))))\r\n .then((d) => {\r\n if (!d.ok) {\r\n setReposError(d.error ?? '加载失败')\r\n return\r\n }\r\n setRepos(d.repos)\r\n setSelectedId((cur) => (cur !== null && d.repos.some((r) => r.id === cur) ? cur : d.repos[0]?.id ?? null))\r\n })\r\n .catch((e) => setReposError(e instanceof Error ? e.message : String(e)))\r\n }, [qs])\r\n\r\n const loadStatus = useCallback((id: string): void => {\r\n setStatusError(null)\r\n setStatus(null)\r\n fetch(`/aero-kb/git/${id}/status${qs}`)\r\n .then((r) => (r.ok ? r.json() as Promise<GitStatusResponse> : Promise.reject(new Error(`HTTP ${r.status}`))))\r\n .then((d) => {\r\n if (!d.ok) setStatusError(d.error ?? '加载失败')\r\n else setStatus(d)\r\n })\r\n .catch((e) => setStatusError(e instanceof Error ? e.message : String(e)))\r\n }, [qs])\r\n\r\n useEffect(() => {\r\n loadRepos()\r\n }, [loadRepos])\r\n\r\n useEffect(() => {\r\n if (selectedId !== null) loadStatus(selectedId)\r\n }, [selectedId, loadStatus])\r\n\r\n useEffect(() => () => {\r\n if (armedTimer.current !== null) clearTimeout(armedTimer.current)\r\n }, [])\r\n\r\n const arm = (op: Op): void => {\r\n if (armed === op) {\r\n setArmed(null)\r\n return\r\n }\r\n setArmed(op)\r\n if (armedTimer.current !== null) clearTimeout(armedTimer.current)\r\n armedTimer.current = setTimeout(() => setArmed((a) => (a === op ? null : a)), 4000)\r\n }\r\n\r\n const runOp = useCallback((op: Op, confirmArmed: boolean): void => {\r\n if (busy !== null || selectedId === null) return\r\n // push / commit 需要两步确认(第二次点击才真正执行)。\r\n if (confirmArmed && armed !== op) {\r\n arm(op)\r\n return\r\n }\r\n setArmed(null)\r\n setBusy(op)\r\n setOpError(null)\r\n setOutput(null)\r\n const init: RequestInit = {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n }\r\n if (op === 'commit') init.body = JSON.stringify({ message })\r\n fetch(`/aero-kb/git/${selectedId}/${op}${qs}`, init)\r\n .then((r) => r.json() as Promise<GitOpResponse>)\r\n .then((d) => {\r\n setOutput(d.output.trim() === '' ? '(无输出)' : d.output.trim())\r\n if (!d.ok) {\r\n setOpError(d.error ?? '操作失败')\r\n } else {\r\n if (d.summary !== undefined) setStatus(d.summary)\r\n loadRepos()\r\n onChanged()\r\n }\r\n })\r\n .catch((e) => setOpError(e instanceof Error ? e.message : String(e)))\r\n .finally(() => setBusy(null))\r\n }, [busy, selectedId, armed, message, qs, loadRepos, onChanged])\r\n\r\n const selected = repos.find((r) => r.id === selectedId) ?? null\r\n const dirtyCount = status?.changes.length ?? 0\r\n\r\n return (\r\n <div className={css.panel}>\r\n <div className={css.header}>\r\n <span className={css.title}>Git 仓库</span>\r\n <button className={css.closeBtn} onClick={onClose} title=\"关闭 Git 面板\">✕</button>\r\n </div>\r\n\r\n <div className={css.repoTabs}>\r\n {repos.map((r) => (\r\n <button\r\n key={r.id}\r\n className={selectedId === r.id ? `${css.repoTab} ${css.repoTabActive}` : css.repoTab}\r\n onClick={() => setSelectedId(r.id)}\r\n title={r.dir}\r\n >\r\n {r.name}\r\n {r.dirty && <span className={css.tabDotDirty} />}\r\n {!r.dirty && r.behind > 0 && <span className={css.tabDotBehind} />}\r\n </button>\r\n ))}\r\n </div>\r\n {reposError !== null && <div className={css.errorBox}>{reposError}</div>}\r\n\r\n <div className={css.body}>\r\n {selected !== null && (\r\n <div className={css.repoHead}>\r\n <span className={css.branchPill}><BranchIcon size={12} /> {status?.branch ?? selected.branch}</span>\r\n <span className={css.syncPill}>\r\n {selected.ahead > 0 || selected.behind > 0\r\n ? `↑${selected.ahead} 未推送 · ↓${selected.behind} 待拉取`\r\n : '与远端同步'}\r\n </span>\r\n </div>\r\n )}\r\n\r\n {selected !== null && (\r\n <div className={css.actions}>\r\n <button\r\n className={css.actionBtn}\r\n onClick={() => runOp('fetch', false)}\r\n disabled={busy !== null}\r\n title=\"从远端抓取引用与对象(不改变工作区)\"\r\n >\r\n <FetchIcon size={13} /> {busy === 'fetch' ? <span className={css.spinner} /> : '拉取'}\r\n </button>\r\n <button\r\n className={css.actionBtn}\r\n onClick={() => runOp('pull', false)}\r\n disabled={busy !== null || selected.dirty}\r\n title={selected.dirty ? '工作区有未提交改动,请先提交' : '快进更新到远端最新(--ff-only)'}\r\n >\r\n <PullIcon size={13} /> {busy === 'pull' ? <span className={css.spinner} /> : '更新'}\r\n </button>\r\n <button\r\n className={armed === 'push' ? `${css.actionBtn} ${css.actionDanger}` : css.actionBtn}\r\n onClick={() => runOp('push', true)}\r\n disabled={busy !== null}\r\n title=\"推送到远端(需要 SSH 权限)\"\r\n >\r\n <PushIcon size={13} />\r\n {busy === 'push' ? <span className={css.spinner} /> : armed === 'push' ? '确认推送?' : '推送'}\r\n </button>\r\n </div>\r\n )}\r\n\r\n {selected !== null && (\r\n <div className={css.commitBox}>\r\n <input\r\n className={css.commitInput}\r\n placeholder=\"提交信息(如:更新第 6 章教案配图)…\"\r\n value={message}\r\n onChange={(e) => setMessage(e.target.value)}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) runOp('commit', true)\r\n }}\r\n />\r\n <button\r\n className={armed === 'commit' ? `${css.commitBtn} ${css.actionDanger}` : css.commitBtn}\r\n onClick={() => runOp('commit', true)}\r\n disabled={busy !== null}\r\n title=\"暂存全部改动并提交(git add -A + commit)\"\r\n >\r\n <CheckIcon size={13} />\r\n {busy === 'commit' ? <span className={css.spinner} /> : armed === 'commit' ? '确认提交?' : '暂存并提交'}\r\n </button>\r\n </div>\r\n )}\r\n\r\n {statusError !== null && <div className={css.errorBox}>{statusError}</div>}\r\n\r\n {status !== null && (\r\n <>\r\n <div className={css.sectionLabel}>\r\n 改动{dirtyCount > 0 ? `(${dirtyCount})` : ''}\r\n </div>\r\n <div className={css.changeList}>\r\n {status.changes.length === 0 && <div className={css.muted}>工作区干净,没有未提交的改动。</div>}\r\n {status.changes.map((c, i) => (\r\n <div key={`${c.path}-${i}`} className={css.changeRow} title={`${c.staged ? '已暂存' : '未暂存'} · ${c.status}`}>\r\n <span className={`${css.chgBadge} ${CHANGE_COLORS[c.status] ?? css.chgU}`}>\r\n {c.status === '' ? '~' : c.status}\r\n </span>\r\n <span className={css.changePath}>{c.path}</span>\r\n <span className={css.stagedMark}>{c.staged && c.status !== '??' ? '已暂存' : ''}</span>\r\n </div>\r\n ))}\r\n </div>\r\n\r\n <div className={css.sectionLabel}>最近提交</div>\r\n <div className={css.logList}>\r\n {status.log.length === 0 && <div className={css.muted}>暂无提交记录。</div>}\r\n {status.log.map((c) => (\r\n <div key={c.hash} className={css.logRow}>\r\n <span className={css.logHash}>{c.hash}</span>\r\n <div className={css.logMain}>\r\n <div className={css.logMsg}>{c.message}</div>\r\n <div className={css.logMeta}>{c.author} · {relativeTime(c.date)}</div>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n\r\n {opError !== null && <div className={css.errorBox}>{opError}</div>}\r\n {output !== null && (\r\n <pre className={css.output}>{output}</pre>\r\n )}\r\n </div>\r\n </div>\r\n )\r\n}\r\n","/**\r\n * 阅读器公共控件:把「学习资料」的正文阅读能力(目录 / 版式 / 阅读设置 / 专注 / 全屏)\r\n * 收在一处实现,供「学习资料」与「备课」两个工作台共用。\r\n *\r\n * 为什么单独成文件:「备课」工作台的 adoc 教案渲染窗格已经改为直接内嵌 DocViewer\r\n * (与「学习资料」同一份正文渲染与阅读偏好),若顶栏按钮各写一份,就会出现\r\n * 两套措辞、两套快捷键、两套默认值。这里只留一份,两边调的是同一份\r\n * readerPrefs 状态与同一个 Fullscreen API 封装。\r\n *\r\n * 职责边界:\r\n * · useFullscreen —— 绑定某个工作台根节点的全屏开关,并跟踪 Esc 等外部退出;\r\n * · useReaderShortcuts —— 正文区快捷键(+ / − / 0 / Z / O / F / Esc);\r\n * · ReaderControls —— 顶栏按钮组本身(不含「文件树 / 列表」这类各台自有的按钮)。\r\n */\r\nimport { useCallback, useEffect, useMemo, useRef, useState, type RefObject } from 'react'\r\nimport {\r\n FONT_STEPS, getOutlineOpen, getZen, nudgeFontStep, resetFontStep, setDocFont, setDocLayout,\r\n setDocLeading, setDocMeasure, setDocPaper, setOutlineOpen, setZen, useReaderPrefs,\r\n type DocFont, type DocLeading, type DocMeasure, type DocPaper,\r\n} from './readerPrefs.js'\r\nimport {\r\n BookIcon, ExpandIcon, ListIcon, PageIcon, ShrinkIcon, SlidersIcon, TypeIcon, ZenIcon,\r\n} from './icons.js'\r\nimport css from './styles.module.css.gen.ts'\r\n\r\n/** 全屏开关(浏览器 Fullscreen API):当前是否全屏 + 切换函数。 */\r\nexport interface FullscreenControl {\r\n active: boolean\r\n toggle: () => void\r\n}\r\n\r\n/**\r\n * 把某个工作台根节点做成全屏目标。\r\n *\r\n * 全屏作用于**工作台根节点**而不是正文容器:顶栏(退出全屏 / 目录 / 列表等入口)\r\n * 必须留在全屏元素内部,否则用户在全屏里失去退出与切换的入口。\r\n * 退出由浏览器接管(Esc / 系统手势),故这里同时监听 fullscreenchange 同步状态。\r\n */\r\nexport function useFullscreen<T extends HTMLElement>(target: RefObject<T | null>): FullscreenControl {\r\n const [active, setActive] = useState(false)\r\n\r\n useEffect(() => {\r\n const onChange = (): void => setActive(document.fullscreenElement === target.current)\r\n document.addEventListener('fullscreenchange', onChange)\r\n onChange()\r\n return () => document.removeEventListener('fullscreenchange', onChange)\r\n }, [target])\r\n\r\n const toggle = useCallback((): void => {\r\n const el = target.current\r\n if (el === null) return\r\n if (document.fullscreenElement === el) {\r\n void document.exitFullscreen().catch(() => { /* 已在实际退出流程中 */ })\r\n return\r\n }\r\n const requested = el.requestFullscreen?.()\r\n if (requested !== undefined) void requested.catch(() => { /* 非用户手势时浏览器会拒绝:静默 */ })\r\n }, [target])\r\n\r\n return useMemo(() => ({ active, toggle }), [active, toggle])\r\n}\r\n\r\n/**\r\n * 正文区快捷键:+ / − 字号、0 复位、Z 专注、O 目录、F 全屏、Esc 收尾。\r\n *\r\n * 两道让位:\r\n * 1. 输入框与可编辑区域内一律让位给打字(备课台的源码编辑器就是 textarea);\r\n * 2. 工作台根节点不可见(标签页被隐藏)时整体不响应——「学习资料」与「备课」\r\n * 可能同时挂载,各挂一份 window 监听会互相抢键。\r\n */\r\nexport function useReaderShortcuts<T extends HTMLElement>(\r\n rootRef: RefObject<T | null>,\r\n toggleFullscreen: () => void,\r\n onEscape: () => void,\r\n): void {\r\n const escapeRef = useRef(onEscape)\r\n escapeRef.current = onEscape\r\n\r\n useEffect(() => {\r\n const onKey = (e: KeyboardEvent): void => {\r\n if (e.ctrlKey || e.metaKey || e.altKey) return\r\n const root = rootRef.current\r\n // 标签页被隐藏时整体不响应:getClientRects 为空(display:none 或未挂载)直接让位,\r\n // visibility:hidden 之类仍有 rect 的情形再看一眼计算样式。全屏中的根节点两关都过。\r\n if (root === null || root.getClientRects().length === 0) return\r\n const style = window.getComputedStyle(root)\r\n if (style.display === 'none' || style.visibility === 'hidden') return\r\n const el = e.target as HTMLElement | null\r\n const tag = el?.tagName ?? ''\r\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || el?.isContentEditable === true) return\r\n switch (e.key) {\r\n case '+': case '=': nudgeFontStep(1); break\r\n case '-': case '_': nudgeFontStep(-1); break\r\n case '0': resetFontStep(); break\r\n case 'z': case 'Z': setZen(!getZen()); break\r\n case 'o': case 'O': setOutlineOpen(!getOutlineOpen()); break\r\n case 'f': case 'F': toggleFullscreen(); break\r\n case 'Escape': escapeRef.current(); return // 全屏由浏览器自身退出\r\n default: return\r\n }\r\n e.preventDefault()\r\n }\r\n window.addEventListener('keydown', onKey)\r\n return () => window.removeEventListener('keydown', onKey)\r\n }, [rootRef, toggleFullscreen])\r\n}\r\n\r\n/** 阅读设置面板里的分段选择器(字体 / 行距 / 版心 / 底色共用)。 */\r\nfunction Seg<T extends string>({ label, value, options, onChange }: {\r\n label: string\r\n value: T\r\n options: readonly { value: T; label: string; title: string }[]\r\n onChange: (next: T) => void\r\n}): JSX.Element {\r\n return (\r\n <div className={css.readerRow}>\r\n <span className={css.readerRowLabel}>{label}</span>\r\n <div className={css.readerSeg} role=\"group\" aria-label={label}>\r\n {options.map((o) => (\r\n <button\r\n key={o.value}\r\n type=\"button\"\r\n className={o.value === value ? `${css.readerSegBtn} ${css.readerSegBtnOn}` : css.readerSegBtn}\r\n onClick={() => onChange(o.value)}\r\n aria-pressed={o.value === value}\r\n title={o.title}\r\n >\r\n {o.label}\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n )\r\n}\r\n\r\nconst FONT_OPTIONS: readonly { value: DocFont; label: string; title: string }[] = [\r\n { value: 'auto', label: '跟随版式', title: '书籍版式用衬线、网页版式用无衬线(默认)' },\r\n { value: 'serif', label: '宋体', title: '衬线族(宋体/思源宋体)——中文长文精读' },\r\n { value: 'sans', label: '黑体', title: '无衬线族(苹方/微软雅黑)——屏幕扫读' },\r\n { value: 'kai', label: '楷体', title: '楷体族——接近纸质教材的字面' },\r\n]\r\n\r\nconst LEADING_OPTIONS: readonly { value: DocLeading; label: string; title: string }[] = [\r\n { value: 'tight', label: '紧凑', title: '行距 1.65——同屏信息更多' },\r\n { value: 'normal', label: '标准', title: '行距 1.9(书籍版式默认)' },\r\n { value: 'loose', label: '宽松', title: '行距 2.25——长时间阅读更省力' },\r\n]\r\n\r\nconst MEASURE_OPTIONS: readonly { value: DocMeasure; label: string; title: string }[] = [\r\n { value: 'auto', label: '跟随版式', title: '书籍 42em / 网页 56em(默认)' },\r\n { value: 'narrow', label: '窄', title: '34em——每行字数最少,眼睛回扫路径短' },\r\n { value: 'wide', label: '宽', title: '64em——大屏上少留白' },\r\n { value: 'full', label: '全宽', title: '不限宽,铺满整个阅读区(窗口小时最有用)' },\r\n]\r\n\r\nconst PAPER_OPTIONS: readonly { value: DocPaper; label: string; title: string }[] = [\r\n { value: 'theme', label: '跟随主题', title: '与 DSH 明暗主题一致(默认)' },\r\n { value: 'white', label: '纸白', title: '纯白纸面 + 深墨字——对比最高' },\r\n { value: 'sepia', label: '米黄', title: '暖黄纸面——降低蓝光与眩光' },\r\n { value: 'green', label: '护眼', title: '浅豆绿纸面——长时间阅读' },\r\n { value: 'dark', label: '夜间', title: '深色纸面 + 浅墨字——暗环境阅读' },\r\n]\r\n\r\n/** 快捷键提示(面板底部常驻)。 */\r\nconst SHORTCUT_HINT = '快捷键:+ / − 字号 · 0 复位 · Z 专注 · F 全屏 · O 目录 · Esc 退出专注'\r\n\r\ninterface Props {\r\n /** 当前是否打开了可阅读的正文(adoc/md);为 false 时(未打开文档 / 选中课件)整组按钮不出现。 */\r\n docOpen: boolean\r\n /** 全屏开关:由各工作台用 useFullscreen 绑定自己的根节点。 */\r\n fullscreen: FullscreenControl\r\n /** 阅读设置面板的开合状态由工作台持有(全屏顶栏自动隐藏要读它)。 */\r\n menuOpen: boolean\r\n onMenuOpenChange: (open: boolean) => void\r\n /** 「专注」会隐藏哪两块内容——两个工作台的措辞不同,由调用方给出。 */\r\n zenHides: string\r\n}\r\n\r\n/**\r\n * 顶栏阅读控件组:目录 / 版式 / 阅读设置 / 专注 / 全屏。\r\n * 各工作台自己的按钮(文件树、复制路径、Git、保存…)由调用方另行摆放。\r\n */\r\nexport function ReaderControls({ docOpen, fullscreen, menuOpen, onMenuOpenChange, zenHides }: Props): JSX.Element {\r\n const prefs = useReaderPrefs()\r\n // 「专注」把内容入口(文件树 / 指令栏)藏起来,因此只要专注是开着的就必须留着这个按钮,\r\n // 否则关掉文档后既看不见文件树、又找不到退出专注的入口,只能靠快捷键 Z 自救。\r\n const showZen = docOpen || prefs.zen\r\n\r\n return (\r\n <>\r\n {docOpen && (\r\n <>\r\n <button\r\n className={css.tbBtn}\r\n onClick={() => setOutlineOpen(!prefs.outlineOpen)}\r\n title={prefs.outlineOpen ? '隐藏本页目录(快捷键 O)' : '显示本页目录(快捷键 O)'}\r\n aria-pressed={prefs.outlineOpen}\r\n >\r\n <ListIcon size={12} /> 目录\r\n </button>\r\n <button\r\n className={css.tbBtn}\r\n onClick={() => setDocLayout(prefs.layout === 'book' ? 'web' : 'book')}\r\n title={prefs.layout === 'book' ? '当前:书籍版式(衬线 / 首行缩进 / 限宽版心)——点击切换为网页版式' : '当前:网页版式(无衬线 / 左对齐 / 宽版心)——点击切换为书籍版式'}\r\n aria-pressed={prefs.layout === 'book'}\r\n >\r\n {prefs.layout === 'book' ? <BookIcon size={12} /> : <PageIcon size={12} />}\r\n {prefs.layout === 'book' ? '书籍版式' : '网页版式'}\r\n </button>\r\n\r\n {/* 阅读设置:字号 / 字体 / 行距 / 版心 / 底色都收在这一处,避免顶栏堆一排按钮 */}\r\n <div className={css.readerWrap}>\r\n <button\r\n className={menuOpen ? `${css.tbBtn} ${css.tbBtnOn}` : css.tbBtn}\r\n onClick={() => onMenuOpenChange(!menuOpen)}\r\n title=\"阅读设置:字号 / 字体 / 行距 / 版心 / 底色\"\r\n aria-expanded={menuOpen}\r\n aria-haspopup=\"dialog\"\r\n >\r\n <TypeIcon size={12} /> 阅读设置\r\n </button>\r\n {menuOpen && (\r\n <>\r\n <div className={css.menuBackdrop} onClick={() => onMenuOpenChange(false)} />\r\n <div className={css.readerMenu} role=\"dialog\" aria-label=\"阅读设置\">\r\n <div className={css.readerMenuHead}>\r\n <SlidersIcon size={12} />\r\n 阅读设置\r\n </div>\r\n <div className={css.readerRow}>\r\n <span className={css.readerRowLabel}>字号</span>\r\n <div className={css.readerSeg} role=\"group\" aria-label=\"字号\">\r\n <button\r\n type=\"button\"\r\n className={css.readerSegBtn}\r\n onClick={() => nudgeFontStep(-1)}\r\n disabled={prefs.fontStep === 0}\r\n title=\"缩小一档(快捷键 -)\"\r\n >\r\n A−\r\n </button>\r\n <span className={css.readerFontValue} title=\"相对 DSH 全局字号的倍率\">\r\n {Math.round((FONT_STEPS[prefs.fontStep] ?? 1) * 100)}%\r\n </span>\r\n <button\r\n type=\"button\"\r\n className={css.readerSegBtn}\r\n onClick={() => nudgeFontStep(1)}\r\n disabled={prefs.fontStep === FONT_STEPS.length - 1}\r\n title=\"放大一档(快捷键 +)\"\r\n >\r\n A+\r\n </button>\r\n <button type=\"button\" className={css.readerSegBtn} onClick={resetFontStep} title=\"复位到 100%(快捷键 0)\">\r\n 复位\r\n </button>\r\n </div>\r\n </div>\r\n <Seg label=\"字体\" value={prefs.font} options={FONT_OPTIONS} onChange={setDocFont} />\r\n <Seg label=\"行距\" value={prefs.leading} options={LEADING_OPTIONS} onChange={setDocLeading} />\r\n <Seg label=\"版心\" value={prefs.measure} options={MEASURE_OPTIONS} onChange={setDocMeasure} />\r\n <Seg label=\"底色\" value={prefs.paper} options={PAPER_OPTIONS} onChange={setDocPaper} />\r\n <div className={css.readerHint}>{SHORTCUT_HINT}</div>\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n </>\r\n )}\r\n\r\n {/* 「专注」把内容入口(文件树 / 指令栏)藏起来,因此只要专注开着就必须留着这个按钮:\r\n 否则关掉文档后既看不见文件树、又找不到退出专注的入口,只能靠快捷键 Z 自救。 */}\r\n {showZen && (\r\n <button\r\n className={prefs.zen ? `${css.tbBtn} ${css.tbBtnOn}` : css.tbBtn}\r\n onClick={() => setZen(!prefs.zen)}\r\n title={prefs.zen ? `退出专注(恢复${zenHides},快捷键 Z)` : `专注:隐藏${zenHides},正文独占(快捷键 Z)`}\r\n aria-pressed={prefs.zen}\r\n >\r\n <ZenIcon size={12} />\r\n 专注\r\n </button>\r\n )}\r\n\r\n {docOpen && (\r\n <button\r\n className={fullscreen.active ? `${css.tbBtn} ${css.tbBtnOn}` : css.tbBtn}\r\n onClick={fullscreen.toggle}\r\n title={fullscreen.active ? '退出全屏(快捷键 F / Esc)' : '全屏:整个工作台铺满屏幕(快捷键 F)'}\r\n aria-pressed={fullscreen.active}\r\n >\r\n {fullscreen.active ? <ShrinkIcon size={12} /> : <ExpandIcon size={12} />}\r\n {fullscreen.active ? '退出全屏' : '全屏'}\r\n </button>\r\n )}\r\n </>\r\n )\r\n}\r\n","/**\n * 视图可见性门控(viewActive)——保活(keep-alive)下把隐藏标签的活停下来。\n *\n * ## 为什么需要\n *\n * 宿主给会话视图打了本地硬化补丁(dsh-client-ui-conversation 的 `wdf2026-keepalive`):\n * 访问过的标签都常驻 DOM,非激活者 `display:none`。好处是切回来还是原来那一份内容\n * (已打开的文档、目录树、Slidev 播放器、滚动位置都在);代价是**隐藏的工作台仍在跑 JS**:\n * · 仿真组件的 `setInterval(calc, 500)` / `requestAnimationFrame` 循环照转(60fps 的\n * 画布动画在后台继续算);\n * · Git 状态每 60s 拉一次 `/aero-kb/git/repos`(一次 git 调用 = 若干子进程)。\n * 于是\"在对话里打字/滚动\"会跟后台的隐藏标签抢主线程——这也是「插件整体卡顿」的一部分。\n *\n * ## 做法\n *\n * 每个工作台绑一个门(gate):`bind(根元素)` 之后,门用 `checkVisibility()` 判断根元素\n * 是否真的被渲染(祖先 `display:none` 时为 false;不依赖宿主一定带 data-* 标记)。\n * · `interval(fn, ms)`:到点先问门,隐藏就跳过本次 tick;\n * · `raf(cb)` / `cancelRaf(id)`:隐藏时**不排帧**、把回调挂起,可见后由看门狗续上。\n * 严格说:切换发生的那一帧可能已经排进队列(隐藏前就算好的),所以\"停住\"的准确\n * 语义是**最多再跑一帧**——随后立刻挂起,不再以 60fps 空转。\n *\n * ## 关键取舍\n *\n * 1. **只在\"确证隐藏\"时暂停**:没绑定元素、元素已卸载、浏览器不支持 `checkVisibility`\n * 且量不到盒子时,一律按\"可见\"处理——宁可多算,不可让画面停死。\n * 2. **自纠错,不依赖事件**:可见性采样节流 250ms,由 tick 与看门狗自己驱动。宿主是\n * display 切换、React 重渲染还是整棵树替换,都不影响判定。\n * 3. **挂起的 rAF 必须有唤醒**:隐藏期间没人调 `raf()`,所以挂起后起一个 250ms 的\n * 看门狗轮询;一旦可见就把挂起的回调续排。看门狗只在有挂起项时存在。\n * 4. **id 语义与浏览器一致**:`interval` 返回真实 interval id(可直接 `clearInterval`);\n * `raf` 返回门自己的 id(用 `cancelRaf` 清),回调里再次 `raf()` 会拿到新 id——\n * 与\"每帧重新 `requestAnimationFrame(loop)`\"的写法兼容。\n */\n\n/** 可见性采样节流(ms):太小会让隐藏期间也在量样式,太大则切回来有肉眼延迟。 */\nconst SAMPLE_THROTTLE_MS = 250\n\n/** 元素是否真的被渲染。无法判断时一律返回 true(不误停)。 */\nfunction isShown(el: Element | null): boolean {\n if (el === null || !el.isConnected) return true\n const probe = el as HTMLElement & { checkVisibility?: () => boolean }\n if (typeof probe.checkVisibility === 'function') return probe.checkVisibility()\n return el.getClientRects().length > 0\n}\n\nexport interface ViewGate {\n /** 绑定工作台根元素(传 null 解绑)。绑定后按该元素的可见性判定。 */\n bind(el: Element | null): void\n /** 当前是否可见(内部节流采样)。 */\n isActive(): boolean\n /** 可见时才 tick 的 setInterval;返回浏览器 interval id,可直接 clearInterval。 */\n interval(fn: () => void, ms: number): number\n /** 可见时才排帧的 requestAnimationFrame;返回门 id,用 cancelRaf 取消。 */\n raf(cb: FrameRequestCallback): number\n /** 取消一个 raf 门 id(重复取消、取消已完成的 id 都安全)。 */\n cancelRaf(id: number): void\n /** 正在挂起等待可见的帧数(诊断用;测试与探针断言可见性) */\n pendingFrames(): number\n}\n\n/** 创建一个独立的门(每个工作台一个,互不影响)。 */\nexport function createViewGate(): ViewGate {\n let el: Element | null = null\n let active = true\n let sampledAt = 0\n\n /** 挂起/进行中的帧:门 id → 回调与浏览器帧 id。 */\n const frames = new Map<number, { cb: FrameRequestCallback; native: number }>()\n let nextFrameId = 1\n let watchdog: number | null = null\n\n function sample(force = false): boolean {\n const now = Date.now()\n if (!force && now - sampledAt < SAMPLE_THROTTLE_MS) return active\n sampledAt = now\n active = isShown(el)\n return active\n }\n\n function parkedFrames(): number {\n let n = 0\n for (const frame of frames.values()) if (frame.native === 0) n += 1\n return n\n }\n\n /** 有帧在挂起时起看门狗;一旦可见就续排所有挂起的帧。 */\n function keepWatching(): void {\n if (watchdog !== null) return\n watchdog = window.setTimeout(() => {\n watchdog = null\n if (!sample(true)) {\n if (parkedFrames() > 0) keepWatching()\n return\n }\n for (const [id, frame] of frames) if (frame.native === 0) schedule(id, frame.cb)\n }, SAMPLE_THROTTLE_MS)\n }\n\n function schedule(id: number, cb: FrameRequestCallback): void {\n const frame = frames.get(id)\n if (frame === undefined) return\n if (!sample()) {\n frame.native = 0\n keepWatching()\n return\n }\n frame.native = window.requestAnimationFrame((time) => {\n // 本帧已消费:id 立刻失效(与浏览器语义一致),回调里要续帧就再 raf 一次\n frames.delete(id)\n cb(time)\n })\n }\n\n return {\n bind(next: Element | null): void {\n el = next\n sample(true)\n },\n isActive(): boolean {\n return sample()\n },\n interval(fn: () => void, ms: number): number {\n return window.setInterval(() => {\n if (sample()) fn()\n }, ms)\n },\n raf(cb: FrameRequestCallback): number {\n const id = nextFrameId\n nextFrameId += 1\n frames.set(id, { cb, native: 0 })\n schedule(id, cb)\n return id\n },\n cancelRaf(id: number): void {\n const frame = frames.get(id)\n if (frame === undefined) return\n frames.delete(id)\n if (frame.native !== 0) window.cancelAnimationFrame(frame.native)\n },\n pendingFrames(): number {\n return parkedFrames()\n },\n }\n}\n\n/** 仿真工作台的门(SimWorkspace 绑定根元素;各 sim 的定时器/帧循环用它)。 */\nexport const simViewGate = createViewGate()\n\n/** 学习资料工作台的门(Git 轮询等后台活用它)。 */\nexport const libraryViewGate = createViewGate()\n","import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'\r\nimport type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\r\nimport type { CatalogResponse, DocRenderResult, KbTreeNode } from '../types.js'\r\nimport { DocViewer } from './DocViewer.js'\r\nimport { SlidevDeckViewer } from './SlidevDeckViewer.js'\r\nimport { buildContextPrompt, ensureGlobalCss, type ReadingContext } from './prose.js'\r\nimport { sendFilledDraft } from './submitDraft.js'\r\nimport { GitPanel, GitStatusButton } from './GitPanel.js'\r\nimport { ChevronIcon, CopyIcon, FolderIcon, RefreshIcon, SidebarIcon } from './icons.js'\r\nimport { setSidebarOpen, setZen, useReaderPrefs } from './readerPrefs.js'\r\nimport { ReaderControls, useFullscreen, useReaderShortcuts } from './readerControls.js'\r\nimport { libraryViewGate } from './viewActive.js'\r\nimport css from './styles.module.css.gen.ts'\r\n\r\ntype Props = PropsRuntime<'conversation.view'>\r\n\r\ninterface DocState {\r\n kind: 'doc'\r\n relPath: string\r\n result: DocRenderResult | null\r\n error: string | null\r\n}\r\n\r\ninterface DeckState {\r\n kind: 'slidev'\r\n relPath: string\r\n name: string\r\n}\r\n\r\n/** 正在取回/渲染的文档:点下去立刻给反馈,不让右侧停在空窗格(这是「点了没反应」的观感来源)。 */\r\ninterface LoadingState {\r\n kind: 'loading'\r\n relPath: string\r\n name: string\r\n /** 分段文档翻段时的段号(0 起)。 */\r\n seg: number\r\n}\r\n\r\ntype ContentState = DocState | DeckState | LoadingState | null\r\n\r\nfunction flattenLeaves(nodes: readonly KbTreeNode[], out: KbTreeNode[] = []): KbTreeNode[] {\r\n for (const n of nodes) {\r\n if (n.type === 'group') flattenLeaves(n.children ?? [], out)\r\n else out.push(n)\r\n }\r\n return out\r\n}\r\n\r\n/** 文件类型字母徽章(ext → {label, cssClass})。 */\r\nfunction fileChipOf(ext: string | undefined, type: KbTreeNode['type']): { label: string; cls: string | undefined } {\r\n if (type === 'deck') return { label: 'S', cls: css.chipSlides }\r\n const e = (ext ?? '').toLowerCase()\r\n if (e === 'md' || e === 'markdown') return { label: 'MD', cls: css.chipMd }\r\n if (e === 'adoc' || e === 'asciidoc') return { label: 'AD', cls: css.chipAdoc }\r\n if (e === 'yml' || e === 'yaml') return { label: 'YML', cls: css.chipYml }\r\n if (e === 'txt' || e === 'text') return { label: 'TXT', cls: css.chipTxt }\r\n if (e === 'pdf') return { label: 'PDF', cls: css.chipPdf }\r\n return { label: e === '' ? '?' : e.slice(0, 4).toUpperCase(), cls: css.chipOther }\r\n}\r\n\r\n/**\r\n * 默认展开到第几层分组(`0` = 只展开顶层 11 个分组,它们的**下一层**可见但不再展开)。\r\n *\r\n * 曾经是 2:顶层与第二层分组全开,于是「参考书」一个分组就把 33 本书的 1028 个章节\r\n * 按钮一次性塞进 DOM——整棵树 2053 个节点全部落地(约一万个 DOM 元素),切标签/首次\r\n * 进入学习资料都要为这些看不见的节点付样式与布局成本。\r\n *\r\n * 现在默认只开顶层,**并且子节点只在展开时才渲染**(见 TreeNode):首屏只有 120 个\r\n * 分组行(11 + 109),元素数掉到一千以内;要看某本书的章节再点开那一层,或用搜索框\r\n * (扁平结果,一次最多 200 条)。\r\n */\r\nconst DEFAULT_OPEN_DEPTH = 0\r\n\r\n/**\r\n * 目录树节点。**必须 memo**:知识库有 1500+ 个文件节点,而本工作台订阅了输入框草稿\r\n * (`useInput(s => s.draft)`),在对话里每敲一个字都会重渲染整棵树——不 memo 的话,\r\n * 打字/滚动时整页都在重排一千多个节点,这正是「插件很卡」的主要来源之一。\r\n *\r\n * `<details>` 的子树只在展开时渲染:关闭的分组不进 DOM(memo + 惰性子节点共同把首屏\r\n * 节点数从 2053 压到 120 行)。\r\n */\r\nconst TreeNode = memo(function TreeNode({ node, selected, onSelect, depth }: {\r\n node: KbTreeNode\r\n selected: boolean\r\n onSelect: (n: KbTreeNode) => void\r\n depth: number\r\n}): JSX.Element {\r\n const [open, setOpen] = useState(depth <= DEFAULT_OPEN_DEPTH)\r\n if (node.type === 'group') {\r\n return (\r\n <details\r\n className={css.group}\r\n open={open}\r\n onToggle={(e) => setOpen(e.currentTarget.open)}\r\n >\r\n <summary className={css.groupLabel}>\r\n <span className={css.chevron}><ChevronIcon size={11} /></span>\r\n <FolderIcon size={13} />\r\n <span className={css.leafText}>{node.name}</span>\r\n </summary>\r\n <div className={css.groupChildren}>\r\n {open && (node.children ?? []).map((c) => (\r\n <TreeNode key={c.id} node={c} selected={selected} onSelect={onSelect} depth={depth + 1} />\r\n ))}\r\n </div>\r\n </details>\r\n )\r\n }\r\n const chip = fileChipOf(node.ext, node.type)\r\n return (\r\n <button\r\n className={selected ? `${css.leaf} ${css.leafActive}` : css.leaf}\r\n onClick={() => onSelect(node)}\r\n title={node.path}\r\n >\r\n <span className={`${css.fileChip} ${chip.cls}`}>{chip.label}</span>\r\n <span className={css.leafText}>{node.name}</span>\r\n </button>\r\n )\r\n})\r\n\r\n/** 整棵树(分组顶层)。与 TreeNode 同理 memo:草稿变化不重渲染。 */\r\nconst TreeView = memo(function TreeView({ groups, selectedPath, onSelect }: {\r\n groups: readonly KbTreeNode[]\r\n selectedPath: string | null\r\n onSelect: (n: KbTreeNode) => void\r\n}): JSX.Element {\r\n return (\r\n <>\r\n {groups.map((g) => (\r\n <TreeNode key={g.id} node={g} selected={selectedPath === g.path} onSelect={onSelect} depth={0} />\r\n ))}\r\n </>\r\n )\r\n})\r\n\r\n/**\r\n * 全屏下顶栏自动隐藏的\"浮现区\"高度(px)。取顶栏自身高度:鼠标进入这条带子就浮现,\r\n * 移出即隐——阈值必须覆盖顶栏全文,否则鼠标停在顶栏下沿会把它闪没。\r\n */\r\nconst FULLSCREEN_TOPBAR_ZONE = 36\r\n\r\n/**\r\n * 鼠标离开浮现区后,顶栏再停留多久才收起(ms)。\r\n *\r\n * 必须是\"延迟收起\"而不是\"立刻收起\":鼠标移向顶栏按钮的路上必然短暂掉出浮现区\r\n * (手是抖的),一掉出就收走会让按钮根本点不到——这正是先前的可用性缺陷。\r\n * 停够这段时间,用户从屏幕任意位置抬手过来都能稳稳点到。\r\n */\r\nconst FULLSCREEN_TOPBAR_HIDE_DELAY = 2500\r\n\r\nexport function LibraryWorkspace(props: Props): JSX.Element {\r\n const { inputActions, sessionId, useInput, useSessions } = props\r\n // 会话工作目录:作为解析知识库根目录的线索传给宿主(否则宿主只能猜 dsh 进程的 cwd)。\r\n const cwd = useSessions((s: { byId: Record<string, { cwd?: string } | undefined> }) => s.byId[sessionId]?.cwd)\r\n // 输入区已发布的草稿:用于\"填入后自动发送\"时判断草稿是否已经进到输入框(见 submitDraft.ts)。\r\n const publishedDraft = useInput((s: { draft: string }) => s.draft)\r\n const draftRef = useRef(publishedDraft)\r\n draftRef.current = publishedDraft\r\n const cwdParam = cwd !== undefined && cwd !== '' ? `&cwd=${encodeURIComponent(cwd)}` : ''\r\n const [catalog, setCatalog] = useState<CatalogResponse | null>(null)\r\n const [catalogError, setCatalogError] = useState<string | null>(null)\r\n const [catalogKey, setCatalogKey] = useState(0)\r\n const [selectedPath, setSelectedPath] = useState<string | null>(null)\r\n const [content, setContent] = useState<ContentState>(null)\r\n const [reading, setReading] = useState<ReadingContext | null>(null)\r\n const [question, setQuestion] = useState('')\r\n const [search, setSearch] = useState('')\r\n const [gitOpen, setGitOpen] = useState(false)\r\n const [gitKey, setGitKey] = useState(0)\r\n const [copied, setCopied] = useState(false)\r\n const [readerMenu, setReaderMenu] = useState(false)\r\n const [topbarShown, setTopbarShown] = useState(true)\r\n const rootRef = useRef<HTMLDivElement>(null)\r\n // 全屏:作用于工作台根节点,让「学习资料」整页铺满屏幕(浏览器 Fullscreen API)。\r\n // 顶部「全屏」按钮与 F 快捷键由顶栏的 ReaderControls / useReaderShortcuts 提供。\r\n const fullscreen = useFullscreen(rootRef)\r\n const isFullscreen = fullscreen.active\r\n // 阅读设置面板是否打开(供 mousemove 监听读取,避免把它写进依赖导致反复重订阅)\r\n const readerMenuRef = useRef(readerMenu)\r\n readerMenuRef.current = readerMenu\r\n // 阅读器偏好(版式 / 字号 / 字体 / 行距 / 版心 / 底色 / 专注 / 目录):存在 client 本地,\r\n // DocViewer 订阅同一份状态(见 readerPrefs.ts)。\r\n const prefs = useReaderPrefs()\r\n const docOpen = content !== null && content.kind === 'doc' && content.error === null\r\n\r\n // 把工作台根元素绑到\"学习资料门\"(viewActive.ts):宿主保活让本页在切走后仍留在\r\n // DOM 里,绑上之后后台轮询(Git 状态,每 60s 一次 git 子进程)在隐藏时自动跳过。\r\n useEffect(() => {\r\n libraryViewGate.bind(rootRef.current)\r\n return () => libraryViewGate.bind(null)\r\n }, [])\r\n\r\n // Esc 的阅读侧收尾:关掉阅读设置面板、退出专注(全屏由浏览器自身退出)。\r\n const onEscape = useCallback((): void => {\r\n setReaderMenu(false)\r\n setZen(false)\r\n }, [])\r\n useReaderShortcuts(rootRef, fullscreen.toggle, onEscape)\r\n\r\n // 全屏下顶栏自动隐藏:鼠标进入顶部浮现区(或键盘聚焦、或阅读设置面板打开)时立即浮现;\r\n // 移出浮现区后**再停留 FULLSCREEN_TOPBAR_HIDE_DELAY 毫秒**才收起。\r\n // 延迟是为了可用性:手移向顶栏按钮的路上会短暂掉出浮现区,立刻收起就点不到了。\r\n const hideTimerRef = useRef<number | null>(null)\r\n const clearHideTimer = useCallback((): void => {\r\n if (hideTimerRef.current !== null) {\r\n window.clearTimeout(hideTimerRef.current)\r\n hideTimerRef.current = null\r\n }\r\n }, [])\r\n const revealTopbar = useCallback((): void => {\r\n clearHideTimer()\r\n setTopbarShown(true)\r\n }, [clearHideTimer])\r\n const scheduleTopbarHide = useCallback((): void => {\r\n if (hideTimerRef.current !== null) return // 已经进入倒计时:不因继续移动而刷新窗口\r\n hideTimerRef.current = window.setTimeout(() => {\r\n hideTimerRef.current = null\r\n if (!readerMenuRef.current) setTopbarShown(false)\r\n }, FULLSCREEN_TOPBAR_HIDE_DELAY)\r\n }, [])\r\n\r\n useEffect(() => {\r\n if (!isFullscreen) {\r\n clearHideTimer()\r\n setTopbarShown(true)\r\n return\r\n }\r\n const onMove = (e: MouseEvent): void => {\r\n if (e.clientY <= FULLSCREEN_TOPBAR_ZONE || readerMenuRef.current) revealTopbar()\r\n else scheduleTopbarHide()\r\n }\r\n window.addEventListener('mousemove', onMove)\r\n return () => {\r\n window.removeEventListener('mousemove', onMove)\r\n clearHideTimer()\r\n }\r\n }, [isFullscreen, revealTopbar, scheduleTopbarHide, clearHideTimer])\r\n\r\n // 阅读快捷键(+ / − / 0 / Z / O / F / Esc)在 readerControls 里统一实现:\r\n // 与「备课」工作台共用一份,两处不会各写一套键位与默认值。\r\n\r\n useEffect(() => {\r\n ensureGlobalCss()\r\n let cancelled = false\r\n const refresh = catalogKey > 0 ? '&refresh=1' : ''\r\n const qs = cwdParam === '' && refresh === '' ? '' : `?${(cwdParam + refresh).slice(1)}`\r\n fetch(`/aero-kb/catalog${qs}`)\r\n .then((r) => (r.ok ? r.json() as Promise<CatalogResponse> : Promise.reject(new Error(`HTTP ${r.status}`))))\r\n .then((d) => {\r\n if (cancelled) return\r\n if (d.error) setCatalogError(d.error)\r\n else setCatalog(d)\r\n })\r\n .catch((e) => {\r\n if (!cancelled) setCatalogError(e instanceof Error ? e.message : String(e))\r\n })\r\n return () => {\r\n cancelled = true\r\n }\r\n }, [cwdParam, catalogKey])\r\n\r\n const selectSeqRef = useRef(0)\r\n\r\n /** 取回并渲染一个文档(可带分段号);序号守卫保证快速连点时只认最后一次。 */\r\n const loadDoc = useCallback((relPath: string, name: string, seg: number) => {\r\n const seq = ++selectSeqRef.current\r\n setContent({ kind: 'loading', relPath, name, seg })\r\n const segParam = seg > 0 ? `&seg=${String(seg)}` : ''\r\n fetch(`/aero-kb/doc?p=${encodeURIComponent(relPath)}${cwdParam}${segParam}`)\r\n .then(async (r) => {\r\n let body: unknown = null\r\n try {\r\n body = await r.json()\r\n } catch {\r\n /* 非 JSON 响应(如网关 502),走通用错误分支 */\r\n }\r\n if (!r.ok) {\r\n // 宿主在 4xx/5xx 时仍返回 JSON 错误体,优先展示其中的 error 说明,而非笼统的 HTTP 状态码。\r\n const err = typeof (body as { error?: unknown } | null)?.error === 'string'\r\n ? (body as { error: string }).error\r\n : `HTTP ${r.status}`\r\n throw new Error(err)\r\n }\r\n return body\r\n })\r\n .then((result) => {\r\n if (seq !== selectSeqRef.current) return\r\n const d = result as DocRenderResult\r\n setContent(d.ok ? { kind: 'doc', relPath, result: d, error: null } : { kind: 'doc', relPath, result: null, error: d.error ?? '渲染失败' })\r\n })\r\n .catch((e) => {\r\n if (seq !== selectSeqRef.current) return\r\n const err = e instanceof Error ? e.message : String(e)\r\n setContent({ kind: 'doc', relPath, result: null, error: err })\r\n })\r\n }, [cwdParam])\r\n\r\n const onSelect = useCallback((node: KbTreeNode) => {\r\n setSelectedPath(node.path)\r\n selectSeqRef.current++\r\n setContent(null)\r\n\r\n // Slidev 课件:交给宿主按需构建 + 播放器渲染(不再走普通 Markdown 渲染)\r\n if (node.type === 'deck') {\r\n setContent({ kind: 'slidev', relPath: node.path, name: node.name })\r\n return\r\n }\r\n loadDoc(node.path, node.name, 0)\r\n }, [loadDoc])\r\n\r\n /** 同一文档翻段(宿主按渲染体积切段,见 src/docsplit.ts)。 */\r\n const onOpenSegment = useCallback((seg: number) => {\r\n const cur = content\r\n if (cur === null || (cur.kind !== 'doc' && cur.kind !== 'loading')) return\r\n const name = cur.kind === 'loading' ? cur.name : (cur.relPath.split('/').pop() ?? cur.relPath)\r\n loadDoc(cur.relPath, name, seg)\r\n }, [content, loadDoc])\r\n\r\n const onReadingChange = useCallback((ctx: ReadingContext) => {\r\n setReading(ctx)\r\n }, [])\r\n\r\n const ask = useCallback((submit: boolean) => {\r\n if (reading === null) return\r\n const text = buildContextPrompt(reading, question)\r\n inputActions.setDraft(text)\r\n // 提交要等草稿真的进到输入框;发送走输入框自己的回车手势(见 submitDraft.ts)。\r\n if (submit) sendFilledDraft(inputActions, text, () => draftRef.current)\r\n }, [reading, question, inputActions])\r\n\r\n /**\r\n * 阅读标注里的「问 AI」:把标注原文 + 自己的想法当问题,拼上当前阅读上下文后发送。\r\n * 与上面「带着这段问 AI」共用同一条发送链(草稿 → 回车手势),不是另一套实现。\r\n */\r\n const askAnnotated = useCallback((text: string) => {\r\n const prompt = reading === null ? text : buildContextPrompt(reading, text)\r\n inputActions.setDraft(prompt)\r\n sendFilledDraft(inputActions, prompt, () => draftRef.current)\r\n }, [reading, inputActions])\r\n\r\n const filtered = useMemo(() => {\r\n const q = search.trim().toLowerCase()\r\n if (q === '' || catalog === null) return null\r\n const leaves = flattenLeaves(catalog.groups)\r\n return leaves.filter((n) => n.name.toLowerCase().includes(q) || n.path.toLowerCase().includes(q)).slice(0, 200)\r\n }, [search, catalog])\r\n\r\n const copyPath = useCallback(() => {\r\n if (selectedPath === null) return\r\n const p = navigator.clipboard?.writeText(selectedPath)\r\n if (p !== undefined) {\r\n void p.then(() => {\r\n setCopied(true)\r\n setTimeout(() => setCopied(false), 1500)\r\n }).catch(() => { /* 剪贴板不可用时静默 */ })\r\n }\r\n }, [selectedPath])\r\n\r\n const onGitChanged = useCallback(() => {\r\n setGitKey((k) => k + 1)\r\n setCatalogKey((k) => k + 1)\r\n }, [])\r\n\r\n const crumbs = useMemo(() => (selectedPath ?? '').split('/').filter((s) => s !== ''), [selectedPath])\r\n\r\n return (\r\n <div\r\n ref={rootRef}\r\n className={css.root}\r\n data-aero-workbench=\"\"\r\n data-zen={prefs.zen ? '1' : '0'}\r\n data-sidebar={prefs.sidebarOpen ? '1' : '0'}\r\n data-fullscreen={isFullscreen ? '1' : '0'}\r\n data-fsbar={topbarShown ? 'shown' : 'hidden'}\r\n >\r\n <div className={css.topbar} onFocus={revealTopbar}>\r\n <span className={css.topbarTitle}>学习资料</span>\r\n {selectedPath !== null && (\r\n <div className={css.crumbs} title={selectedPath}>\r\n {crumbs.map((seg, i) => (\r\n <span key={`${seg}-${i}`}>\r\n {i > 0 && <span className={css.crumbSep}>/</span>}\r\n <span className={i === crumbs.length - 1 ? css.crumbLast : css.crumb}>{seg}</span>\r\n </span>\r\n ))}\r\n </div>\r\n )}\r\n {/* 正文阅读控件(目录 / 版式 / 阅读设置 / 专注 / 全屏):与「备课」工作台共用一份实现 */}\r\n <ReaderControls\r\n docOpen={docOpen}\r\n fullscreen={fullscreen}\r\n menuOpen={readerMenu}\r\n onMenuOpenChange={setReaderMenu}\r\n zenHides=\"文件树与提问栏\"\r\n />\r\n <button\r\n className={prefs.sidebarOpen ? `${css.tbBtn} ${css.tbBtnOn}` : css.tbBtn}\r\n onClick={() => setSidebarOpen(!prefs.sidebarOpen)}\r\n title={prefs.sidebarOpen ? '收起左侧文件树(文档列表)' : '展开左侧文件树(文档列表)——文档看不见时先点这里'}\r\n aria-pressed={prefs.sidebarOpen}\r\n >\r\n <SidebarIcon size={12} /> 文件树\r\n </button>\r\n <button className={css.tbBtn} onClick={copyPath} disabled={selectedPath === null} title=\"复制文档相对路径\">\r\n <CopyIcon size={12} /> {copied ? '已复制' : '复制路径'}\r\n </button>\r\n <button className={css.tbBtn} onClick={() => setCatalogKey((k) => k + 1)} title=\"重新扫描知识库目录\">\r\n <RefreshIcon size={12} />\r\n </button>\r\n <GitStatusButton cwd={cwd} refreshKey={gitKey} onClick={() => setGitOpen((o) => !o)} gate={libraryViewGate} />\r\n </div>\r\n\r\n <div className={css.body}>\r\n <div className={css.sidebar}>\r\n <div className={css.sidebarHeader}>\r\n <input\r\n className={css.search}\r\n placeholder=\"搜索教材/参考书/教案/课件…\"\r\n value={search}\r\n onChange={(e) => setSearch(e.target.value)}\r\n />\r\n </div>\r\n <div className={css.tree}>\r\n {catalogError !== null && <div className={css.empty}>加载目录失败:{catalogError}</div>}\r\n {catalog === null && catalogError === null && <div className={css.empty}>正在加载目录…</div>}\r\n {catalog !== null && filtered === null && (\r\n <TreeView groups={catalog.groups} selectedPath={selectedPath} onSelect={onSelect} />\r\n )}\r\n {filtered !== null && (\r\n <div className={css.flatList}>\r\n {filtered.length === 0 && <div className={css.empty}>无匹配结果</div>}\r\n {filtered.map((n) => (\r\n <button\r\n key={n.id}\r\n className={selectedPath === n.path ? `${css.leaf} ${css.leafActive}` : css.leaf}\r\n onClick={() => onSelect(n)}\r\n title={n.path}\r\n >\r\n <span className={`${css.fileChip} ${fileChipOf(n.ext, n.type).cls}`}>{fileChipOf(n.ext, n.type).label}</span>\r\n <span className={css.leafText}>{n.name}</span>\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n\r\n <div className={css.main}>\r\n <div className={css.content}>\r\n {content === null && (\r\n <div className={css.empty}>\r\n {prefs.zen\r\n ? '左侧文件树已隐藏:当前处于专注模式 —— 点顶栏「专注」按钮退出,或按 Z。'\r\n : (!prefs.sidebarOpen\r\n ? '左侧文件树已收起,看不到文档列表:点顶栏「文件树」按钮展开。'\r\n : '从左侧选择一个文档或课件开始阅读。')}\r\n </div>\r\n )}\r\n {content !== null && content.kind === 'loading' && (\r\n <div className={css.empty}>\r\n <span className={css.loadingDot} /> 正在打开 {content.name}\r\n {content.seg > 0 ? `(第 ${content.seg + 1} 段)` : ''}…\r\n </div>\r\n )}\r\n {content !== null && content.kind === 'doc' && content.error !== null && <div className={css.empty}>加载失败:{content.error}</div>}\r\n {content !== null && content.kind === 'doc' && content.error === null && content.result !== null && (\r\n <DocViewer\r\n key={`${content.relPath}#${String(content.result.seg ?? 0)}`}\r\n relPath={content.relPath}\r\n result={content.result}\r\n cwdParam={cwdParam}\r\n onReadingChange={onReadingChange}\r\n onAsk={askAnnotated}\r\n onOpenDoc={(p) => onSelect({ id: p, name: p, type: 'doc', path: p, children: [] })}\r\n onOpenSegment={onOpenSegment}\r\n />\r\n )}\r\n {content !== null && content.kind === 'slidev' && (\r\n <SlidevDeckViewer\r\n relPath={content.relPath}\r\n name={content.name}\r\n cwdParam={cwdParam}\r\n onReadingChange={onReadingChange}\r\n onAsk={askAnnotated}\r\n />\r\n )}\r\n </div>\r\n\r\n <div className={css.contextBar}>\r\n <div className={css.contextInfo}>\r\n <span className={css.contextDot} />\r\n {reading === null ? (\r\n <span className={css.contextMuted}>正在阅读:—</span>\r\n ) : (\r\n <span className={css.contextText} title={reading.excerpt}>\r\n {reading.title} · {reading.section}\r\n </span>\r\n )}\r\n </div>\r\n <input\r\n className={css.questionInput}\r\n placeholder=\"就当前内容提问…\"\r\n value={question}\r\n onChange={(e) => setQuestion(e.target.value)}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Enter') ask(true)\r\n }}\r\n />\r\n <button\r\n className={css.btnPrimary}\r\n onClick={() => ask(true)}\r\n disabled={reading === null}\r\n title=\"把当前阅读片段填入提问框并发送。若提示「当前会话已被占用」:同一个会话只能被一个 DSH 实例写入,请先退出另一个正在运行的 DSH(如另一个 dsh web),或换一个没有在别处打开的会话再问。\"\r\n >\r\n 带着这段问 AI\r\n </button>\r\n <button className={css.btn} onClick={() => ask(false)} disabled={reading === null} title=\"把上下文填入下方提问框,不立即发送\">\r\n 填入提问框\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {gitOpen && (\r\n <GitPanel cwd={cwd} onChanged={onGitChanged} onClose={() => setGitOpen(false)} />\r\n )}\r\n </div>\r\n </div>\r\n )\r\n}\r\n","/**\n * 「我的库」:多库管理 + 加库向导 + 私人库说明。\n *\n * 样式刻意用内联对象,不依赖 `styles.module.css` 的类名 —— 这一页的排版需求极简,\n * 复用阅读器的样式类会让两处耦合(改阅读器版式会牵到这页)。\n *\n * 口径(P1–P3):只**展示与引导**,不替学生猜路径;私人库明示\"只在本机\"。\n */\nimport { useCallback, useEffect, useState } from 'react'\nimport type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\n\ntype Props = PropsRuntime<'conversation.view'>\n\ninterface LibraryRow {\n id: string\n title: string\n kind: string\n visibility: string\n root: string\n groups: number\n outline?: { id: string; title: string }[]\n}\n\ninterface LibrariesResponse {\n ok?: boolean\n root?: string\n legacy?: boolean\n viewer?: string\n libraries?: LibraryRow[]\n error?: string\n}\n\nconst KIND_LABEL: Record<string, string> = {\n knowledge: '知识手册', 'lesson-plan': '教案', slides: '课件', textbook: '教材',\n reference: '参考书', exercises: '习题', sim: '仿真', notes: '笔记', other: '其他',\n}\nconst VIS_LABEL: Record<string, string> = {\n private: '私人(只在本机)', course: '课程', teacher: '教师端', public: '公开',\n}\n\nconst box: React.CSSProperties = { padding: '14px 16px', fontSize: 13, lineHeight: 1.6 }\nconst row: React.CSSProperties = { border: '1px solid rgba(127,127,127,.28)', borderRadius: 8, padding: '10px 12px', marginBottom: 8 }\nconst badge: React.CSSProperties = { display: 'inline-block', padding: '0 6px', marginLeft: 6, fontSize: 11, lineHeight: '18px', borderRadius: 9, background: 'rgba(127,127,127,.16)' }\nconst warnBadge: React.CSSProperties = { ...badge, background: 'rgba(214,120,0,.18)' }\nconst meta: React.CSSProperties = { color: 'rgba(127,127,127,.95)', fontSize: 12, marginTop: 4 }\nconst pre: React.CSSProperties = { whiteSpace: 'pre-wrap', fontSize: 12, lineHeight: 1.55, padding: '10px 12px', borderRadius: 8, background: 'rgba(127,127,127,.1)', overflowX: 'auto' }\n\nconst WIZARD = `# 在资料目录根放 library.yaml(推荐)\nschema: aero-library/1\nid: my-course\ntitle: 我的另一门课\nkind: notes\nvisibility: private\ngroups:\n - { id: main, label: 笔记, dir: notes, exts: [md, adoc], maxDepth: 3 }\n\n# 或者在工作区根放 libraries.yaml,一次挂多个库\n# libraries:\n# - { path: ./my-course }\n# - { path: ~/资料/高数 }`\n\nexport function MyLibraries(_props: Props): JSX.Element {\n const [state, setState] = useState<LibrariesResponse | null>(null)\n const [error, setError] = useState<string | null>(null)\n\n const load = useCallback(async (): Promise<void> => {\n try {\n const res = await fetch('/kb/libraries?refresh=1')\n const body = (await res.json()) as LibrariesResponse\n setState(body)\n setError(body.error ?? null)\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e))\n }\n }, [])\n\n useEffect(() => {\n void load()\n }, [load])\n\n const rows = state?.libraries ?? []\n\n return (\n <div style={box}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>\n <strong>我的库</strong>\n <span style={meta}>\n {state === null ? '解析中…' : `${rows.length} 个库 · ${state.legacy === true ? 'legacy 布局' : '清单驱动'} · 视图 ${state.viewer ?? '-'}`}\n </span>\n <button onClick={() => void load()} title=\"重新解析\">刷新</button>\n </div>\n\n {error !== null && <div style={{ ...row, marginTop: 10 }}>{error}</div>}\n\n <div style={{ marginTop: 10 }}>\n {rows.map((l) => (\n <div key={l.id} style={row}>\n <div>\n <strong>{l.title}</strong>\n <code style={{ marginLeft: 6 }}>{l.id}</code>\n <span style={badge}>{KIND_LABEL[l.kind] ?? l.kind}</span>\n <span style={l.visibility === 'private' ? warnBadge : badge}>{VIS_LABEL[l.visibility] ?? l.visibility}</span>\n </div>\n <div style={meta}>\n {l.groups} 个分组 · <code>{l.root}</code>\n </div>\n {l.outline !== undefined && l.outline.length > 0 && (\n <div style={meta}>学习路径:{l.outline.map((o) => o.title).join(' → ')}</div>\n )}\n </div>\n ))}\n {rows.length === 0 && state !== null && (\n <div style={row}>还没有解析到库。按下面的片段加一个,刷新即出现。</div>\n )}\n </div>\n\n <div style={{ ...row, marginTop: 12 }}>\n <strong>隐私</strong>\n <ul style={{ margin: '6px 0 0 18px', padding: 0 }}>\n <li>阅读位置、荧光笔、便签提问、AI 对话都只存在这台电脑(<code>localStorage</code> / <code>~/.dsh</code>),不上传、不云同步、无遥测。</li>\n <li>标为<em>私人</em>的库只在本机三个出口(目录 / 检索 / 给模型的上下文)出现;导出、分享、发布一律拒绝。</li>\n </ul>\n </div>\n\n <div style={{ marginTop: 12 }}>\n <strong>加一个库(两分钟)</strong>\n <pre style={pre}>{WIZARD}</pre>\n </div>\n </div>\n )\n}\n","/**\n * 客户端入口:两个标签页。\n *\n * - 「学习资料」(order 10):目录树 + 书籍版式阅读 + 标注 + 课件只读播放 + 阅读上下文提问\n * - 「我的库」(order 20):库列表、加库向导、私人库说明、每库 Git 状态\n *\n * 边界:不含仿真(sim-kit)、不含备课写回(prep-kit)。\n */\nimport type { Context as ClientContext } from '@deepseek-ai/cordis'\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-session/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-slots'\nimport type {} from '@deepseek-ai/dsh-client-ui-workspace/client'\nimport { LibraryWorkspace } from './LibraryWorkspace.js'\nimport { MyLibraries } from './MyLibraries.js'\n\nexport const inject = ['slots', 'sessions', 'uiWorkspace']\n\nexport function apply(ctx: ClientContext): void {\n ctx.slots.inject('conversation.view', () => ctx.slots.register({\n name: 'conversation.view',\n id: 'study-kit-library',\n order: 10,\n label: () => '学习资料',\n }, LibraryWorkspace))\n\n ctx.slots.inject('conversation.view', () => ctx.slots.register({\n name: 'conversation.view',\n id: 'study-kit-my-libraries',\n order: 20,\n label: () => '我的库',\n }, MyLibraries))\n}\n"],"mappings":"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"}