dsh-plugins-jizuo-creator-writing 0.3.30 → 0.3.31

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/README.md CHANGED
@@ -12,7 +12,7 @@ dsh-plugins-jizuo-creator-writing
12
12
  dsh plugin --profile desktop add dsh-plugins-jizuo-creator-writing
13
13
  ```
14
14
 
15
- 这是已验证 v0.3.30 插件包的 npm 安装入口,内含原始插件及共享核心,无需额外安装依赖。
15
+ 这是已验证 v0.3.31 插件包的 npm 安装入口,内含原始插件及共享核心,无需额外安装依赖。
16
16
 
17
17
  已有 GitHub 安装版本时,请先卸载对应的旧安装项,再安装此 npm 包,完成后重启 DSH;卸载插件不会删除作品或对话。不要同时安装同一功能的 GitHub 包与 npm 包。
18
18
 
@@ -7,7 +7,7 @@
7
7
  支持 **DeepSeek Harness Desktop 0.2.0-rc.2**。在左侧「插件」→「添加插件」粘贴下面这一行,确认来源后安装:
8
8
 
9
9
  ```text
10
- https://github.com/ShikangPang/jizuo-creator-writing/releases/download/v0.3.30/jizuo-writing-plugin-0.3.30.tgz
10
+ https://github.com/ShikangPang/jizuo-creator-writing/releases/download/v0.3.31/jizuo-writing-plugin-0.3.31.tgz
11
11
  ```
12
12
 
13
13
  只填安装包地址,不要填整个安装命令。安装完成后「已安装」中显示「即作写作」,可分别启用、关闭、配置或卸载。共享核心已包含在安装包中,自动加载,不需要另装即作桌面端或手动安装核心插件。保留 Harness 原有新会话、插件与工作区入口;创作项目统一显示在工作区区域,小说和视频以前置图标区分,不再提供独立的创作面板。
@@ -17,7 +17,7 @@ https://github.com/ShikangPang/jizuo-creator-writing/releases/download/v0.3.30/j
17
17
  也可使用 Desktop 菜单安装的 dsh 命令:
18
18
 
19
19
  ```sh
20
- dsh plugin --profile desktop add https://github.com/ShikangPang/jizuo-creator-writing/releases/download/v0.3.30/jizuo-writing-plugin-0.3.30.tgz
20
+ dsh plugin --profile desktop add https://github.com/ShikangPang/jizuo-creator-writing/releases/download/v0.3.31/jizuo-writing-plugin-0.3.31.tgz
21
21
  ```
22
22
 
23
23
  源码克隆后运行 `node scripts/install.mjs --all` 一次安装五个插件,默认 desktop;Web 用户显式传 `--profile web`。脚本严格检查宿主版本。不要用旧版全局 dsh 命令安装到新版 Desktop,也不要绕过兼容检查。
@@ -26,7 +26,7 @@ dsh plugin --profile desktop add https://github.com/ShikangPang/jizuo-creator-wr
26
26
 
27
27
  启用即作写作插件后,点击工作区列表顶部的“导入小说”。支持 TXT、Markdown 和 DOCX,单文件最大 10 MB。选择文件后预览章节、修改作品名称,确认后创建新的小说项目,展开“正文”即可编辑。取消预览不会创建作品;首章前的内容保留为前言。TXT 支持 UTF-8 和 GB18030 编码。
28
28
 
29
- 已安装多个即作插件时,请将它们一并更新到 0.3.30,并重启 Harness,使共享核心版本一致。
29
+ 已安装多个即作插件时,请将它们一并更新到 0.3.31,并重启 Harness,使共享核心版本一致。
30
30
 
31
31
  ## 项目与数据
32
32
 
@@ -114,7 +114,7 @@ window.__ModuleLoader__.load({
114
114
  }).message;
115
115
  }
116
116
  //#endregion
117
- //#region ../../node_modules/zod/v4/core/core.js
117
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/zod/v4/core/core.js
118
118
  var _a$1;
119
119
  function $constructor(name, initializer, params) {
120
120
  function init(inst, def) {
@@ -173,7 +173,7 @@ window.__ModuleLoader__.load({
173
173
  return globalConfig;
174
174
  }
175
175
  //#endregion
176
- //#region ../../node_modules/zod/v4/core/util.js
176
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/zod/v4/core/util.js
177
177
  function getEnumValues(entries) {
178
178
  const numericValues = Object.values(entries).filter((v) => typeof v === "number");
179
179
  return Object.entries(entries).filter(([k, _]) => numericValues.indexOf(+k) === -1).map(([_, v]) => v);
@@ -487,7 +487,7 @@ window.__ModuleLoader__.load({
487
487
  return { ...iss };
488
488
  }
489
489
  //#endregion
490
- //#region ../../node_modules/zod/v4/core/errors.js
490
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/zod/v4/core/errors.js
491
491
  const initializer$1 = (inst, def) => {
492
492
  inst.name = "$ZodError";
493
493
  Object.defineProperty(inst, "_zod", {
@@ -547,7 +547,7 @@ window.__ModuleLoader__.load({
547
547
  return fieldErrors;
548
548
  }
549
549
  //#endregion
550
- //#region ../../node_modules/zod/v4/core/parse.js
550
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/zod/v4/core/parse.js
551
551
  const _parse = (_Err) => (schema, value, _ctx, _params) => {
552
552
  const ctx = _ctx ? {
553
553
  ..._ctx,
@@ -661,7 +661,7 @@ window.__ModuleLoader__.load({
661
661
  return _safeParseAsync(_Err)(schema, value, _ctx);
662
662
  };
663
663
  //#endregion
664
- //#region ../../node_modules/zod/v4/core/regexes.js
664
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/zod/v4/core/regexes.js
665
665
  /**
666
666
  * @deprecated CUID v1 is deprecated by its authors due to information leakage
667
667
  * (timestamps embedded in the id). Use {@link cuid2} instead.
@@ -726,7 +726,7 @@ window.__ModuleLoader__.load({
726
726
  const lowercase = /^[^A-Z]*$/;
727
727
  const uppercase = /^[^a-z]*$/;
728
728
  //#endregion
729
- //#region ../../node_modules/zod/v4/core/checks.js
729
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/zod/v4/core/checks.js
730
730
  const $ZodCheck = /*@__PURE__*/ $constructor("$ZodCheck", (inst, def) => {
731
731
  var _a;
732
732
  inst._zod ?? (inst._zod = {});
@@ -1088,7 +1088,7 @@ window.__ModuleLoader__.load({
1088
1088
  };
1089
1089
  });
1090
1090
  //#endregion
1091
- //#region ../../node_modules/zod/v4/core/doc.js
1091
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/zod/v4/core/doc.js
1092
1092
  var Doc = class {
1093
1093
  constructor(args = []) {
1094
1094
  this.content = [];
@@ -1119,14 +1119,14 @@ window.__ModuleLoader__.load({
1119
1119
  }
1120
1120
  };
1121
1121
  //#endregion
1122
- //#region ../../node_modules/zod/v4/core/versions.js
1122
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/zod/v4/core/versions.js
1123
1123
  const version = {
1124
1124
  major: 4,
1125
1125
  minor: 4,
1126
1126
  patch: 3
1127
1127
  };
1128
1128
  //#endregion
1129
- //#region ../../node_modules/zod/v4/core/schemas.js
1129
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/zod/v4/core/schemas.js
1130
1130
  const $ZodType = /*@__PURE__*/ $constructor("$ZodType", (inst, def) => {
1131
1131
  var _a;
1132
1132
  inst ?? (inst = {});
@@ -2443,7 +2443,7 @@ window.__ModuleLoader__.load({
2443
2443
  }
2444
2444
  }
2445
2445
  //#endregion
2446
- //#region ../../node_modules/zod/v4/core/registries.js
2446
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/zod/v4/core/registries.js
2447
2447
  var _a;
2448
2448
  var $ZodRegistry = class {
2449
2449
  constructor() {
@@ -2490,7 +2490,7 @@ window.__ModuleLoader__.load({
2490
2490
  (_a = globalThis).__zod_globalRegistry ?? (_a.__zod_globalRegistry = registry());
2491
2491
  const globalRegistry = globalThis.__zod_globalRegistry;
2492
2492
  //#endregion
2493
- //#region ../../node_modules/zod/v4/core/api.js
2493
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/zod/v4/core/api.js
2494
2494
  // @__NO_SIDE_EFFECTS__
2495
2495
  function _string(Class, params) {
2496
2496
  return new Class({
@@ -3002,7 +3002,7 @@ window.__ModuleLoader__.load({
3002
3002
  return ch;
3003
3003
  }
3004
3004
  //#endregion
3005
- //#region ../../node_modules/zod/v4/core/to-json-schema.js
3005
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/zod/v4/core/to-json-schema.js
3006
3006
  function initializeContext(params) {
3007
3007
  let target = params?.target ?? "draft-2020-12";
3008
3008
  if (target === "draft-4") target = "draft-04";
@@ -3297,7 +3297,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
3297
3297
  return finalize(ctx, schema);
3298
3298
  };
3299
3299
  //#endregion
3300
- //#region ../../node_modules/zod/v4/core/json-schema-processors.js
3300
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/zod/v4/core/json-schema-processors.js
3301
3301
  const formatMap = {
3302
3302
  guid: "uuid",
3303
3303
  url: "uri",
@@ -3575,7 +3575,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
3575
3575
  seen.ref = innerType;
3576
3576
  };
3577
3577
  //#endregion
3578
- //#region ../../node_modules/zod/v4/classic/iso.js
3578
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/zod/v4/classic/iso.js
3579
3579
  const ZodISODateTime = /*@__PURE__*/ $constructor("ZodISODateTime", (inst, def) => {
3580
3580
  $ZodISODateTime.init(inst, def);
3581
3581
  ZodStringFormat.init(inst, def);
@@ -3605,7 +3605,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
3605
3605
  return /* @__PURE__ */ _isoDuration(ZodISODuration, params);
3606
3606
  }
3607
3607
  //#endregion
3608
- //#region ../../node_modules/zod/v4/classic/errors.js
3608
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/zod/v4/classic/errors.js
3609
3609
  const initializer = (inst, issues) => {
3610
3610
  $ZodError.init(inst, issues);
3611
3611
  inst.name = "ZodError";
@@ -3627,7 +3627,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
3627
3627
  };
3628
3628
  const ZodRealError = /*@__PURE__*/ $constructor("ZodError", initializer, { Parent: Error });
3629
3629
  //#endregion
3630
- //#region ../../node_modules/zod/v4/classic/parse.js
3630
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/zod/v4/classic/parse.js
3631
3631
  const parse = /* @__PURE__ */ _parse(ZodRealError);
3632
3632
  const parseAsync = /* @__PURE__ */ _parseAsync(ZodRealError);
3633
3633
  const safeParse = /* @__PURE__ */ _safeParse(ZodRealError);
@@ -3641,7 +3641,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
3641
3641
  const safeEncodeAsync = /* @__PURE__ */ _safeEncodeAsync(ZodRealError);
3642
3642
  const safeDecodeAsync = /* @__PURE__ */ _safeDecodeAsync(ZodRealError);
3643
3643
  //#endregion
3644
- //#region ../../node_modules/zod/v4/classic/schemas.js
3644
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/zod/v4/classic/schemas.js
3645
3645
  const _installedGroups = /* @__PURE__ */ new WeakMap();
3646
3646
  function _installLazyMethods(inst, group, methods) {
3647
3647
  const proto = Object.getPrototypeOf(inst);
@@ -7016,7 +7016,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7016
7016
  };
7017
7017
  }
7018
7018
  //#endregion
7019
- //#region ../../node_modules/diff/libesm/diff/base.js
7019
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/diff/libesm/diff/base.js
7020
7020
  var Diff = class {
7021
7021
  diff(oldStr, newStr, options = {}) {
7022
7022
  let callback;
@@ -7194,11 +7194,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7194
7194
  }
7195
7195
  };
7196
7196
  //#endregion
7197
- //#region ../../node_modules/diff/libesm/diff/character.js
7197
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/diff/libesm/diff/character.js
7198
7198
  var CharacterDiff = class extends Diff {};
7199
7199
  new CharacterDiff();
7200
7200
  //#endregion
7201
- //#region ../../node_modules/diff/libesm/util/string.js
7201
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/diff/libesm/util/string.js
7202
7202
  function longestCommonPrefix(str1, str2) {
7203
7203
  let i = 0;
7204
7204
  for (; i < str1.length && i < str2.length; i++) if (str1[i] != str2[i]) return str1.slice(0, i);
@@ -7288,7 +7288,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7288
7288
  return [/\s/.test(firstSeg) ? firstSeg : "", /\s/.test(lastSeg) ? lastSeg : ""];
7289
7289
  }
7290
7290
  //#endregion
7291
- //#region ../../node_modules/diff/libesm/diff/word.js
7291
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/diff/libesm/diff/word.js
7292
7292
  const extendedWordChars = "a-zA-Z0-9_\\u{AD}\\u{C0}-\\u{D6}\\u{D8}-\\u{F6}\\u{F8}-\\u{2C6}\\u{2C8}-\\u{2D7}\\u{2DE}-\\u{2FF}\\u{1E00}-\\u{1EFF}";
7293
7293
  const tokenizeIncludingWhitespace = new RegExp(`[${extendedWordChars}]+|\\s+|[^${extendedWordChars}]`, "ug");
7294
7294
  var WordDiff = class extends Diff {
@@ -7396,7 +7396,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7396
7396
  };
7397
7397
  new WordsWithSpaceDiff();
7398
7398
  //#endregion
7399
- //#region ../../node_modules/diff/libesm/diff/line.js
7399
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/diff/libesm/diff/line.js
7400
7400
  var LineDiff = class extends Diff {
7401
7401
  constructor() {
7402
7402
  super(...arguments);
@@ -7429,7 +7429,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7429
7429
  return retLines;
7430
7430
  }
7431
7431
  //#endregion
7432
- //#region ../../node_modules/diff/libesm/diff/sentence.js
7432
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/diff/libesm/diff/sentence.js
7433
7433
  function isSentenceEndPunct(char) {
7434
7434
  return char == "." || char == "!" || char == "?";
7435
7435
  }
@@ -7456,7 +7456,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7456
7456
  };
7457
7457
  new SentenceDiff();
7458
7458
  //#endregion
7459
- //#region ../../node_modules/diff/libesm/diff/css.js
7459
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/diff/libesm/diff/css.js
7460
7460
  var CssDiff = class extends Diff {
7461
7461
  tokenize(value) {
7462
7462
  return value.split(/([{}:;,]|\s+)/);
@@ -7464,7 +7464,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7464
7464
  };
7465
7465
  new CssDiff();
7466
7466
  //#endregion
7467
- //#region ../../node_modules/diff/libesm/diff/json.js
7467
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/diff/libesm/diff/json.js
7468
7468
  var JsonDiff = class extends Diff {
7469
7469
  constructor() {
7470
7470
  super(...arguments);
@@ -7519,7 +7519,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7519
7519
  return canonicalizedObj;
7520
7520
  }
7521
7521
  //#endregion
7522
- //#region ../../node_modules/diff/libesm/diff/array.js
7522
+ //#region ../../../../../../stability-release-0.3.30/jizuo-creator-writing/.build/workspace/node_modules/diff/libesm/diff/array.js
7523
7523
  var ArrayDiff = class extends Diff {
7524
7524
  tokenize(value) {
7525
7525
  return value.slice();
@@ -8128,12 +8128,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8128
8128
  function hasCode(error, code) {
8129
8129
  return typeof error === "object" && error !== null && "code" in error && error.code === code;
8130
8130
  }
8131
+ function isSelectionGesture(event) {
8132
+ return event.key.startsWith("Arrow") || [
8133
+ "Home",
8134
+ "End",
8135
+ "PageUp",
8136
+ "PageDown"
8137
+ ].includes(event.key) || event.key.toLocaleLowerCase() === "a" && (event.metaKey || event.ctrlKey);
8138
+ }
8131
8139
  const BACKGROUND_REFRESH_INTERVAL_MS = 1500;
8132
8140
  const HISTORY_READ_TIMEOUT_MS = 15e3;
8133
8141
  function createEditSessionId() {
8134
8142
  return `edit_${typeof globalThis.crypto?.randomUUID === "function" ? globalThis.crypto.randomUUID().replaceAll("-", "") : `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`}`;
8135
8143
  }
8136
- function ChapterInspector({ remote, persistence, close, onQuoteExcerpt, subscribeWorksChanges }) {
8144
+ function ChapterInspector({ remote, persistence, close, onSelectionExcerpt, subscribeWorksChanges }) {
8137
8145
  const selection = useSelection();
8138
8146
  const editorRef = (0, react.useRef)(null);
8139
8147
  const draftPersistence = (0, react.useMemo)(() => persistence ?? createDraftPersistence(), [persistence]);
@@ -8154,7 +8162,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8154
8162
  const [outlineDraft, setOutlineDraft] = (0, react.useState)("");
8155
8163
  const [detailedOutlineDraft, setDetailedOutlineDraft] = (0, react.useState)("");
8156
8164
  const [activeTab, setActiveTab] = (0, react.useState)("content");
8157
- const [selectedExcerpt, setSelectedExcerpt] = (0, react.useState)("");
8165
+ const selectionExcerptCallback = (0, react.useRef)(onSelectionExcerpt);
8166
+ selectionExcerptCallback.current = onSelectionExcerpt;
8167
+ const searchHighlight = (0, react.useRef)(null);
8168
+ const clearAutomaticExcerpt = (0, react.useCallback)(() => {
8169
+ try {
8170
+ if (selectionExcerptCallback.current?.(null) === false) return false;
8171
+ return true;
8172
+ } catch {
8173
+ return false;
8174
+ }
8175
+ }, []);
8158
8176
  const [outlineSaveState, setOutlineSaveState] = (0, react.useState)("idle");
8159
8177
  const [loading, setLoading] = (0, react.useState)(false);
8160
8178
  const [loadError, setLoadError] = (0, react.useState)(null);
@@ -8173,6 +8191,41 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8173
8191
  const resizeDragRef = (0, react.useRef)(null);
8174
8192
  const visibleDraft = chapter?.liveDraft ?? draft;
8175
8193
  const targetKey = target === null ? null : `${target.workId}:${target.volumeId}:${target.chapterId}`;
8194
+ const fullChapterQuote = (0, react.useMemo)(() => {
8195
+ if (target === null || chapter === null || loading || loadError !== null || chapter.id !== target.chapterId || chapter.volumeId !== target.volumeId || chapter.workId !== target.workId || selection.overlay !== "chapter" || activeTab !== "content" || historyOpen || proposals[0] !== void 0 || visibleDraft.trim() === "") return null;
8196
+ return {
8197
+ target,
8198
+ chapterTitle: chapter.title,
8199
+ text: visibleDraft,
8200
+ kind: "chapter"
8201
+ };
8202
+ }, [
8203
+ target,
8204
+ chapter?.id,
8205
+ chapter?.volumeId,
8206
+ chapter?.workId,
8207
+ chapter?.title,
8208
+ visibleDraft,
8209
+ loading,
8210
+ loadError,
8211
+ selection.overlay,
8212
+ activeTab,
8213
+ historyOpen,
8214
+ proposals[0]?.id
8215
+ ]);
8216
+ (0, react.useEffect)(() => {
8217
+ searchHighlight.current = null;
8218
+ if (fullChapterQuote === null) {
8219
+ clearAutomaticExcerpt();
8220
+ return;
8221
+ }
8222
+ try {
8223
+ selectionExcerptCallback.current?.(fullChapterQuote);
8224
+ } catch {}
8225
+ }, [fullChapterQuote, clearAutomaticExcerpt]);
8226
+ (0, react.useEffect)(() => () => {
8227
+ clearAutomaticExcerpt();
8228
+ }, [clearAutomaticExcerpt]);
8176
8229
  const revisionReader = (0, react.useMemo)(() => {
8177
8230
  let active = false;
8178
8231
  let pending;
@@ -8259,12 +8312,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8259
8312
  if (!selection.searchMatch || !chapter || chapter.id !== selection.chapterId || loading) return;
8260
8313
  setActiveTab("content");
8261
8314
  setHistoryOpen(false);
8315
+ if (fullChapterQuote !== null) try {
8316
+ selectionExcerptCallback.current?.(fullChapterQuote);
8317
+ } catch {}
8262
8318
  const frame = requestAnimationFrame(() => {
8263
8319
  const editor = editorRef.current;
8264
8320
  const match = selection.searchMatch;
8265
8321
  if (!editor || !match) return;
8266
8322
  const start = chapter.revisionToken === match.revisionToken && visibleDraft === chapter.content ? match.start : visibleDraft.toLocaleLowerCase().indexOf(match.query.toLocaleLowerCase());
8267
8323
  if (start >= 0) {
8324
+ searchHighlight.current = {
8325
+ start,
8326
+ end: start + match.query.length,
8327
+ content: visibleDraft
8328
+ };
8268
8329
  editor.focus();
8269
8330
  editor.setSelectionRange(start, start + match.query.length);
8270
8331
  const lineHeight = parseFloat(getComputedStyle(editor).lineHeight) || 24;
@@ -8280,7 +8341,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8280
8341
  selection.chapterId,
8281
8342
  chapter,
8282
8343
  loading,
8283
- visibleDraft
8344
+ visibleDraft,
8345
+ fullChapterQuote
8284
8346
  ]);
8285
8347
  (0, react.useEffect)(() => {
8286
8348
  if (!target || !remote.touchDreamActivity) return;
@@ -8322,7 +8384,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8322
8384
  setDraft("");
8323
8385
  setOutlineDraft("");
8324
8386
  setDetailedOutlineDraft("");
8325
- setSelectedExcerpt("");
8326
8387
  setLoadError(null);
8327
8388
  setActionNotice(null);
8328
8389
  return;
@@ -8341,7 +8402,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8341
8402
  setDraft(matchingDraft?.content ?? next.content);
8342
8403
  setOutlineDraft(next.outline);
8343
8404
  setDetailedOutlineDraft(next.detailedOutline);
8344
- setSelectedExcerpt("");
8345
8405
  setOutlineSaveState("idle");
8346
8406
  }).catch((cause) => {
8347
8407
  if (active) setLoadError(messageOf$1(cause));
@@ -8519,7 +8579,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8519
8579
  };
8520
8580
  else editSessionRef.current.lastChangedAt = now;
8521
8581
  setDraft(content);
8522
- setSelectedExcerpt("");
8582
+ searchHighlight.current = null;
8523
8583
  setActionNotice(null);
8524
8584
  if (target !== null && chapter !== null) draftPersistence.save(target, {
8525
8585
  content,
@@ -8527,32 +8587,25 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8527
8587
  });
8528
8588
  };
8529
8589
  const captureExcerpt = (editor) => {
8590
+ if (onSelectionExcerpt === void 0 || fullChapterQuote === null || selection.searchMatch !== void 0 || document.activeElement !== editor) return;
8591
+ const highlighted = searchHighlight.current;
8592
+ if (highlighted !== null && highlighted.content === editor.value && highlighted.start === editor.selectionStart && highlighted.end === editor.selectionEnd) return;
8593
+ searchHighlight.current = null;
8530
8594
  const text = editor.value.slice(editor.selectionStart, editor.selectionEnd).trim();
8531
- setSelectedExcerpt(text.slice(0, 6e3));
8532
- };
8533
- const quoteSelectedExcerpt = () => {
8534
- if (target === null || chapter === null || onQuoteExcerpt === void 0) return;
8535
- const quoteText = selectedExcerpt === "" ? visibleDraft.trim() : selectedExcerpt;
8536
- if (quoteText === "") return;
8537
- setActionError(null);
8538
- setActionNotice(null);
8539
- let inserted = false;
8540
8595
  try {
8541
- inserted = onQuoteExcerpt({
8542
- target,
8543
- chapterTitle: chapter.title,
8544
- text: quoteText
8545
- });
8596
+ if (!onSelectionExcerpt(text === "" ? fullChapterQuote : {
8597
+ target: fullChapterQuote.target,
8598
+ chapterTitle: fullChapterQuote.chapterTitle,
8599
+ text
8600
+ })) {
8601
+ if (text !== "") setActionError("当前对话正在发送或暂不可用,请稍后重新选择。");
8602
+ return;
8603
+ }
8604
+ setActionError(null);
8605
+ setActionNotice(null);
8546
8606
  } catch (cause) {
8547
- setActionError(`引用失败:${messageOf$1(cause)}`);
8548
- return;
8549
- }
8550
- if (!inserted) {
8551
- setActionError("当前对话不可用,请先打开该作品的对话后重试。");
8552
- return;
8607
+ if (text !== "") setActionError(`引用失败:${messageOf$1(cause)}`);
8553
8608
  }
8554
- setActionNotice(selectedExcerpt === "" ? "已将整章引用到当前对话" : "已将选段引用到当前对话");
8555
- setSelectedExcerpt("");
8556
8609
  };
8557
8610
  const applyProposal = async (proposal) => {
8558
8611
  if (remote.authorizeProposal === void 0 || remote.applyProposal === void 0) return;
@@ -8739,44 +8792,33 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8739
8792
  ]
8740
8793
  }), activeTab === "content" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8741
8794
  className: "jz-inspector-save-actions",
8742
- children: [
8743
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconButton, {
8744
- icon: "history",
8745
- label: revisions.length > 0 ? `历史版本(${revisions.length})` : "历史版本",
8746
- type: "button",
8747
- "aria-controls": "jz-chapter-history",
8748
- "aria-expanded": historyOpen,
8749
- onClick: () => {
8750
- setHistoryOpen((open) => {
8751
- if (!open) refreshRevisions(true);
8752
- return !open;
8753
- });
8754
- }
8755
- }),
8756
- proposals[0] === void 0 && onQuoteExcerpt !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconButton, {
8757
- icon: "chat",
8758
- label: "引用到对话",
8759
- type: "button",
8760
- title: "有选中文本时引用选段,否则引用整章",
8761
- disabled: visibleDraft.trim() === "",
8762
- onClick: quoteSelectedExcerpt
8763
- }),
8764
- proposals[0] === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconButton, {
8765
- icon: "save",
8766
- label: "保存正文",
8767
- type: "button",
8768
- disabled: chapter.liveDraft !== void 0 || autosave.state === "saving" || autosave.state === "conflict",
8769
- onClick: () => {
8770
- setActionError(null);
8771
- if (draft === chapter.content) {
8772
- setActionNotice("正文已经保存");
8773
- return;
8774
- }
8775
- setActionNotice(null);
8776
- autosave.saveNow();
8795
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconButton, {
8796
+ icon: "history",
8797
+ label: revisions.length > 0 ? `历史版本(${revisions.length})` : "历史版本",
8798
+ type: "button",
8799
+ "aria-controls": "jz-chapter-history",
8800
+ "aria-expanded": historyOpen,
8801
+ onClick: () => {
8802
+ setHistoryOpen((open) => {
8803
+ if (!open) refreshRevisions(true);
8804
+ return !open;
8805
+ });
8806
+ }
8807
+ }), proposals[0] === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconButton, {
8808
+ icon: "save",
8809
+ label: "保存正文",
8810
+ type: "button",
8811
+ disabled: chapter.liveDraft !== void 0 || autosave.state === "saving" || autosave.state === "conflict",
8812
+ onClick: () => {
8813
+ setActionError(null);
8814
+ if (draft === chapter.content) {
8815
+ setActionNotice("正文已经保存");
8816
+ return;
8777
8817
  }
8778
- })
8779
- ]
8818
+ setActionNotice(null);
8819
+ autosave.saveNow();
8820
+ }
8821
+ })]
8780
8822
  }) : activeTab === "workflow" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconButton, {
8781
8823
  icon: "save",
8782
8824
  label: activeTab === "outline" ? "保存大纲" : "保存细纲",
@@ -8851,6 +8893,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8851
8893
  },
8852
8894
  onSelect: (event) => {
8853
8895
  captureExcerpt(event.currentTarget);
8896
+ },
8897
+ onPointerDown: () => {
8898
+ searchHighlight.current = null;
8899
+ },
8900
+ onPointerUp: (event) => {
8901
+ captureExcerpt(event.currentTarget);
8902
+ },
8903
+ onKeyDown: (event) => {
8904
+ if (isSelectionGesture(event)) searchHighlight.current = null;
8905
+ },
8906
+ onKeyUp: (event) => {
8907
+ if (isSelectionGesture(event)) captureExcerpt(event.currentTarget);
8854
8908
  }
8855
8909
  })]
8856
8910
  }),
@@ -9110,7 +9164,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9110
9164
  remote,
9111
9165
  subscribeWorksChanges: changes,
9112
9166
  close,
9113
- onQuoteExcerpt: host.conversation ? (quote) => host.conversation.appendChapterExcerpt(quote) : void 0
9167
+ onSelectionExcerpt: host.conversation?.syncChapterSelection ? (quote) => host.conversation.syncChapterSelection(quote) : void 0
9114
9168
  })
9115
9169
  }, ChapterInspector),
9116
9170
  volume: () => host.slots.register({