dsh-quote-followup 0.1.0 → 0.1.1

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 (2) hide show
  1. package/lib/client.js +34 -3
  2. package/package.json +1 -1
package/lib/client.js CHANGED
@@ -91,10 +91,36 @@ window.__ModuleLoader__.load({
91
91
  }
92
92
  return null;
93
93
  };
94
+ /** Dispatch a real paste path so stateful editors (Lexical) own the update. */
95
+ const pasteIntoEditor = (element, text) => {
96
+ let clipboardData = null;
97
+ try {
98
+ clipboardData = new DataTransfer();
99
+ clipboardData.setData("text/plain", text);
100
+ } catch {}
101
+ let event;
102
+ try {
103
+ event = new ClipboardEvent("paste", {
104
+ bubbles: true,
105
+ cancelable: true,
106
+ clipboardData
107
+ });
108
+ } catch {
109
+ event = new Event("paste", { bubbles: true, cancelable: true });
110
+ }
111
+ if (clipboardData !== null && event.clipboardData == null) {
112
+ try {
113
+ Object.defineProperty(event, "clipboardData", { value: clipboardData });
114
+ } catch {}
115
+ }
116
+ element.dispatchEvent(event);
117
+ return event.defaultPrevented;
118
+ };
94
119
  /**
95
120
  * Append the quote at the END of the composer text (classic quote-reply
96
121
  * reading order) and leave the caret on the blank line for the question.
97
- * React-controlled inputs need the native setter + input event.
122
+ * Textareas use their native setter; stateful contenteditables receive a
123
+ * paste event so Lexical/other editors update their model, not only the DOM.
98
124
  */
99
125
  const appendToComposer = (element, insertText) => {
100
126
  element.focus();
@@ -117,6 +143,10 @@ window.__ModuleLoader__.load({
117
143
  range.collapse(false);
118
144
  selection?.removeAllRanges();
119
145
  selection?.addRange(range);
146
+ if (pasteIntoEditor(element, insertText))
147
+ return;
148
+ if (typeof document.execCommand === "function" && document.execCommand("insertText", false, insertText))
149
+ return;
120
150
  range.insertNode(document.createTextNode(insertText));
121
151
  range.collapse(false);
122
152
  element.dispatchEvent(new InputEvent("input", { bubbles: true, inputType: "insertText", data: insertText }));
@@ -208,9 +238,10 @@ window.__ModuleLoader__.load({
208
238
  console.warn("[dsh-quote-followup] composer input not found — quote dropped");
209
239
  return;
210
240
  }
241
+ // Clear the transcript range BEFORE focusing the composer. Clearing after
242
+ // insertion destroys Lexical's caret and makes the next quote unreliable.
243
+ document.getSelection()?.removeAllRanges();
211
244
  appendToComposer(composer, quoteFrame(quote.text, quote.role));
212
- const selection = document.getSelection();
213
- selection?.removeAllRanges();
214
245
  };
215
246
  //#endregion
216
247
  //#region apply
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-quote-followup",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Quote selected conversation content into a targeted follow-up turn for DeepSeek Harness — a TUI face (message picker + next-input rewrite via the official plugin seams) and a Web face (text-selection quoting into the composer).",
5
5
  "keywords": [
6
6
  "dsh",