dsh-quote-annotate-pro 0.2.8 → 0.2.10

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
  本项目的所有重要变更都记在这里。版本号遵循 [SemVer](https://semver.org/lang/zh-CN/)。
4
4
 
5
+ ## 0.2.10 — 文档更正:如实披露 localhost 诊断探测
6
+
7
+ - PR #697(`0xsline/awesome-deepseek-harness`)**已合并**,但维护者把我们的收录文案从 "no network access" 改写成
8
+ *"the client enables localhost diagnostic requests by default"* —— 因为插件默认确实会向 `127.0.0.1:47821` 发一次探测
9
+ - README / README.en 新增「隐私 / 网络」小节:如实说明"纯客户端、不访问外部服务、不碰凭证",
10
+ 但**默认会向本机 47821 发一次探测**;想让"零请求"成真就设 `DIAG_ENABLED = false`
11
+ - 发布工具包 `PR-TEXTS.md` 同步改写(EN/ZH 两处模板 + 复查清单加了一条 ⚠️ 提醒),避免后续插件再写错
12
+ - 仅文档变更,代码行为不变
13
+
14
+ ## 0.2.9 — 编辑框定位再修:排除"贴文档原点"的退化矩形
15
+
16
+ - 0.2.8 只拦了"尺寸为 0"的矩形;实测选区被打断后 `getBoundingClientRect()` 会返回**贴文档原点、但高度非 0** 的退化矩形,仍会算出 `left≈12 / top≈8`(窗口左上角)
17
+ - 现在取值优先级为:**当前还活着的选区** → 存下来的矩形(需通过 `plausibleRect()`:有限值、有尺寸、**不在原点附近**、不越出视口)→ **视口底部居中**
18
+ - 新增诊断 `editor:anchor`(只记来源与矩形,不记内容),便于下次一眼定位
19
+ - 文本与模型侧行为不变
20
+
5
21
  ## 0.2.8 — 修复"批注编辑框跑到窗口左上角 / 引用不了"
6
22
 
7
23
  - **现象**:选中文字点「批注」后,编辑框出现在窗口左上角(压住侧边栏),看起来像引用功能坏了
package/README.en.md CHANGED
@@ -81,6 +81,12 @@ npm run diag # local diagnostics sink (http://127.0.0.1:47821)
81
81
 
82
82
  `lib/client.js` is a hand-written bundle (no build step) — edit and save; the client HMR reloads it. See [README.md](./README.md) (Chinese) for the diagnostics channel and known limitations.
83
83
 
84
+ ### Privacy / network (state this accurately in directory entries)
85
+
86
+ This is a client-side plugin: **no external services, no credentials**. Its only data store is the anchor map in `localStorage` (≤60 entries per session).
87
+
88
+ ⚠️ It **does** send one probe to `http://127.0.0.1:47821` on load by default (`DIAG_ENABLED = true`) plus diagnostics once a local sink answers — so **do not describe it as "no network access"**. On 2026-10-16 the `0xsline/awesome-deepseek-harness` maintainer corrected exactly that claim while merging our entry to *"the client enables localhost diagnostic requests by default"*. Set `DIAG_ENABLED = false` if you want zero requests to be literally true.
89
+
84
90
  ## Releasing (maintainers)
85
91
 
86
92
  Releases go through **npm Trusted Publishing (OIDC)** — no token is stored in the repository and no one-time code is needed:
package/README.md CHANGED
@@ -129,6 +129,14 @@ const DIAG_URL = 'http://127.0.0.1:47821/dsh-quote-pro'
129
129
  插件启动时 POST 一次 `/ping`;**探测不到接收端就本次运行静默**(不会产生网络噪音)。
130
130
  配合 `npm run diag`,终端会实时打出全链路事件:
131
131
 
132
+ > ⚠️ **隐私 / 网络说明(收录信息里必须如实写)**:本插件是纯客户端插件,**不访问任何外部服务、不碰凭证**,
133
+ > 唯一的数据落点是 `localStorage` 里的锚点表(每会话 ≤60 条)。
134
+ > 但它默认会向**本机** `http://127.0.0.1:47821` 发一次探测(以及探测成功后的诊断事件)——
135
+ > 这是 `DIAG_ENABLED = true` 的默认行为,**不要写成"零网络请求"**。
136
+ > 2026-10-16 我们就因为这句不准确的表述,被 `0xsline/awesome-deepseek-harness` 的维护者在合并时改写成
137
+ > *"the client enables localhost diagnostic requests by default"*。想让"无网络请求"成为事实,就把 `DIAG_ENABLED` 改成 `false`。
138
+
139
+
132
140
  ```
133
141
  module:materialized / apply:start / register:ok … 插件加载与槽位注册
134
142
  selection:show / selection:stage 划词与「批注」
package/lib/client.js CHANGED
@@ -1,6 +1,16 @@
1
1
  // dsh-quote-annotate-pro —— Client 半区(浏览器)
2
2
  // Fork of dsh-quote-annotate v0.1.1 (MIT, wangwei-wade) —— 增强:精确锚点 / 可观测性
3
3
  // 上游 bundle 形态保留:window.__ModuleLoader__ 工厂式 CJS
4
+ //
5
+ // ⚠️ 开发注意(踩过的坑,改装饰逻辑前必读)
6
+ // 1) 装饰(把"【引用 · 第N轮 · 角色】+ 原文"重排成紧凑块)**绝不能破坏用户当前选区**:
7
+ // 一旦替换了用户正在划词的文本节点,range.getBoundingClientRect() 会退化成"贴文档原点"的矩形,
8
+ // 用它算出的位置正好是 left≈12/top≈8 —— 批注编辑框就跑到窗口左上角(0.2.8 的现象)。
9
+ // 因此:① 扫描时用 selectionTouches(row) 跳过用户正在划词的那条消息;
10
+ // ② 编辑框定位一律走 anchorRect():优先**当前活着的选区** → 校验过的旧矩形 → 视口底部居中。
11
+ // 2) 装饰必须是"幂等 + 只加样式类/包一层隐藏元素",且判定要看**内容**(是否还有未接管的位置行),
12
+ // 不能只看 data-* 标记 —— 宿主会重排气泡内容,标记会骗人。
13
+ // 3) 所有装饰都要 try/catch 且不抛到 React 渲染路径上;观察者回调里同步执行(先于绘制)才不会闪。
4
14
  window.__ModuleLoader__.load({
5
15
  id: 'dsh-quote-annotate-pro',
6
16
  factory: (require) => {
@@ -683,7 +693,11 @@ window.__ModuleLoader__.load({
683
693
  anchorKey: sel.anchorKey,
684
694
  turn: sel.turn,
685
695
  kind: sel.kind,
686
- }, safeRect(sel.rect))
696
+ }, anchorRect(sel.rect))
697
+ try {
698
+ const r = anchorRect(sel.rect)
699
+ report('editor:anchor', { src: r.__dshq === 'fallback' ? 'fallback' : (liveSelectionRect() ? 'live' : 'stored'), rect: [Math.round(r.left), Math.round(r.top), Math.round(r.right - r.left), Math.round(r.bottom - r.top)] })
700
+ } catch (e) { /* ignore */ }
687
701
  finish()
688
702
  }
689
703
  return React.createElement('div', { className: 'dshq-toolbar', style: { left, top } },
@@ -705,28 +719,46 @@ window.__ModuleLoader__.load({
705
719
 
706
720
  // ============ 组件三:悬浮批注编辑框(评论输入框元素永久驻留,复用时输入法上下文不重建) ============
707
721
  /**
708
- * 选区矩形兜底。矩形失效(节点被装饰/重渲染替换后 getBoundingClientRect 会全 0)时,
709
- * 直接用它会算出 left=12 / top=8 —— 编辑框就跑到窗口左上角(用户反馈的现象)。
710
- * 处理:无效 → 用当前选区重算 → 仍无效 → 退回视口底部居中。
722
+ * 选区矩形兜底。矩形失效(节点被装饰/重渲染替换后 getBoundingClientRect 会返回"文档原点附近"的退化矩形)
723
+ * 时,直接用它会算出 left≈12 / top≈8 —— 编辑框就跑到窗口左上角(用户反馈的现象)。
724
+ * 取值优先级:**当前还活着的选区** → 存下来的矩形(且看着正常)→ 视口底部居中。
711
725
  */
712
- function safeRect(rect) {
713
- const ok = (r) => !!(r
714
- && Number.isFinite(r.left) && Number.isFinite(r.top)
715
- && Number.isFinite(r.right) && Number.isFinite(r.bottom)
716
- && ((r.right - r.left) > 0 || (r.bottom - r.top) > 0))
717
- if (ok(rect)) return rect
726
+ function liveSelectionRect() {
718
727
  try {
719
728
  const s = typeof window !== 'undefined' ? window.getSelection() : null
720
- if (s && s.rangeCount > 0) {
721
- const r = s.getRangeAt(0).getBoundingClientRect()
722
- if (ok(r)) return r
723
- }
724
- } catch (e) { /* ignore */ }
729
+ if (!s || s.rangeCount === 0 || s.isCollapsed) return null
730
+ const r = s.getRangeAt(0).getBoundingClientRect()
731
+ return plausibleRect(r) ? r : null
732
+ } catch (e) { return null }
733
+ }
734
+ /** 排除"贴文档原点"的退化矩形:那是选区失效后的典型产物 */
735
+ function plausibleRect(r) {
736
+ if (!r) return false
737
+ if (!(Number.isFinite(r.left) && Number.isFinite(r.top) && Number.isFinite(r.right) && Number.isFinite(r.bottom))) return false
738
+ const w = r.right - r.left
739
+ const h = r.bottom - r.top
740
+ if (!(w > 0 || h > 0)) return false
741
+ if (r.left < 24 && r.top < 24) return false // 原点附近 → 视为失效
742
+ const vw = typeof window !== 'undefined' ? window.innerWidth : 1024
743
+ const vh = typeof window !== 'undefined' ? window.innerHeight : 768
744
+ if (r.left > vw || r.top > vh) return false
745
+ return true
746
+ }
747
+ function bottomCenterRect() {
725
748
  const vw = typeof window !== 'undefined' ? window.innerWidth : 1024
726
749
  const vh = typeof window !== 'undefined' ? window.innerHeight : 768
727
750
  const left = Math.max(12, Math.round(vw / 2 - 140))
728
751
  const top = Math.max(12, Math.round(vh - 200))
729
- return { left, right: left + 280, top, bottom: top + 24, width: 280, height: 24 }
752
+ return { left, right: left + 280, top, bottom: top + 24, width: 280, height: 24, __dshq: 'fallback' }
753
+ }
754
+ function anchorRect(stored) {
755
+ const live = liveSelectionRect()
756
+ if (live) return live
757
+ if (plausibleRect(stored)) return stored
758
+ return bottomCenterRect()
759
+ }
760
+ function safeRect(rect) {
761
+ return anchorRect(rect)
730
762
  }
731
763
 
732
764
  const AnnotationEditor = () => {
@@ -746,7 +778,10 @@ window.__ModuleLoader__.load({
746
778
  const vw = typeof window !== 'undefined' ? window.innerWidth : 1024
747
779
  const vh = typeof window !== 'undefined' ? window.innerHeight : 768
748
780
  const item = state.item
749
- const rect = open ? safeRect(state.rect) : null
781
+ const rect = open ? anchorRect(state.rect) : null
782
+ if (rect && rect.__dshq === 'fallback') {
783
+ try { report('editor:anchor', { src: 'fallback' }) } catch (e) { /* ignore */ }
784
+ }
750
785
  let left = -9999
751
786
  let top = -9999
752
787
  let w = 200
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-quote-annotate-pro",
3
- "version": "0.2.8",
3
+ "version": "0.2.10",
4
4
  "description": "选区引用与锚点批注(增强 fork):划词 → 批注 → 带精确锚点的引用;输入框上方只显示原文片段,点一下跳回原文;发送时把轮次/角色写入引用块,让模型精确知道你指的是哪一处。",
5
5
  "keywords": ["dsh", "dsh-plugin", "deepseek-harness", "quote", "annotate", "selection", "reference", "anchor"],
6
6
  "license": "MIT",