@hyebook/vue3-adapter 0.2.1 → 0.2.3

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.
@@ -9,12 +9,22 @@ export interface EditorWorkbenchFeatures {
9
9
  export interface EditorWorkbenchOptions {
10
10
  initialDoc?: EbookDoc;
11
11
  features?: Partial<EditorWorkbenchFeatures>;
12
+ previewAnnotations?: EditorWorkbenchPreviewAnnotationOptions;
12
13
  title?: string;
13
14
  pageWidth?: number;
14
15
  upload?: EditorWorkbenchUploadOptions;
15
16
  importDocx?: EditorWorkbenchDocxImportOptions;
16
17
  onDocumentChange?: (doc: EbookDoc) => void;
17
18
  }
19
+ export interface EditorWorkbenchPreviewAnnotationActions {
20
+ canDelete?: boolean;
21
+ }
22
+ export interface EditorWorkbenchPreviewAnnotationOptions {
23
+ showAnnotationList?: boolean;
24
+ enablePreviewSelectionToolbar?: boolean;
25
+ annotationListDefaultTab?: "highlights" | "notes";
26
+ annotationActions?: EditorWorkbenchPreviewAnnotationActions;
27
+ }
18
28
  export interface EditorWorkbenchDocxImportOptions {
19
29
  maxSizeBytes?: number;
20
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"editor-workbench.d.ts","sourceRoot":"","sources":["../../../../../core/src/workbench/editor-workbench.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,QAAQ,EAKR,kBAAkB,EAWnB,MAAM,gBAAgB,CAAC;AAkJxB,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,CAAC,EAAE,QAAQ,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,4BAA4B,CAAC;IACtC,UAAU,CAAC,EAAE,gCAAgC,CAAC;IAC9C,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,IAAI,CAAC;CAC5C;AAED,MAAM,WAAW,gCAAgC;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,OAAO,CAAC;AAEtD,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,qBAAqB,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,2BAA2B;IAC1C,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3D;AAED,MAAM,WAAW,wBAAyB,SAAQ,2BAA2B;CAAG;AAEhF,MAAM,WAAW,uBAAwB,SAAQ,2BAA2B;IAC1E,SAAS,EAAE,qBAAqB,CAAC;CAClC;AAED,MAAM,WAAW,4BAA4B;IAC3C,UAAU,CAAC,EAAE,CACX,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,uBAAuB,KAC7B,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,CACZ,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,wBAAwB,KAC9B,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,QAAQ,CAAC;IAC5B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,YAAY,EAAE,MAAM,MAAM,CAAC;IAC3B,UAAU,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAC9B,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;IACjD,sBAAsB,EAAE,CACtB,WAAW,EAAE,kBAAkB,GAAG,IAAI,GAAG,SAAS,KAC/C,kBAAkB,CAAC;IACxB,WAAW,EAAE,MAAM,uBAAuB,CAAC;IAC3C,WAAW,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,uBAAuB,CAAC,KAAK,IAAI,CAAC;CACnE;AAED,eAAO,MAAM,iCAAiC,EAAE,uBAM/C,CAAC;AAEF,KAAK,IAAI,GAAG,QAAQ,GAAG,SAAS,CAAC;AAsQjC,wBAAgB,8BAA8B,IAAI,QAAQ,CA6GzD;AAED,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,WAAW,EACtB,OAAO,GAAE,sBAA2B,GACnC,qBAAqB,CAszIvB"}
1
+ {"version":3,"file":"editor-workbench.d.ts","sourceRoot":"","sources":["../../../../../core/src/workbench/editor-workbench.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { addPageCommand } from "../editor/commands";
2
2
  import { EditorEngine } from "../editor/engine";
3
3
  const WORKBENCH_STYLE_ID = "hy-ebook-workbench-style";
4
+ const WORKBENCH_STYLE_VERSION = "0.2.3";
4
5
  const WORKBENCH_CSS = `
5
6
  .hyewb-root{font-family:"Noto Sans SC","PingFang SC","Microsoft YaHei",sans-serif;color:#0f172a;background:#f8fbff;border:1px solid #d8e0ea;border-radius:12px;padding:12px;display:grid;gap:10px}
6
7
  .hyewb-header{display:flex;justify-content:space-between;align-items:center;gap:8px;flex-wrap:wrap}
@@ -23,7 +24,9 @@ const WORKBENCH_CSS = `
23
24
  .hyewb-field-icon svg{width:14px;height:14px;stroke-width:2}
24
25
  .hyewb-field-with-icon .hyewb-select,.hyewb-field-with-icon .hyewb-number{padding-left:30px}
25
26
  .hyewb-shell{border:1px dashed #b8c3d1;border-radius:10px;background:#eef4ff;padding:10px;overflow-x:auto;overflow-y:auto;overscroll-behavior:auto;-webkit-overflow-scrolling:touch}
26
- .hyewb-canvas{position:relative;background:#fff;border:1px solid #d9e3ee;border-radius:8px;min-height:420px;padding:20px 24px;box-shadow:0 6px 16px rgba(15,23,42,.08);margin:0 auto}
27
+ .hyewb-preview-layout{display:grid;grid-template-columns:minmax(0,1fr);gap:12px;align-items:start}
28
+ .hyewb-preview-layout.with-annotation-panel{grid-template-columns:minmax(0,1fr) 300px}
29
+ .hyewb-canvas{position:relative;background:#fff;border:1px solid #d9e3ee;border-radius:8px;min-height:420px;padding:20px 24px;box-shadow:0 6px 16px rgba(15,23,42,.08);margin:0 auto;max-width:100%;box-sizing:border-box}
27
30
  .hyewb-editor{min-height:360px;outline:none;line-height:1.7;font-size:16px;color:#1e293b}
28
31
  .hyewb-float{position:fixed;z-index:9999;display:none;align-items:center;gap:6px;padding:6px 8px;border-radius:10px;border:1px solid #0f172a;background:rgba(15,23,42,.96);box-shadow:0 10px 24px rgba(15,23,42,.22)}
29
32
  .hyewb-float.show{display:inline-flex}
@@ -139,6 +142,29 @@ const WORKBENCH_CSS = `
139
142
  .hyewb-upload-progress{height:8px;background:#e2e8f0;border-radius:999px;overflow:hidden}
140
143
  .hyewb-upload-progress > span{display:block;height:100%;width:0;background:#0b7285;transition:width .18s ease}
141
144
  .hyewb-upload-error{min-height:18px;font-size:12px;color:#b91c1c;margin:0}
145
+ .hyewb-preview-highlight-mark{background:var(--hyewb-highlight-color,#fff59d);color:inherit;padding:0 .08em;border-radius:.2em}
146
+ .hyewb-preview-note-mark{background:rgba(14,116,144,.14);border-bottom:2px solid #0e7490;color:inherit;padding:0 .04em;border-radius:.2em}
147
+ .hyewb-preview-annotation-panel{display:none;align-content:start;gap:10px;border:1px solid #d8e0ea;border-radius:10px;background:#ffffff;padding:12px;max-height:100%;overflow:auto}
148
+ .hyewb-preview-annotation-title{margin:0;font-size:14px}
149
+ .hyewb-preview-annotation-tabs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
150
+ .hyewb-preview-annotation-tab{width:auto;min-width:0;height:32px;padding:0 12px;font-size:13px;border:1px solid #cbd5e1;border-radius:8px;background:#fff;color:#0f172a;cursor:pointer}
151
+ .hyewb-preview-annotation-tab.active{color:#ffffff;background:#0b7285;border-color:#0b7285}
152
+ .hyewb-preview-annotation-list{margin:0;padding:0;list-style:none;display:grid;gap:8px}
153
+ .hyewb-preview-annotation-item{width:100%;text-align:left;display:grid;gap:4px;padding:8px 36px 8px 8px;border-radius:8px;border:1px solid #dce5ef;background:#f8fafc;position:relative;cursor:pointer}
154
+ .hyewb-preview-annotation-item:hover{background:#eef6ff;border-color:#b9d7f4}
155
+ .hyewb-preview-annotation-item-title{font-size:12px;color:#0f766e}
156
+ .hyewb-preview-annotation-item-body{font-size:13px;color:#1e293b;line-height:1.5}
157
+ .hyewb-preview-annotation-delete{position:absolute;right:8px;top:8px;border-radius:8px;border:1px solid #f1b3b3;background:#fff5f5;color:#b42318;width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;opacity:0;pointer-events:none;transition:opacity .15s ease;cursor:pointer;padding:0}
158
+ .hyewb-preview-annotation-item:hover .hyewb-preview-annotation-delete{opacity:1;pointer-events:auto}
159
+ .hyewb-preview-annotation-delete svg{width:14px;height:14px}
160
+ .hyewb-preview-annotation-empty{margin:0;color:#64748b;font-size:13px}
161
+ .hyewb-preview-selection-toolbar{position:fixed;z-index:10060;display:none;align-items:center;gap:8px;padding:6px 8px;border-radius:10px;border:1px solid #0f172a;background:rgba(15,23,42,.96);box-shadow:0 10px 24px rgba(15,23,42,.22);transform:translate(-50%,-100%)}
162
+ .hyewb-preview-selection-toolbar.show{display:inline-flex}
163
+ .hyewb-preview-selection-btn{width:32px;height:32px;padding:0;display:inline-flex;align-items:center;justify-content:center;border:1px solid #334155;background:#1e293b;color:#f8fafc;border-radius:8px;cursor:pointer}
164
+ .hyewb-preview-selection-btn:hover{background:#334155}
165
+ .hyewb-preview-selection-btn svg{width:16px;height:16px}
166
+ .hyewb-preview-annotation-flash{animation:hyewb-preview-annotation-pulse .9s ease}
167
+ @keyframes hyewb-preview-annotation-pulse{0%{box-shadow:0 0 0 0 rgba(14,116,144,.4)}100%{box-shadow:0 0 0 12px rgba(14,116,144,0)}}
142
168
  .hyewb-root:fullscreen .hyewb-editor,.hyewb-root:fullscreen .hyewb-preview{min-height:1000px}
143
169
  .hyewb-root:-webkit-full-screen .hyewb-editor,.hyewb-root:-webkit-full-screen .hyewb-preview{min-height:1000px}
144
170
  `;
@@ -161,11 +187,13 @@ const WORKBENCH_ICON_PATHS = {
161
187
  "chevron-right": '<polyline points="9 18 15 12 9 6"/>',
162
188
  "fullscreen-enter": '<polyline points="9 3 3 3 3 9"/><line x1="3" y1="3" x2="10" y2="10"/><polyline points="15 3 21 3 21 9"/><line x1="14" y1="10" x2="21" y2="3"/><polyline points="3 15 3 21 9 21"/><line x1="3" y1="21" x2="10" y2="14"/><polyline points="15 21 21 21 21 15"/><line x1="14" y1="14" x2="21" y2="21"/>',
163
189
  "fullscreen-exit": '<polyline points="10 14 10 21 3 21"/><line x1="10" y1="14" x2="3" y2="21"/><polyline points="14 10 21 10 21 3"/><line x1="14" y1="10" x2="21" y2="3"/><polyline points="3 9 3 3 9 3"/><line x1="3" y1="3" x2="10" y2="10"/><polyline points="21 15 21 21 15 21"/><line x1="21" y1="21" x2="14" y2="14"/>',
190
+ highlighter: '<path d="M15 2l7 7-8.5 8.5-7-7z"/><path d="M12.5 11.5L2 22l6-1.5 6-6"/><line x1="13" y1="4" x2="20" y2="11"/>',
164
191
  "file-up": '<path d="M14 2H8a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/><line x1="12" y1="18" x2="12" y2="12"/><polyline points="9.5 14.5 12 12 14.5 14.5"/>',
165
192
  image: '<rect x="3" y="5" width="18" height="14" rx="2"/><circle cx="9" cy="10" r="1.5"/><path d="M6 17l4-4 3 3 3-2 2 3"/>',
166
193
  italic: '<line x1="10" y1="4" x2="16" y2="4"/><line x1="8" y1="20" x2="14" y2="20"/><line x1="14" y1="4" x2="10" y2="20"/>',
167
194
  "indent-increase": '<line x1="4" y1="6" x2="14" y2="6"/><line x1="4" y1="10" x2="10" y2="10"/><line x1="4" y1="14" x2="14" y2="14"/><line x1="4" y1="18" x2="10" y2="18"/><polyline points="15 9 19 12 15 15"/>',
168
195
  move: '<polyline points="8 4 12 1 16 4"/><line x1="12" y1="1" x2="12" y2="23"/><polyline points="8 20 12 23 16 20"/><polyline points="4 8 1 12 4 16"/><line x1="1" y1="12" x2="23" y2="12"/><polyline points="20 8 23 12 20 16"/>',
196
+ "notebook-pen": '<path d="M4 5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2z"/><line x1="8" y1="7" x2="14" y2="7"/><line x1="8" y1="11" x2="14" y2="11"/><path d="M14.5 16.5l4-4 2 2-4 4-2.5.5z"/>',
169
197
  "paint-bucket": '<path d="M7 10l6-6 7 7-6 6z"/><path d="M12 5l7 7"/><path d="M5 19a2 2 0 1 0 4 0c0-1-1-2-2-3-1 1-2 2-2 3z"/>',
170
198
  palette: '<path d="M12 3a9 9 0 1 0 0 18h1.5a2.5 2.5 0 0 0 0-5h-1a2 2 0 0 1 0-4H16a5 5 0 0 0-4-9z"/><circle cx="7.5" cy="10" r="1"/><circle cx="10" cy="7.5" r="1"/><circle cx="14" cy="7.5" r="1"/>',
171
199
  pilcrow: '<path d="M9 4h7v16"/><path d="M12 4v16"/><path d="M9 4a4 4 0 0 0 0 8h3"/>',
@@ -175,6 +203,7 @@ const WORKBENCH_ICON_PATHS = {
175
203
  subscript: '<line x1="4" y1="8" x2="10" y2="16"/><line x1="10" y1="8" x2="4" y2="16"/><path d="M14 15c0-1.1.9-2 2-2s2 .9 2 2c0 .7-.3 1.2-.9 1.7L14 20h4"/>',
176
204
  superscript: '<line x1="4" y1="8" x2="10" y2="16"/><line x1="10" y1="8" x2="4" y2="16"/><path d="M14 6c0-1.1.9-2 2-2s2 .9 2 2c0 .7-.3 1.2-.9 1.7L14 11h4"/>',
177
205
  table: '<rect x="3" y="5" width="18" height="14" rx="1"/><line x1="3" y1="10" x2="21" y2="10"/><line x1="9" y1="5" x2="9" y2="19"/><line x1="15" y1="5" x2="15" y2="19"/>',
206
+ "trash-2": '<polyline points="3 6 5 6 21 6"/><path d="M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/>',
178
207
  underline: '<path d="M6 4v6a6 6 0 0 0 12 0V4"/><line x1="4" y1="20" x2="20" y2="20"/>',
179
208
  video: '<rect x="3" y="6" width="14" height="12" rx="2"/><polygon points="10 10 10 14 13 12"/><path d="M17 10l4-2v8l-4-2z"/>',
180
209
  x: '<line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/>',
@@ -274,6 +303,16 @@ const RESIZE_HANDLES = [
274
303
  "w",
275
304
  ];
276
305
  const DEFAULT_FLOW_BLOCK_WIDTH = 620;
306
+ function resolvePreviewAnnotationOptions(options) {
307
+ return {
308
+ showAnnotationList: options?.showAnnotationList ?? true,
309
+ enablePreviewSelectionToolbar: options?.enablePreviewSelectionToolbar ?? true,
310
+ annotationListDefaultTab: options?.annotationListDefaultTab === "notes" ? "notes" : "highlights",
311
+ annotationActions: {
312
+ canDelete: options?.annotationActions?.canDelete ?? true,
313
+ },
314
+ };
315
+ }
277
316
  export function createDefaultWorkbenchDocument() {
278
317
  const now = new Date().toISOString();
279
318
  return {
@@ -394,6 +433,7 @@ export function mountEditorWorkbench(container, options = {}) {
394
433
  doc: editor.getDocument(),
395
434
  features: resolveFeatures(options.features),
396
435
  };
436
+ const previewAnnotationOptions = resolvePreviewAnnotationOptions(options.previewAnnotations);
397
437
  const paperWidth = resolvePaperWidth(options.pageWidth, state.doc.settings.page.width);
398
438
  const root = document.createElement("section");
399
439
  root.className = "hyewb-root";
@@ -674,6 +714,8 @@ export function mountEditorWorkbench(container, options = {}) {
674
714
  pageInfo.className = "hyewb-status";
675
715
  fullscreenBtn.style.marginLeft = "auto";
676
716
  pageRow.append(prevPageBtn, nextPageBtn, addPageBtn, pageInfo, fullscreenBtn);
717
+ const previewLayout = document.createElement("div");
718
+ previewLayout.className = "hyewb-preview-layout";
677
719
  const shell = document.createElement("div");
678
720
  shell.className = "hyewb-shell";
679
721
  const canvas = document.createElement("div");
@@ -698,6 +740,43 @@ export function mountEditorWorkbench(container, options = {}) {
698
740
  mediaList.className = "hyewb-media-list";
699
741
  canvas.append(editorArea, previewArea, mediaStage, inlineResizeOverlay, mediaList);
700
742
  shell.append(canvas);
743
+ const annotationPanel = document.createElement("aside");
744
+ annotationPanel.className = "hyewb-preview-annotation-panel";
745
+ const annotationTitle = document.createElement("h3");
746
+ annotationTitle.className = "hyewb-preview-annotation-title";
747
+ annotationTitle.textContent = "预览标注";
748
+ const annotationTabs = document.createElement("div");
749
+ annotationTabs.className = "hyewb-preview-annotation-tabs";
750
+ const annotationHighlightTab = document.createElement("button");
751
+ annotationHighlightTab.type = "button";
752
+ annotationHighlightTab.className = "hyewb-preview-annotation-tab";
753
+ annotationHighlightTab.textContent = "高亮";
754
+ const annotationNoteTab = document.createElement("button");
755
+ annotationNoteTab.type = "button";
756
+ annotationNoteTab.className = "hyewb-preview-annotation-tab";
757
+ annotationNoteTab.textContent = "笔记";
758
+ annotationTabs.append(annotationHighlightTab, annotationNoteTab);
759
+ const annotationList = document.createElement("ul");
760
+ annotationList.className = "hyewb-preview-annotation-list";
761
+ const annotationEmpty = document.createElement("p");
762
+ annotationEmpty.className = "hyewb-preview-annotation-empty";
763
+ annotationPanel.append(annotationTitle, annotationTabs, annotationList, annotationEmpty);
764
+ previewLayout.append(shell, annotationPanel);
765
+ const previewSelectionToolbar = document.createElement("div");
766
+ previewSelectionToolbar.className = "hyewb-preview-selection-toolbar";
767
+ const previewHighlightBtn = document.createElement("button");
768
+ previewHighlightBtn.type = "button";
769
+ previewHighlightBtn.className = "hyewb-preview-selection-btn";
770
+ previewHighlightBtn.title = "创建高亮";
771
+ previewHighlightBtn.setAttribute("aria-label", "创建高亮");
772
+ previewHighlightBtn.append(createIconPlaceholder("highlighter"));
773
+ const previewNoteBtn = document.createElement("button");
774
+ previewNoteBtn.type = "button";
775
+ previewNoteBtn.className = "hyewb-preview-selection-btn";
776
+ previewNoteBtn.title = "创建笔记";
777
+ previewNoteBtn.setAttribute("aria-label", "创建笔记");
778
+ previewNoteBtn.append(createIconPlaceholder("notebook-pen"));
779
+ previewSelectionToolbar.append(previewHighlightBtn, previewNoteBtn);
701
780
  const floatingToolbar = document.createElement("div");
702
781
  floatingToolbar.className = "hyewb-float";
703
782
  const floatBoldBtn = createButton("bold");
@@ -772,7 +851,7 @@ export function mountEditorWorkbench(container, options = {}) {
772
851
  const colorGrid = document.createElement("div");
773
852
  colorGrid.className = "hyewb-color-grid";
774
853
  colorPalette.append(colorGrid);
775
- root.append(header, toolbar, pageRow, shell, status, colorPalette, tablePicker, tableTools, tableRowDeleteBtn, tableMoveHandle, tableScaleHandle, tableColEdgeLayer, tableRowEdgeLayer, tableRowGapInsertBtn, tableColGapInsertBtn, tableDropIndicator, tableContextMenu, uploadBackdrop, docxInput);
854
+ root.append(header, toolbar, pageRow, previewLayout, status, colorPalette, tablePicker, tableTools, tableRowDeleteBtn, tableMoveHandle, tableScaleHandle, tableColEdgeLayer, tableRowEdgeLayer, tableRowGapInsertBtn, tableColGapInsertBtn, tableDropIndicator, tableContextMenu, uploadBackdrop, docxInput, previewSelectionToolbar);
776
855
  container.innerHTML = "";
777
856
  container.append(root, floatingToolbar);
778
857
  renderWorkbenchIcons();
@@ -798,6 +877,8 @@ export function mountEditorWorkbench(container, options = {}) {
798
877
  let tableContextTarget = null;
799
878
  let selectedTableRowIndex = null;
800
879
  let selectedTableColIndex = null;
880
+ let annotationActiveTab = previewAnnotationOptions.annotationListDefaultTab;
881
+ let previewSelectionDraft = null;
801
882
  const isTableGapInsertTarget = (node) => {
802
883
  if (!node) {
803
884
  return false;
@@ -1132,6 +1213,7 @@ export function mountEditorWorkbench(container, options = {}) {
1132
1213
  syncEditorToDoc();
1133
1214
  state.mode = nextMode;
1134
1215
  hideFloatingToolbar();
1216
+ hidePreviewSelectionToolbar();
1135
1217
  render();
1136
1218
  };
1137
1219
  const loadPreviewAnnotations = () => {
@@ -1144,6 +1226,423 @@ export function mountEditorWorkbench(container, options = {}) {
1144
1226
  updateStateDoc(nextDoc);
1145
1227
  return clone(normalized);
1146
1228
  };
1229
+ const getCurrentPageId = () => {
1230
+ return state.doc.pages[state.pageIndex]?.id || `page-${state.pageIndex}`;
1231
+ };
1232
+ const normalizeOffsetRange = (start, end) => {
1233
+ const safeStart = Math.max(0, Math.floor(start || 0));
1234
+ const safeEnd = Math.max(0, Math.floor(end || 0));
1235
+ if (safeStart === safeEnd) {
1236
+ return null;
1237
+ }
1238
+ return safeStart < safeEnd
1239
+ ? { start: safeStart, end: safeEnd }
1240
+ : { start: safeEnd, end: safeStart };
1241
+ };
1242
+ const getNodeTextLength = (rootNode) => {
1243
+ if (!rootNode) {
1244
+ return 0;
1245
+ }
1246
+ const walker = document.createTreeWalker(rootNode, NodeFilter.SHOW_TEXT);
1247
+ let size = 0;
1248
+ while (walker.nextNode()) {
1249
+ size += walker.currentNode.textContent?.length || 0;
1250
+ }
1251
+ return size;
1252
+ };
1253
+ const getRangeTextLength = (range) => {
1254
+ if (!range) {
1255
+ return 0;
1256
+ }
1257
+ return getNodeTextLength(range.cloneContents());
1258
+ };
1259
+ const getSelectionOffsets = (containerNode, selection) => {
1260
+ if (!selection.rangeCount) {
1261
+ return null;
1262
+ }
1263
+ const range = selection.getRangeAt(0);
1264
+ if (!containerNode.contains(range.startContainer) ||
1265
+ !containerNode.contains(range.endContainer)) {
1266
+ return null;
1267
+ }
1268
+ const beforeStart = range.cloneRange();
1269
+ beforeStart.selectNodeContents(containerNode);
1270
+ beforeStart.setEnd(range.startContainer, range.startOffset);
1271
+ const beforeEnd = range.cloneRange();
1272
+ beforeEnd.selectNodeContents(containerNode);
1273
+ beforeEnd.setEnd(range.endContainer, range.endOffset);
1274
+ return normalizeOffsetRange(getRangeTextLength(beforeStart), getRangeTextLength(beforeEnd));
1275
+ };
1276
+ const createRangeFromOffsets = (containerNode, start, end) => {
1277
+ const normalized = normalizeOffsetRange(start, end);
1278
+ if (!normalized) {
1279
+ return null;
1280
+ }
1281
+ const range = document.createRange();
1282
+ const walker = document.createTreeWalker(containerNode, NodeFilter.SHOW_TEXT);
1283
+ let cursor = 0;
1284
+ let startNode = null;
1285
+ let endNode = null;
1286
+ let startOffset = 0;
1287
+ let endOffset = 0;
1288
+ let lastTextNode = null;
1289
+ while (walker.nextNode()) {
1290
+ const node = walker.currentNode;
1291
+ const length = node.textContent?.length || 0;
1292
+ lastTextNode = node;
1293
+ const nextCursor = cursor + length;
1294
+ if (!startNode &&
1295
+ normalized.start >= cursor &&
1296
+ normalized.start < nextCursor) {
1297
+ startNode = node;
1298
+ startOffset = normalized.start - cursor;
1299
+ }
1300
+ if (!endNode && normalized.end > cursor && normalized.end <= nextCursor) {
1301
+ endNode = node;
1302
+ endOffset = normalized.end - cursor;
1303
+ break;
1304
+ }
1305
+ cursor = nextCursor;
1306
+ }
1307
+ if (!startNode && lastTextNode && normalized.start === cursor) {
1308
+ startNode = lastTextNode;
1309
+ startOffset = lastTextNode.textContent?.length || 0;
1310
+ }
1311
+ if (!endNode && lastTextNode && normalized.end === cursor) {
1312
+ endNode = lastTextNode;
1313
+ endOffset = lastTextNode.textContent?.length || 0;
1314
+ }
1315
+ if (!startNode || !endNode) {
1316
+ return null;
1317
+ }
1318
+ range.setStart(startNode, startOffset);
1319
+ range.setEnd(endNode, endOffset);
1320
+ return range;
1321
+ };
1322
+ const unwrapPreviewMarks = (containerNode, kinds) => {
1323
+ const selector = kinds
1324
+ .map((kind) => `mark[data-preview-annotation='${kind}']`)
1325
+ .join(",");
1326
+ if (!selector) {
1327
+ return;
1328
+ }
1329
+ const marks = Array.from(containerNode.querySelectorAll(selector));
1330
+ marks.forEach((mark) => {
1331
+ const parent = mark.parentNode;
1332
+ if (!parent) {
1333
+ return;
1334
+ }
1335
+ while (mark.firstChild) {
1336
+ parent.insertBefore(mark.firstChild, mark);
1337
+ }
1338
+ parent.removeChild(mark);
1339
+ });
1340
+ };
1341
+ const applyHighlightMarks = (containerNode, highlights) => {
1342
+ unwrapPreviewMarks(containerNode, ["highlight"]);
1343
+ [...highlights]
1344
+ .filter((item) => Number.isFinite(item.start) && Number.isFinite(item.end))
1345
+ .sort((a, b) => b.start - a.start)
1346
+ .forEach((item) => {
1347
+ const range = createRangeFromOffsets(containerNode, item.start, item.end);
1348
+ if (!range || range.collapsed) {
1349
+ return;
1350
+ }
1351
+ const mark = document.createElement("mark");
1352
+ mark.dataset.previewAnnotation = "highlight";
1353
+ mark.className = "hyewb-preview-highlight-mark";
1354
+ mark.style.setProperty("--hyewb-highlight-color", item.color || "#fff59d");
1355
+ try {
1356
+ range.surroundContents(mark);
1357
+ }
1358
+ catch {
1359
+ const fragment = range.extractContents();
1360
+ mark.append(fragment);
1361
+ range.insertNode(mark);
1362
+ }
1363
+ });
1364
+ };
1365
+ const applyNoteMarks = (containerNode, notes) => {
1366
+ unwrapPreviewMarks(containerNode, ["note"]);
1367
+ [...notes]
1368
+ .filter((item) => Number.isFinite(item.start) && Number.isFinite(item.end))
1369
+ .sort((a, b) => b.start - a.start)
1370
+ .forEach((item) => {
1371
+ const range = createRangeFromOffsets(containerNode, item.start, item.end);
1372
+ if (!range || range.collapsed) {
1373
+ return;
1374
+ }
1375
+ const mark = document.createElement("mark");
1376
+ mark.dataset.previewAnnotation = "note";
1377
+ mark.dataset.previewNoteId = item.id || "";
1378
+ mark.className = "hyewb-preview-note-mark";
1379
+ try {
1380
+ range.surroundContents(mark);
1381
+ }
1382
+ catch {
1383
+ const fragment = range.extractContents();
1384
+ mark.append(fragment);
1385
+ range.insertNode(mark);
1386
+ }
1387
+ });
1388
+ };
1389
+ const mergeHighlightRecords = (records, draft) => {
1390
+ const normalized = normalizeOffsetRange(draft.start, draft.end);
1391
+ if (!normalized || !draft.pageId || !draft.blockId) {
1392
+ return records;
1393
+ }
1394
+ const targetColor = draft.color || "#fff59d";
1395
+ const sameBucket = [];
1396
+ const rest = [];
1397
+ records.forEach((item) => {
1398
+ if (item.pageId === draft.pageId &&
1399
+ item.blockId === draft.blockId &&
1400
+ (item.color || "#fff59d") === targetColor) {
1401
+ sameBucket.push(item);
1402
+ }
1403
+ else {
1404
+ rest.push(item);
1405
+ }
1406
+ });
1407
+ let mergedStart = normalized.start;
1408
+ let mergedEnd = normalized.end;
1409
+ const kept = [];
1410
+ sameBucket.forEach((item) => {
1411
+ const overlap = !(item.end < mergedStart || item.start > mergedEnd);
1412
+ if (overlap) {
1413
+ mergedStart = Math.min(mergedStart, item.start);
1414
+ mergedEnd = Math.max(mergedEnd, item.end);
1415
+ }
1416
+ else {
1417
+ kept.push(item);
1418
+ }
1419
+ });
1420
+ return [
1421
+ ...rest,
1422
+ ...kept,
1423
+ {
1424
+ ...draft,
1425
+ start: mergedStart,
1426
+ end: mergedEnd,
1427
+ },
1428
+ ];
1429
+ };
1430
+ const mergeNoteRecords = (records, draft) => {
1431
+ const index = records.findIndex((item) => {
1432
+ return (item.pageId === draft.pageId &&
1433
+ item.start === draft.start &&
1434
+ item.end === draft.end);
1435
+ });
1436
+ if (index === -1) {
1437
+ return [...records, draft];
1438
+ }
1439
+ const next = [...records];
1440
+ const existing = next[index];
1441
+ if (!existing) {
1442
+ return [...records, draft];
1443
+ }
1444
+ next[index] = {
1445
+ ...existing,
1446
+ ...draft,
1447
+ id: existing.id || draft.id,
1448
+ updatedAt: new Date().toISOString(),
1449
+ };
1450
+ return next;
1451
+ };
1452
+ const summarizePreviewText = (text, fallback, maxLength = 52) => {
1453
+ const raw = String(text || "")
1454
+ .replace(/\s+/g, " ")
1455
+ .trim();
1456
+ if (!raw) {
1457
+ return fallback;
1458
+ }
1459
+ return raw.length > maxLength ? `${raw.slice(0, maxLength)}...` : raw;
1460
+ };
1461
+ const flashPreviewAnnotationTarget = (node) => {
1462
+ if (!node || !node.classList) {
1463
+ return;
1464
+ }
1465
+ node.classList.remove("hyewb-preview-annotation-flash");
1466
+ void node.offsetWidth;
1467
+ node.classList.add("hyewb-preview-annotation-flash");
1468
+ window.setTimeout(() => {
1469
+ node.classList.remove("hyewb-preview-annotation-flash");
1470
+ }, 900);
1471
+ };
1472
+ const focusPreviewAnnotationRecord = (record, kind) => {
1473
+ let target = null;
1474
+ if (kind === "note" && "id" in record && record.id) {
1475
+ const noteId = String(record.id);
1476
+ target = previewArea.querySelector(`mark[data-preview-annotation='note'][data-preview-note-id='${noteId.replace(/["\\]/g, "\\$&")}']`);
1477
+ }
1478
+ if (!target) {
1479
+ const range = createRangeFromOffsets(previewArea, record.start, record.end);
1480
+ if (range && !range.collapsed) {
1481
+ const node = range.startContainer;
1482
+ target =
1483
+ node.nodeType === Node.ELEMENT_NODE
1484
+ ? node
1485
+ : node.parentElement;
1486
+ }
1487
+ }
1488
+ if (!target ||
1489
+ typeof target.scrollIntoView !== "function") {
1490
+ return;
1491
+ }
1492
+ target.scrollIntoView({
1493
+ behavior: "smooth",
1494
+ block: "center",
1495
+ inline: "nearest",
1496
+ });
1497
+ flashPreviewAnnotationTarget(target);
1498
+ };
1499
+ const getPreviewAnnotationsByPage = () => {
1500
+ const pageId = getCurrentPageId();
1501
+ const annotations = normalizePreviewAnnotations(state.doc.meta.previewAnnotations);
1502
+ return {
1503
+ annotations,
1504
+ pageId,
1505
+ highlights: annotations.highlights.filter((item) => item.pageId === pageId),
1506
+ notes: annotations.notes.filter((item) => item.pageId === pageId),
1507
+ };
1508
+ };
1509
+ const renderAnnotationPanel = () => {
1510
+ const shouldShowPanel = state.mode === "preview" &&
1511
+ state.features.preview &&
1512
+ previewAnnotationOptions.showAnnotationList;
1513
+ annotationPanel.style.display = shouldShowPanel ? "grid" : "none";
1514
+ previewLayout.classList.toggle("with-annotation-panel", shouldShowPanel);
1515
+ if (!shouldShowPanel) {
1516
+ return;
1517
+ }
1518
+ const { highlights, notes } = getPreviewAnnotationsByPage();
1519
+ annotationHighlightTab.classList.toggle("active", annotationActiveTab === "highlights");
1520
+ annotationNoteTab.classList.toggle("active", annotationActiveTab === "notes");
1521
+ const activeList = annotationActiveTab === "highlights" ? highlights : notes;
1522
+ annotationList.innerHTML = "";
1523
+ if (!activeList.length) {
1524
+ annotationEmpty.style.display = "block";
1525
+ annotationEmpty.textContent =
1526
+ annotationActiveTab === "highlights"
1527
+ ? "当前页暂无高亮"
1528
+ : "当前页暂无笔记";
1529
+ return;
1530
+ }
1531
+ annotationEmpty.style.display = "none";
1532
+ activeList.forEach((record, index) => {
1533
+ const item = document.createElement("li");
1534
+ const button = document.createElement("button");
1535
+ button.type = "button";
1536
+ button.className = "hyewb-preview-annotation-item";
1537
+ const heading = document.createElement("span");
1538
+ heading.className = "hyewb-preview-annotation-item-title";
1539
+ heading.textContent =
1540
+ annotationActiveTab === "highlights"
1541
+ ? `高亮 ${index + 1}`
1542
+ : `笔记 ${index + 1}`;
1543
+ const body = document.createElement("span");
1544
+ body.className = "hyewb-preview-annotation-item-body";
1545
+ const fallbackRange = `[${record.start}, ${record.end}]`;
1546
+ body.textContent =
1547
+ annotationActiveTab === "highlights"
1548
+ ? summarizePreviewText(record.selectedText, fallbackRange)
1549
+ : summarizePreviewText(record.text, "未命名笔记");
1550
+ button.append(heading, body);
1551
+ button.addEventListener("click", () => {
1552
+ focusPreviewAnnotationRecord(record, annotationActiveTab === "highlights" ? "highlight" : "note");
1553
+ });
1554
+ if (previewAnnotationOptions.annotationActions.canDelete) {
1555
+ const deleteButton = document.createElement("button");
1556
+ deleteButton.type = "button";
1557
+ deleteButton.className = "hyewb-preview-annotation-delete";
1558
+ deleteButton.title = "删除标注";
1559
+ deleteButton.setAttribute("aria-label", "删除标注");
1560
+ deleteButton.append(createIconPlaceholder("trash-2"));
1561
+ deleteButton.addEventListener("click", (event) => {
1562
+ event.preventDefault();
1563
+ event.stopPropagation();
1564
+ if (!window.confirm("确定删除这条标注吗?")) {
1565
+ return;
1566
+ }
1567
+ const current = normalizePreviewAnnotations(state.doc.meta.previewAnnotations);
1568
+ if (annotationActiveTab === "highlights") {
1569
+ current.highlights = current.highlights.filter((item) => {
1570
+ if ("id" in record && record.id && item.id) {
1571
+ return String(item.id) !== String(record.id);
1572
+ }
1573
+ return !(item.pageId === record.pageId &&
1574
+ item.start === record.start &&
1575
+ item.end === record.end);
1576
+ });
1577
+ }
1578
+ else {
1579
+ current.notes = current.notes.filter((item) => {
1580
+ if ("id" in record && record.id && item.id) {
1581
+ return String(item.id) !== String(record.id);
1582
+ }
1583
+ return !(item.pageId === record.pageId &&
1584
+ item.start === record.start &&
1585
+ item.end === record.end);
1586
+ });
1587
+ }
1588
+ savePreviewAnnotations(current);
1589
+ });
1590
+ button.append(deleteButton);
1591
+ }
1592
+ item.append(button);
1593
+ annotationList.append(item);
1594
+ });
1595
+ };
1596
+ const applyPreviewAnnotationsToView = () => {
1597
+ if (state.mode !== "preview") {
1598
+ previewSelectionToolbar.classList.remove("show");
1599
+ return;
1600
+ }
1601
+ const { highlights, notes } = getPreviewAnnotationsByPage();
1602
+ applyHighlightMarks(previewArea, highlights);
1603
+ applyNoteMarks(previewArea, notes);
1604
+ };
1605
+ const hidePreviewSelectionToolbar = () => {
1606
+ previewSelectionToolbar.classList.remove("show");
1607
+ previewSelectionDraft = null;
1608
+ };
1609
+ const syncPreviewSelectionToolbar = () => {
1610
+ if (!previewAnnotationOptions.enablePreviewSelectionToolbar ||
1611
+ state.mode !== "preview") {
1612
+ hidePreviewSelectionToolbar();
1613
+ return;
1614
+ }
1615
+ const selection = window.getSelection();
1616
+ if (!selection || selection.rangeCount === 0 || selection.isCollapsed) {
1617
+ hidePreviewSelectionToolbar();
1618
+ return;
1619
+ }
1620
+ const range = selection.getRangeAt(0);
1621
+ if (!previewArea.contains(range.startContainer) ||
1622
+ !previewArea.contains(range.endContainer)) {
1623
+ hidePreviewSelectionToolbar();
1624
+ return;
1625
+ }
1626
+ const offsets = getSelectionOffsets(previewArea, selection);
1627
+ if (!offsets) {
1628
+ hidePreviewSelectionToolbar();
1629
+ return;
1630
+ }
1631
+ const rect = range.getBoundingClientRect();
1632
+ if (!rect.width && !rect.height) {
1633
+ hidePreviewSelectionToolbar();
1634
+ return;
1635
+ }
1636
+ previewSelectionDraft = {
1637
+ start: offsets.start,
1638
+ end: offsets.end,
1639
+ pageId: getCurrentPageId(),
1640
+ text: selection.toString().trim(),
1641
+ };
1642
+ previewSelectionToolbar.style.left = `${Math.round(rect.left + rect.width / 2)}px`;
1643
+ previewSelectionToolbar.style.top = `${Math.round(rect.top - 8)}px`;
1644
+ previewSelectionToolbar.classList.add("show");
1645
+ };
1147
1646
  const hideFloatingToolbar = () => {
1148
1647
  floatingToolbar.classList.remove("show");
1149
1648
  lastSelection = null;
@@ -2844,7 +3343,14 @@ export function mountEditorWorkbench(container, options = {}) {
2844
3343
  selectInlineImage(null);
2845
3344
  rememberedParagraphIndex = null;
2846
3345
  }
2847
- canvas.style.width = `${paperWidth}px`;
3346
+ if (state.mode === "preview") {
3347
+ canvas.style.width = "100%";
3348
+ canvas.style.maxWidth = `${paperWidth}px`;
3349
+ }
3350
+ else {
3351
+ canvas.style.width = `${paperWidth}px`;
3352
+ canvas.style.maxWidth = "100%";
3353
+ }
2848
3354
  previewArea.innerHTML = html;
2849
3355
  previewArea.classList.toggle("show", state.mode === "preview");
2850
3356
  editorArea.style.display = state.mode === "editor" ? "block" : "none";
@@ -2937,6 +3443,9 @@ export function mountEditorWorkbench(container, options = {}) {
2937
3443
  });
2938
3444
  updateInlineResizeOverlay();
2939
3445
  syncToolbarState();
3446
+ applyPreviewAnnotationsToView();
3447
+ renderAnnotationPanel();
3448
+ syncPreviewSelectionToolbar();
2940
3449
  };
2941
3450
  boldBtn.addEventListener("click", () => {
2942
3451
  withSelectionCommand(() => {
@@ -3127,6 +3636,59 @@ export function mountEditorWorkbench(container, options = {}) {
3127
3636
  floatBgColorInput.addEventListener("click", () => {
3128
3637
  openColorPalette(floatBgColorInput, "background");
3129
3638
  });
3639
+ annotationHighlightTab.addEventListener("click", () => {
3640
+ annotationActiveTab = "highlights";
3641
+ renderAnnotationPanel();
3642
+ });
3643
+ annotationNoteTab.addEventListener("click", () => {
3644
+ annotationActiveTab = "notes";
3645
+ renderAnnotationPanel();
3646
+ });
3647
+ previewHighlightBtn.addEventListener("click", () => {
3648
+ if (!previewSelectionDraft) {
3649
+ return;
3650
+ }
3651
+ const current = normalizePreviewAnnotations(state.doc.meta.previewAnnotations);
3652
+ current.highlights = mergeHighlightRecords(current.highlights, {
3653
+ id: `hl-${Date.now()}-${Math.round(Math.random() * 10000)}`,
3654
+ pageId: previewSelectionDraft.pageId,
3655
+ blockId: "preview-flow-text",
3656
+ start: previewSelectionDraft.start,
3657
+ end: previewSelectionDraft.end,
3658
+ color: "#fff59d",
3659
+ selectedText: previewSelectionDraft.text,
3660
+ createdAt: new Date().toISOString(),
3661
+ });
3662
+ annotationActiveTab = "highlights";
3663
+ savePreviewAnnotations(current);
3664
+ window.getSelection()?.removeAllRanges();
3665
+ hidePreviewSelectionToolbar();
3666
+ });
3667
+ previewNoteBtn.addEventListener("click", () => {
3668
+ if (!previewSelectionDraft) {
3669
+ return;
3670
+ }
3671
+ const text = window.prompt("请输入笔记内容", previewSelectionDraft.text || "") || "";
3672
+ const noteText = text.trim();
3673
+ if (!noteText) {
3674
+ return;
3675
+ }
3676
+ const current = normalizePreviewAnnotations(state.doc.meta.previewAnnotations);
3677
+ current.notes = mergeNoteRecords(current.notes, {
3678
+ id: `note-${Date.now()}-${Math.round(Math.random() * 10000)}`,
3679
+ pageId: previewSelectionDraft.pageId,
3680
+ start: previewSelectionDraft.start,
3681
+ end: previewSelectionDraft.end,
3682
+ text: noteText,
3683
+ selectedText: previewSelectionDraft.text,
3684
+ color: "#0e7490",
3685
+ createdAt: new Date().toISOString(),
3686
+ });
3687
+ annotationActiveTab = "notes";
3688
+ savePreviewAnnotations(current);
3689
+ window.getSelection()?.removeAllRanges();
3690
+ hidePreviewSelectionToolbar();
3691
+ });
3130
3692
  floatLeftBtn.addEventListener("click", () => updateAlign("left"));
3131
3693
  floatCenterBtn.addEventListener("click", () => updateAlign("center"));
3132
3694
  floatRightBtn.addEventListener("click", () => updateAlign("right"));
@@ -3781,12 +4343,14 @@ export function mountEditorWorkbench(container, options = {}) {
3781
4343
  updateInlineResizeOverlay();
3782
4344
  syncToolbarState();
3783
4345
  syncFocusedTableControls();
4346
+ syncPreviewSelectionToolbar();
3784
4347
  };
3785
4348
  const handleWindowResize = () => {
3786
4349
  updateShellViewportHeight();
3787
4350
  updateInlineResizeOverlay();
3788
4351
  syncTableToolsPosition();
3789
4352
  syncFocusedTableControls();
4353
+ syncPreviewSelectionToolbar();
3790
4354
  if (tablePicker.classList.contains("show")) {
3791
4355
  showTablePicker();
3792
4356
  }
@@ -3797,6 +4361,7 @@ export function mountEditorWorkbench(container, options = {}) {
3797
4361
  updateFloatingToolbarBySelection();
3798
4362
  syncTableToolsPosition();
3799
4363
  syncFocusedTableControls();
4364
+ syncPreviewSelectionToolbar();
3800
4365
  if (tablePicker.classList.contains("show")) {
3801
4366
  showTablePicker();
3802
4367
  }
@@ -3819,6 +4384,7 @@ export function mountEditorWorkbench(container, options = {}) {
3819
4384
  updateInlineResizeOverlay();
3820
4385
  syncTableToolsPosition();
3821
4386
  syncFocusedTableControls();
4387
+ syncPreviewSelectionToolbar();
3822
4388
  });
3823
4389
  };
3824
4390
  document.addEventListener("fullscreenchange", handleFullscreenChange);
@@ -4013,12 +4579,22 @@ export function mountEditorWorkbench(container, options = {}) {
4013
4579
  };
4014
4580
  }
4015
4581
  function ensureWorkbenchStyles() {
4016
- if (document.getElementById(WORKBENCH_STYLE_ID)) {
4582
+ const existing = document.getElementById(WORKBENCH_STYLE_ID);
4583
+ if (existing instanceof HTMLStyleElement) {
4584
+ if (existing.dataset.hyewbVersion !== WORKBENCH_STYLE_VERSION ||
4585
+ existing.textContent !== WORKBENCH_CSS) {
4586
+ existing.textContent = WORKBENCH_CSS;
4587
+ existing.dataset.hyewbVersion = WORKBENCH_STYLE_VERSION;
4588
+ }
4017
4589
  return;
4018
4590
  }
4591
+ if (existing) {
4592
+ existing.remove();
4593
+ }
4019
4594
  const style = document.createElement("style");
4020
4595
  style.id = WORKBENCH_STYLE_ID;
4021
4596
  style.textContent = WORKBENCH_CSS;
4597
+ style.dataset.hyewbVersion = WORKBENCH_STYLE_VERSION;
4022
4598
  document.head.append(style);
4023
4599
  }
4024
4600
  function resolveFeatures(next, base = DEFAULT_EDITOR_WORKBENCH_FEATURES) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyebook/vue3-adapter",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "Vue3 adapter for hy-ebook core",
5
5
  "repository": {
6
6
  "type": "git",
@@ -17,7 +17,7 @@
17
17
  "dist"
18
18
  ],
19
19
  "dependencies": {
20
- "@hyebook/core": "^0.2.1"
20
+ "@hyebook/core": "^0.2.3"
21
21
  },
22
22
  "scripts": {
23
23
  "build": "tsc -p tsconfig.json",