@hyebook/vue3-adapter 0.2.0 → 0.2.2
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;
|
|
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;AA2KxB,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,kBAAkB,CAAC,EAAE,uCAAuC,CAAC;IAC7D,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,uCAAuC;IACtD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,uCAAuC;IACtD,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,6BAA6B,CAAC,EAAE,OAAO,CAAC;IACxC,wBAAwB,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC;IAClD,iBAAiB,CAAC,EAAE,uCAAuC,CAAC;CAC7D;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;AAoSjC,wBAAgB,8BAA8B,IAAI,QAAQ,CA6GzD;AAED,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,WAAW,EACtB,OAAO,GAAE,sBAA2B,GACnC,qBAAqB,CAs9JvB"}
|
|
@@ -22,8 +22,10 @@ const WORKBENCH_CSS = `
|
|
|
22
22
|
.hyewb-field-icon{position:absolute;left:10px;top:50%;transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;color:#64748b;pointer-events:none;z-index:1}
|
|
23
23
|
.hyewb-field-icon svg{width:14px;height:14px;stroke-width:2}
|
|
24
24
|
.hyewb-field-with-icon .hyewb-select,.hyewb-field-with-icon .hyewb-number{padding-left:30px}
|
|
25
|
-
.hyewb-shell{border:1px dashed #b8c3d1;border-radius:10px;background:#eef4ff;padding:10px;overflow-x:auto}
|
|
26
|
-
.hyewb-
|
|
25
|
+
.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-preview-layout{display:grid;grid-template-columns:minmax(0,1fr);gap:12px;align-items:start}
|
|
27
|
+
.hyewb-preview-layout.with-annotation-panel{grid-template-columns:minmax(0,1fr) 300px}
|
|
28
|
+
.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
29
|
.hyewb-editor{min-height:360px;outline:none;line-height:1.7;font-size:16px;color:#1e293b}
|
|
28
30
|
.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
31
|
.hyewb-float.show{display:inline-flex}
|
|
@@ -81,18 +83,20 @@ const WORKBENCH_CSS = `
|
|
|
81
83
|
.hyewb-table-picker-row{display:flex;align-items:center;gap:8px}
|
|
82
84
|
.hyewb-table-picker-confirm{border:1px solid #0b7285;background:#0b7285;color:#fff;border-radius:8px;height:32px;padding:0 10px;cursor:pointer}
|
|
83
85
|
.hyewb-table-tools{display:none !important}
|
|
84
|
-
.hyewb-table-tools.show{display:
|
|
86
|
+
.hyewb-table-tools.show{display:flex !important}
|
|
85
87
|
.hyewb-table-tools .hyewb-btn{width:30px;height:30px;border-color:#334155;background:#1e293b;color:#f8fafc}
|
|
86
88
|
.hyewb-table-tools .hyewb-number{width:68px;height:30px;padding:4px 6px;border-color:#334155;background:#1e293b;color:#f8fafc}
|
|
87
89
|
.hyewb-table-tools label{font-size:12px;color:#e2e8f0;display:inline-flex;align-items:center;gap:4px}
|
|
88
|
-
.hyewb-table-row-delete{position:fixed;display:none;z-index:10026;width:
|
|
90
|
+
.hyewb-table-row-delete{position:fixed;display:none;z-index:10026;width:20px;height:20px;border:1px solid #ef4444;background:#fff;color:#dc2626;border-radius:999px;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 8px 18px rgba(15,23,42,.2);padding:0}
|
|
89
91
|
.hyewb-table-row-delete.show{display:inline-flex}
|
|
90
92
|
.hyewb-table-row-delete::before{content:"";position:absolute;left:-14px;top:-8px;width:20px;height:44px}
|
|
91
|
-
.hyewb-table-handle{position:fixed;display:none;z-index:10030;width:
|
|
93
|
+
.hyewb-table-handle{position:fixed;display:none;z-index:10030;width:16px;height:16px;border-radius:999px;border:1px solid #0284c7;background:#ffffff;color:#0369a1;align-items:center;justify-content:center;cursor:grab;box-shadow:0 8px 18px rgba(15,23,42,.2);padding:0}
|
|
92
94
|
.hyewb-table-handle.show{display:inline-flex}
|
|
93
95
|
.hyewb-table-handle:active{cursor:grabbing}
|
|
94
96
|
.hyewb-table-handle.scale{cursor:nwse-resize}
|
|
95
97
|
.hyewb-table-handle.scale:active{cursor:nwse-resize}
|
|
98
|
+
.hyewb-table-handle .hyewb-icon,.hyewb-table-row-delete .hyewb-icon{display:inline-flex;align-items:center;justify-content:center}
|
|
99
|
+
.hyewb-table-handle svg,.hyewb-table-row-delete svg{width:8px;height:8px;stroke-width:2.25;flex:0 0 auto}
|
|
96
100
|
.hyewb-table-edge-layer{position:fixed;display:none;z-index:10028;pointer-events:none}
|
|
97
101
|
.hyewb-table-edge-layer.show{display:block}
|
|
98
102
|
.hyewb-table-edge-hit{position:absolute;display:flex;align-items:center;justify-content:center;border:1px solid #cbd5e1;background:#f8fafc;color:#0369a1;border-radius:0px;cursor:grab;pointer-events:auto;line-height:1;font-size:12px;padding:0}
|
|
@@ -100,7 +104,7 @@ const WORKBENCH_CSS = `
|
|
|
100
104
|
.hyewb-table-edge-hit.active{border-color:#0284c7;background:#e0f2fe;color:#0c4a6e}
|
|
101
105
|
.hyewb-table-edge-layer.col .hyewb-table-edge-hit{height:14px}
|
|
102
106
|
.hyewb-table-edge-layer.row .hyewb-table-edge-hit{width:14px}
|
|
103
|
-
.hyewb-table-gap-insert{position:fixed;display:none;z-index:10029;width:
|
|
107
|
+
.hyewb-table-gap-insert{position:fixed;display:none;z-index:10029;width:18px;height:18px;border-radius:999px;border:1px solid #0284c7;background:#ffffff;color:#0369a1;cursor:pointer;align-items:center;justify-content:center;padding:0;font-size:14px;line-height:1;box-shadow:0 8px 18px rgba(15,23,42,.2)}
|
|
104
108
|
.hyewb-table-gap-insert.show{display:inline-flex}
|
|
105
109
|
.hyewb-table-drop-indicator{position:fixed;display:none;z-index:10024;background:#0284c7;pointer-events:none;border-radius:999px}
|
|
106
110
|
.hyewb-table-drop-indicator.show{display:block}
|
|
@@ -137,6 +141,31 @@ const WORKBENCH_CSS = `
|
|
|
137
141
|
.hyewb-upload-progress{height:8px;background:#e2e8f0;border-radius:999px;overflow:hidden}
|
|
138
142
|
.hyewb-upload-progress > span{display:block;height:100%;width:0;background:#0b7285;transition:width .18s ease}
|
|
139
143
|
.hyewb-upload-error{min-height:18px;font-size:12px;color:#b91c1c;margin:0}
|
|
144
|
+
.hyewb-preview-highlight-mark{background:var(--hyewb-highlight-color,#fff59d);color:inherit;padding:0 .08em;border-radius:.2em}
|
|
145
|
+
.hyewb-preview-note-mark{background:rgba(14,116,144,.14);border-bottom:2px solid #0e7490;color:inherit;padding:0 .04em;border-radius:.2em}
|
|
146
|
+
.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}
|
|
147
|
+
.hyewb-preview-annotation-title{margin:0;font-size:14px}
|
|
148
|
+
.hyewb-preview-annotation-tabs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
|
|
149
|
+
.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}
|
|
150
|
+
.hyewb-preview-annotation-tab.active{color:#ffffff;background:#0b7285;border-color:#0b7285}
|
|
151
|
+
.hyewb-preview-annotation-list{margin:0;padding:0;list-style:none;display:grid;gap:8px}
|
|
152
|
+
.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}
|
|
153
|
+
.hyewb-preview-annotation-item:hover{background:#eef6ff;border-color:#b9d7f4}
|
|
154
|
+
.hyewb-preview-annotation-item-title{font-size:12px;color:#0f766e}
|
|
155
|
+
.hyewb-preview-annotation-item-body{font-size:13px;color:#1e293b;line-height:1.5}
|
|
156
|
+
.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}
|
|
157
|
+
.hyewb-preview-annotation-item:hover .hyewb-preview-annotation-delete{opacity:1;pointer-events:auto}
|
|
158
|
+
.hyewb-preview-annotation-delete svg{width:14px;height:14px}
|
|
159
|
+
.hyewb-preview-annotation-empty{margin:0;color:#64748b;font-size:13px}
|
|
160
|
+
.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%)}
|
|
161
|
+
.hyewb-preview-selection-toolbar.show{display:inline-flex}
|
|
162
|
+
.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}
|
|
163
|
+
.hyewb-preview-selection-btn:hover{background:#334155}
|
|
164
|
+
.hyewb-preview-selection-btn svg{width:16px;height:16px}
|
|
165
|
+
.hyewb-preview-annotation-flash{animation:hyewb-preview-annotation-pulse .9s ease}
|
|
166
|
+
@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)}}
|
|
167
|
+
.hyewb-root:fullscreen .hyewb-editor,.hyewb-root:fullscreen .hyewb-preview{min-height:1000px}
|
|
168
|
+
.hyewb-root:-webkit-full-screen .hyewb-editor,.hyewb-root:-webkit-full-screen .hyewb-preview{min-height:1000px}
|
|
140
169
|
`;
|
|
141
170
|
export const DEFAULT_EDITOR_WORKBENCH_FEATURES = {
|
|
142
171
|
textToolbar: true,
|
|
@@ -155,19 +184,25 @@ const WORKBENCH_ICON_PATHS = {
|
|
|
155
184
|
bold: '<path d="M7 4h6a3 3 0 0 1 0 6H7z"/><path d="M7 10h7a3 3 0 0 1 0 6H7z"/>',
|
|
156
185
|
"chevron-left": '<polyline points="15 18 9 12 15 6"/>',
|
|
157
186
|
"chevron-right": '<polyline points="9 18 15 12 9 6"/>',
|
|
187
|
+
"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"/>',
|
|
188
|
+
"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"/>',
|
|
189
|
+
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"/>',
|
|
158
190
|
"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"/>',
|
|
159
191
|
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"/>',
|
|
160
192
|
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"/>',
|
|
161
193
|
"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"/>',
|
|
162
194
|
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"/>',
|
|
195
|
+
"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"/>',
|
|
163
196
|
"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"/>',
|
|
164
197
|
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"/>',
|
|
165
198
|
pilcrow: '<path d="M9 4h7v16"/><path d="M12 4v16"/><path d="M9 4a4 4 0 0 0 0 8h3"/>',
|
|
199
|
+
"resize-se": '<polyline points="11 13 13 13 13 11"/><line x1="10" y1="14" x2="14" y2="10"/><polyline points="15 19 19 19 19 15"/><line x1="14" y1="20" x2="20" y2="14"/>',
|
|
166
200
|
"square-plus": '<rect x="3" y="3" width="18" height="18" rx="2"/><line x1="12" y1="8" x2="12" y2="16"/><line x1="8" y1="12" x2="16" y2="12"/>',
|
|
167
201
|
strikethrough: '<path d="M16 5a4 4 0 0 0-8 0c0 2.2 2 3.2 4 4"/><path d="M8 19a4 4 0 0 0 8 0c0-2.2-2-3.2-4-4"/><line x1="4" y1="12" x2="20" y2="12"/>',
|
|
168
|
-
subscript: '<
|
|
169
|
-
superscript: '<
|
|
202
|
+
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"/>',
|
|
203
|
+
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"/>',
|
|
170
204
|
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"/>',
|
|
205
|
+
"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"/>',
|
|
171
206
|
underline: '<path d="M6 4v6a6 6 0 0 0 12 0V4"/><line x1="4" y1="20" x2="20" y2="20"/>',
|
|
172
207
|
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"/>',
|
|
173
208
|
x: '<line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/>',
|
|
@@ -191,6 +226,7 @@ const WORKBENCH_BUTTONS = {
|
|
|
191
226
|
alignCenter: { icon: "align-center", ariaLabel: "居中" },
|
|
192
227
|
alignRight: { icon: "align-right", ariaLabel: "右对齐" },
|
|
193
228
|
alignJustify: { icon: "align-justify", ariaLabel: "两端对齐" },
|
|
229
|
+
fullscreen: { icon: "fullscreen-enter", ariaLabel: "全屏" },
|
|
194
230
|
close: { icon: "x", ariaLabel: "关闭" },
|
|
195
231
|
};
|
|
196
232
|
const COLOR_SWATCHES = [
|
|
@@ -265,6 +301,17 @@ const RESIZE_HANDLES = [
|
|
|
265
301
|
"sw",
|
|
266
302
|
"w",
|
|
267
303
|
];
|
|
304
|
+
const DEFAULT_FLOW_BLOCK_WIDTH = 620;
|
|
305
|
+
function resolvePreviewAnnotationOptions(options) {
|
|
306
|
+
return {
|
|
307
|
+
showAnnotationList: options?.showAnnotationList ?? true,
|
|
308
|
+
enablePreviewSelectionToolbar: options?.enablePreviewSelectionToolbar ?? true,
|
|
309
|
+
annotationListDefaultTab: options?.annotationListDefaultTab === "notes" ? "notes" : "highlights",
|
|
310
|
+
annotationActions: {
|
|
311
|
+
canDelete: options?.annotationActions?.canDelete ?? true,
|
|
312
|
+
},
|
|
313
|
+
};
|
|
314
|
+
}
|
|
268
315
|
export function createDefaultWorkbenchDocument() {
|
|
269
316
|
const now = new Date().toISOString();
|
|
270
317
|
return {
|
|
@@ -385,6 +432,7 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
385
432
|
doc: editor.getDocument(),
|
|
386
433
|
features: resolveFeatures(options.features),
|
|
387
434
|
};
|
|
435
|
+
const previewAnnotationOptions = resolvePreviewAnnotationOptions(options.previewAnnotations);
|
|
388
436
|
const paperWidth = resolvePaperWidth(options.pageWidth, state.doc.settings.page.width);
|
|
389
437
|
const root = document.createElement("section");
|
|
390
438
|
root.className = "hyewb-root";
|
|
@@ -393,6 +441,7 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
393
441
|
const title = document.createElement("div");
|
|
394
442
|
title.className = "hyewb-title";
|
|
395
443
|
title.textContent = options.title ?? "hy-ebook Editor Workbench";
|
|
444
|
+
const fullscreenBtn = createButton("fullscreen");
|
|
396
445
|
header.append(title);
|
|
397
446
|
const toolbar = document.createElement("div");
|
|
398
447
|
toolbar.className = "hyewb-row";
|
|
@@ -611,7 +660,7 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
611
660
|
tableScaleHandle.className = "hyewb-table-handle scale";
|
|
612
661
|
tableScaleHandle.title = "按比例缩放表格";
|
|
613
662
|
tableScaleHandle.setAttribute("aria-label", "按比例缩放表格");
|
|
614
|
-
tableScaleHandle.append(createIconPlaceholder("
|
|
663
|
+
tableScaleHandle.append(createIconPlaceholder("resize-se"));
|
|
615
664
|
const tableColEdgeLayer = document.createElement("div");
|
|
616
665
|
tableColEdgeLayer.className = "hyewb-table-edge-layer col";
|
|
617
666
|
const tableRowEdgeLayer = document.createElement("div");
|
|
@@ -662,7 +711,10 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
662
711
|
const addPageBtn = createButton("addPage");
|
|
663
712
|
const pageInfo = document.createElement("span");
|
|
664
713
|
pageInfo.className = "hyewb-status";
|
|
665
|
-
|
|
714
|
+
fullscreenBtn.style.marginLeft = "auto";
|
|
715
|
+
pageRow.append(prevPageBtn, nextPageBtn, addPageBtn, pageInfo, fullscreenBtn);
|
|
716
|
+
const previewLayout = document.createElement("div");
|
|
717
|
+
previewLayout.className = "hyewb-preview-layout";
|
|
666
718
|
const shell = document.createElement("div");
|
|
667
719
|
shell.className = "hyewb-shell";
|
|
668
720
|
const canvas = document.createElement("div");
|
|
@@ -687,6 +739,43 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
687
739
|
mediaList.className = "hyewb-media-list";
|
|
688
740
|
canvas.append(editorArea, previewArea, mediaStage, inlineResizeOverlay, mediaList);
|
|
689
741
|
shell.append(canvas);
|
|
742
|
+
const annotationPanel = document.createElement("aside");
|
|
743
|
+
annotationPanel.className = "hyewb-preview-annotation-panel";
|
|
744
|
+
const annotationTitle = document.createElement("h3");
|
|
745
|
+
annotationTitle.className = "hyewb-preview-annotation-title";
|
|
746
|
+
annotationTitle.textContent = "预览标注";
|
|
747
|
+
const annotationTabs = document.createElement("div");
|
|
748
|
+
annotationTabs.className = "hyewb-preview-annotation-tabs";
|
|
749
|
+
const annotationHighlightTab = document.createElement("button");
|
|
750
|
+
annotationHighlightTab.type = "button";
|
|
751
|
+
annotationHighlightTab.className = "hyewb-preview-annotation-tab";
|
|
752
|
+
annotationHighlightTab.textContent = "高亮";
|
|
753
|
+
const annotationNoteTab = document.createElement("button");
|
|
754
|
+
annotationNoteTab.type = "button";
|
|
755
|
+
annotationNoteTab.className = "hyewb-preview-annotation-tab";
|
|
756
|
+
annotationNoteTab.textContent = "笔记";
|
|
757
|
+
annotationTabs.append(annotationHighlightTab, annotationNoteTab);
|
|
758
|
+
const annotationList = document.createElement("ul");
|
|
759
|
+
annotationList.className = "hyewb-preview-annotation-list";
|
|
760
|
+
const annotationEmpty = document.createElement("p");
|
|
761
|
+
annotationEmpty.className = "hyewb-preview-annotation-empty";
|
|
762
|
+
annotationPanel.append(annotationTitle, annotationTabs, annotationList, annotationEmpty);
|
|
763
|
+
previewLayout.append(shell, annotationPanel);
|
|
764
|
+
const previewSelectionToolbar = document.createElement("div");
|
|
765
|
+
previewSelectionToolbar.className = "hyewb-preview-selection-toolbar";
|
|
766
|
+
const previewHighlightBtn = document.createElement("button");
|
|
767
|
+
previewHighlightBtn.type = "button";
|
|
768
|
+
previewHighlightBtn.className = "hyewb-preview-selection-btn";
|
|
769
|
+
previewHighlightBtn.title = "创建高亮";
|
|
770
|
+
previewHighlightBtn.setAttribute("aria-label", "创建高亮");
|
|
771
|
+
previewHighlightBtn.append(createIconPlaceholder("highlighter"));
|
|
772
|
+
const previewNoteBtn = document.createElement("button");
|
|
773
|
+
previewNoteBtn.type = "button";
|
|
774
|
+
previewNoteBtn.className = "hyewb-preview-selection-btn";
|
|
775
|
+
previewNoteBtn.title = "创建笔记";
|
|
776
|
+
previewNoteBtn.setAttribute("aria-label", "创建笔记");
|
|
777
|
+
previewNoteBtn.append(createIconPlaceholder("notebook-pen"));
|
|
778
|
+
previewSelectionToolbar.append(previewHighlightBtn, previewNoteBtn);
|
|
690
779
|
const floatingToolbar = document.createElement("div");
|
|
691
780
|
floatingToolbar.className = "hyewb-float";
|
|
692
781
|
const floatBoldBtn = createButton("bold");
|
|
@@ -761,7 +850,7 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
761
850
|
const colorGrid = document.createElement("div");
|
|
762
851
|
colorGrid.className = "hyewb-color-grid";
|
|
763
852
|
colorPalette.append(colorGrid);
|
|
764
|
-
root.append(header, toolbar, pageRow,
|
|
853
|
+
root.append(header, toolbar, pageRow, previewLayout, status, colorPalette, tablePicker, tableTools, tableRowDeleteBtn, tableMoveHandle, tableScaleHandle, tableColEdgeLayer, tableRowEdgeLayer, tableRowGapInsertBtn, tableColGapInsertBtn, tableDropIndicator, tableContextMenu, uploadBackdrop, docxInput, previewSelectionToolbar);
|
|
765
854
|
container.innerHTML = "";
|
|
766
855
|
container.append(root, floatingToolbar);
|
|
767
856
|
renderWorkbenchIcons();
|
|
@@ -787,6 +876,8 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
787
876
|
let tableContextTarget = null;
|
|
788
877
|
let selectedTableRowIndex = null;
|
|
789
878
|
let selectedTableColIndex = null;
|
|
879
|
+
let annotationActiveTab = previewAnnotationOptions.annotationListDefaultTab;
|
|
880
|
+
let previewSelectionDraft = null;
|
|
790
881
|
const isTableGapInsertTarget = (node) => {
|
|
791
882
|
if (!node) {
|
|
792
883
|
return false;
|
|
@@ -802,6 +893,77 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
802
893
|
speedMbps: undefined,
|
|
803
894
|
error: undefined,
|
|
804
895
|
};
|
|
896
|
+
const setButtonIcon = (button, iconName) => {
|
|
897
|
+
button.innerHTML = "";
|
|
898
|
+
button.append(createIconPlaceholder(iconName));
|
|
899
|
+
};
|
|
900
|
+
const getFullscreenElement = () => {
|
|
901
|
+
const webkitDocument = document;
|
|
902
|
+
return (document.fullscreenElement ||
|
|
903
|
+
webkitDocument.webkitFullscreenElement ||
|
|
904
|
+
null);
|
|
905
|
+
};
|
|
906
|
+
const isWorkbenchFullscreen = () => {
|
|
907
|
+
return getFullscreenElement() === root;
|
|
908
|
+
};
|
|
909
|
+
const updateFullscreenButtonState = () => {
|
|
910
|
+
const isFullscreen = isWorkbenchFullscreen();
|
|
911
|
+
setButtonActive(fullscreenBtn, isFullscreen);
|
|
912
|
+
setButtonIcon(fullscreenBtn, isFullscreen ? "fullscreen-exit" : "fullscreen-enter");
|
|
913
|
+
const label = isFullscreen ? "退出全屏" : "全屏";
|
|
914
|
+
fullscreenBtn.title = label;
|
|
915
|
+
fullscreenBtn.setAttribute("aria-label", label);
|
|
916
|
+
};
|
|
917
|
+
const updateShellViewportHeight = () => {
|
|
918
|
+
const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
|
|
919
|
+
const top = root.getBoundingClientRect().top;
|
|
920
|
+
const bottomPadding = isWorkbenchFullscreen() ? 16 : 24;
|
|
921
|
+
const nextHeight = Math.max(320, Math.floor(viewportHeight - top - bottomPadding));
|
|
922
|
+
shell.style.maxHeight = `${nextHeight}px`;
|
|
923
|
+
};
|
|
924
|
+
const requestWorkbenchFullscreen = async () => {
|
|
925
|
+
const target = root;
|
|
926
|
+
if (typeof target.requestFullscreen === "function") {
|
|
927
|
+
await target.requestFullscreen();
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
if (typeof target.webkitRequestFullscreen === "function") {
|
|
931
|
+
target.webkitRequestFullscreen();
|
|
932
|
+
return;
|
|
933
|
+
}
|
|
934
|
+
throw new Error("当前环境不支持全屏");
|
|
935
|
+
};
|
|
936
|
+
const exitWorkbenchFullscreen = async () => {
|
|
937
|
+
const webkitDocument = document;
|
|
938
|
+
if (typeof document.exitFullscreen === "function") {
|
|
939
|
+
await document.exitFullscreen();
|
|
940
|
+
return;
|
|
941
|
+
}
|
|
942
|
+
if (typeof webkitDocument.webkitExitFullscreen === "function") {
|
|
943
|
+
webkitDocument.webkitExitFullscreen();
|
|
944
|
+
return;
|
|
945
|
+
}
|
|
946
|
+
if (typeof webkitDocument.webkitCancelFullScreen === "function") {
|
|
947
|
+
webkitDocument.webkitCancelFullScreen();
|
|
948
|
+
}
|
|
949
|
+
};
|
|
950
|
+
const toggleWorkbenchFullscreen = async () => {
|
|
951
|
+
try {
|
|
952
|
+
if (isWorkbenchFullscreen()) {
|
|
953
|
+
await exitWorkbenchFullscreen();
|
|
954
|
+
}
|
|
955
|
+
else {
|
|
956
|
+
await requestWorkbenchFullscreen();
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
catch {
|
|
960
|
+
status.textContent = "当前浏览器不支持全屏";
|
|
961
|
+
}
|
|
962
|
+
finally {
|
|
963
|
+
updateFullscreenButtonState();
|
|
964
|
+
updateShellViewportHeight();
|
|
965
|
+
}
|
|
966
|
+
};
|
|
805
967
|
const formatUploadProgress = (percent) => {
|
|
806
968
|
const safe = Number.isFinite(percent) ? percent : 0;
|
|
807
969
|
const clamped = Math.max(0, Math.min(100, safe));
|
|
@@ -947,7 +1109,7 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
947
1109
|
const mammothNamespace = await import("mammoth");
|
|
948
1110
|
const mammothModule = resolveMammothModule(mammothNamespace);
|
|
949
1111
|
const arrayBuffer = await file.arrayBuffer();
|
|
950
|
-
const xmlPreferredFlowBlocks = await parseDocxFlowBlocksFromXml(arrayBuffer);
|
|
1112
|
+
const xmlPreferredFlowBlocks = await parseDocxFlowBlocksFromXml(arrayBuffer, resolveDocxImportMaxFlowBlockWidth(state.doc.settings.page, paperWidth));
|
|
951
1113
|
if (xmlPreferredFlowBlocks?.length) {
|
|
952
1114
|
syncEditorToDoc();
|
|
953
1115
|
const nextDoc = clone(state.doc);
|
|
@@ -1050,6 +1212,7 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
1050
1212
|
syncEditorToDoc();
|
|
1051
1213
|
state.mode = nextMode;
|
|
1052
1214
|
hideFloatingToolbar();
|
|
1215
|
+
hidePreviewSelectionToolbar();
|
|
1053
1216
|
render();
|
|
1054
1217
|
};
|
|
1055
1218
|
const loadPreviewAnnotations = () => {
|
|
@@ -1062,6 +1225,423 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
1062
1225
|
updateStateDoc(nextDoc);
|
|
1063
1226
|
return clone(normalized);
|
|
1064
1227
|
};
|
|
1228
|
+
const getCurrentPageId = () => {
|
|
1229
|
+
return state.doc.pages[state.pageIndex]?.id || `page-${state.pageIndex}`;
|
|
1230
|
+
};
|
|
1231
|
+
const normalizeOffsetRange = (start, end) => {
|
|
1232
|
+
const safeStart = Math.max(0, Math.floor(start || 0));
|
|
1233
|
+
const safeEnd = Math.max(0, Math.floor(end || 0));
|
|
1234
|
+
if (safeStart === safeEnd) {
|
|
1235
|
+
return null;
|
|
1236
|
+
}
|
|
1237
|
+
return safeStart < safeEnd
|
|
1238
|
+
? { start: safeStart, end: safeEnd }
|
|
1239
|
+
: { start: safeEnd, end: safeStart };
|
|
1240
|
+
};
|
|
1241
|
+
const getNodeTextLength = (rootNode) => {
|
|
1242
|
+
if (!rootNode) {
|
|
1243
|
+
return 0;
|
|
1244
|
+
}
|
|
1245
|
+
const walker = document.createTreeWalker(rootNode, NodeFilter.SHOW_TEXT);
|
|
1246
|
+
let size = 0;
|
|
1247
|
+
while (walker.nextNode()) {
|
|
1248
|
+
size += walker.currentNode.textContent?.length || 0;
|
|
1249
|
+
}
|
|
1250
|
+
return size;
|
|
1251
|
+
};
|
|
1252
|
+
const getRangeTextLength = (range) => {
|
|
1253
|
+
if (!range) {
|
|
1254
|
+
return 0;
|
|
1255
|
+
}
|
|
1256
|
+
return getNodeTextLength(range.cloneContents());
|
|
1257
|
+
};
|
|
1258
|
+
const getSelectionOffsets = (containerNode, selection) => {
|
|
1259
|
+
if (!selection.rangeCount) {
|
|
1260
|
+
return null;
|
|
1261
|
+
}
|
|
1262
|
+
const range = selection.getRangeAt(0);
|
|
1263
|
+
if (!containerNode.contains(range.startContainer) ||
|
|
1264
|
+
!containerNode.contains(range.endContainer)) {
|
|
1265
|
+
return null;
|
|
1266
|
+
}
|
|
1267
|
+
const beforeStart = range.cloneRange();
|
|
1268
|
+
beforeStart.selectNodeContents(containerNode);
|
|
1269
|
+
beforeStart.setEnd(range.startContainer, range.startOffset);
|
|
1270
|
+
const beforeEnd = range.cloneRange();
|
|
1271
|
+
beforeEnd.selectNodeContents(containerNode);
|
|
1272
|
+
beforeEnd.setEnd(range.endContainer, range.endOffset);
|
|
1273
|
+
return normalizeOffsetRange(getRangeTextLength(beforeStart), getRangeTextLength(beforeEnd));
|
|
1274
|
+
};
|
|
1275
|
+
const createRangeFromOffsets = (containerNode, start, end) => {
|
|
1276
|
+
const normalized = normalizeOffsetRange(start, end);
|
|
1277
|
+
if (!normalized) {
|
|
1278
|
+
return null;
|
|
1279
|
+
}
|
|
1280
|
+
const range = document.createRange();
|
|
1281
|
+
const walker = document.createTreeWalker(containerNode, NodeFilter.SHOW_TEXT);
|
|
1282
|
+
let cursor = 0;
|
|
1283
|
+
let startNode = null;
|
|
1284
|
+
let endNode = null;
|
|
1285
|
+
let startOffset = 0;
|
|
1286
|
+
let endOffset = 0;
|
|
1287
|
+
let lastTextNode = null;
|
|
1288
|
+
while (walker.nextNode()) {
|
|
1289
|
+
const node = walker.currentNode;
|
|
1290
|
+
const length = node.textContent?.length || 0;
|
|
1291
|
+
lastTextNode = node;
|
|
1292
|
+
const nextCursor = cursor + length;
|
|
1293
|
+
if (!startNode &&
|
|
1294
|
+
normalized.start >= cursor &&
|
|
1295
|
+
normalized.start < nextCursor) {
|
|
1296
|
+
startNode = node;
|
|
1297
|
+
startOffset = normalized.start - cursor;
|
|
1298
|
+
}
|
|
1299
|
+
if (!endNode && normalized.end > cursor && normalized.end <= nextCursor) {
|
|
1300
|
+
endNode = node;
|
|
1301
|
+
endOffset = normalized.end - cursor;
|
|
1302
|
+
break;
|
|
1303
|
+
}
|
|
1304
|
+
cursor = nextCursor;
|
|
1305
|
+
}
|
|
1306
|
+
if (!startNode && lastTextNode && normalized.start === cursor) {
|
|
1307
|
+
startNode = lastTextNode;
|
|
1308
|
+
startOffset = lastTextNode.textContent?.length || 0;
|
|
1309
|
+
}
|
|
1310
|
+
if (!endNode && lastTextNode && normalized.end === cursor) {
|
|
1311
|
+
endNode = lastTextNode;
|
|
1312
|
+
endOffset = lastTextNode.textContent?.length || 0;
|
|
1313
|
+
}
|
|
1314
|
+
if (!startNode || !endNode) {
|
|
1315
|
+
return null;
|
|
1316
|
+
}
|
|
1317
|
+
range.setStart(startNode, startOffset);
|
|
1318
|
+
range.setEnd(endNode, endOffset);
|
|
1319
|
+
return range;
|
|
1320
|
+
};
|
|
1321
|
+
const unwrapPreviewMarks = (containerNode, kinds) => {
|
|
1322
|
+
const selector = kinds
|
|
1323
|
+
.map((kind) => `mark[data-preview-annotation='${kind}']`)
|
|
1324
|
+
.join(",");
|
|
1325
|
+
if (!selector) {
|
|
1326
|
+
return;
|
|
1327
|
+
}
|
|
1328
|
+
const marks = Array.from(containerNode.querySelectorAll(selector));
|
|
1329
|
+
marks.forEach((mark) => {
|
|
1330
|
+
const parent = mark.parentNode;
|
|
1331
|
+
if (!parent) {
|
|
1332
|
+
return;
|
|
1333
|
+
}
|
|
1334
|
+
while (mark.firstChild) {
|
|
1335
|
+
parent.insertBefore(mark.firstChild, mark);
|
|
1336
|
+
}
|
|
1337
|
+
parent.removeChild(mark);
|
|
1338
|
+
});
|
|
1339
|
+
};
|
|
1340
|
+
const applyHighlightMarks = (containerNode, highlights) => {
|
|
1341
|
+
unwrapPreviewMarks(containerNode, ["highlight"]);
|
|
1342
|
+
[...highlights]
|
|
1343
|
+
.filter((item) => Number.isFinite(item.start) && Number.isFinite(item.end))
|
|
1344
|
+
.sort((a, b) => b.start - a.start)
|
|
1345
|
+
.forEach((item) => {
|
|
1346
|
+
const range = createRangeFromOffsets(containerNode, item.start, item.end);
|
|
1347
|
+
if (!range || range.collapsed) {
|
|
1348
|
+
return;
|
|
1349
|
+
}
|
|
1350
|
+
const mark = document.createElement("mark");
|
|
1351
|
+
mark.dataset.previewAnnotation = "highlight";
|
|
1352
|
+
mark.className = "hyewb-preview-highlight-mark";
|
|
1353
|
+
mark.style.setProperty("--hyewb-highlight-color", item.color || "#fff59d");
|
|
1354
|
+
try {
|
|
1355
|
+
range.surroundContents(mark);
|
|
1356
|
+
}
|
|
1357
|
+
catch {
|
|
1358
|
+
const fragment = range.extractContents();
|
|
1359
|
+
mark.append(fragment);
|
|
1360
|
+
range.insertNode(mark);
|
|
1361
|
+
}
|
|
1362
|
+
});
|
|
1363
|
+
};
|
|
1364
|
+
const applyNoteMarks = (containerNode, notes) => {
|
|
1365
|
+
unwrapPreviewMarks(containerNode, ["note"]);
|
|
1366
|
+
[...notes]
|
|
1367
|
+
.filter((item) => Number.isFinite(item.start) && Number.isFinite(item.end))
|
|
1368
|
+
.sort((a, b) => b.start - a.start)
|
|
1369
|
+
.forEach((item) => {
|
|
1370
|
+
const range = createRangeFromOffsets(containerNode, item.start, item.end);
|
|
1371
|
+
if (!range || range.collapsed) {
|
|
1372
|
+
return;
|
|
1373
|
+
}
|
|
1374
|
+
const mark = document.createElement("mark");
|
|
1375
|
+
mark.dataset.previewAnnotation = "note";
|
|
1376
|
+
mark.dataset.previewNoteId = item.id || "";
|
|
1377
|
+
mark.className = "hyewb-preview-note-mark";
|
|
1378
|
+
try {
|
|
1379
|
+
range.surroundContents(mark);
|
|
1380
|
+
}
|
|
1381
|
+
catch {
|
|
1382
|
+
const fragment = range.extractContents();
|
|
1383
|
+
mark.append(fragment);
|
|
1384
|
+
range.insertNode(mark);
|
|
1385
|
+
}
|
|
1386
|
+
});
|
|
1387
|
+
};
|
|
1388
|
+
const mergeHighlightRecords = (records, draft) => {
|
|
1389
|
+
const normalized = normalizeOffsetRange(draft.start, draft.end);
|
|
1390
|
+
if (!normalized || !draft.pageId || !draft.blockId) {
|
|
1391
|
+
return records;
|
|
1392
|
+
}
|
|
1393
|
+
const targetColor = draft.color || "#fff59d";
|
|
1394
|
+
const sameBucket = [];
|
|
1395
|
+
const rest = [];
|
|
1396
|
+
records.forEach((item) => {
|
|
1397
|
+
if (item.pageId === draft.pageId &&
|
|
1398
|
+
item.blockId === draft.blockId &&
|
|
1399
|
+
(item.color || "#fff59d") === targetColor) {
|
|
1400
|
+
sameBucket.push(item);
|
|
1401
|
+
}
|
|
1402
|
+
else {
|
|
1403
|
+
rest.push(item);
|
|
1404
|
+
}
|
|
1405
|
+
});
|
|
1406
|
+
let mergedStart = normalized.start;
|
|
1407
|
+
let mergedEnd = normalized.end;
|
|
1408
|
+
const kept = [];
|
|
1409
|
+
sameBucket.forEach((item) => {
|
|
1410
|
+
const overlap = !(item.end < mergedStart || item.start > mergedEnd);
|
|
1411
|
+
if (overlap) {
|
|
1412
|
+
mergedStart = Math.min(mergedStart, item.start);
|
|
1413
|
+
mergedEnd = Math.max(mergedEnd, item.end);
|
|
1414
|
+
}
|
|
1415
|
+
else {
|
|
1416
|
+
kept.push(item);
|
|
1417
|
+
}
|
|
1418
|
+
});
|
|
1419
|
+
return [
|
|
1420
|
+
...rest,
|
|
1421
|
+
...kept,
|
|
1422
|
+
{
|
|
1423
|
+
...draft,
|
|
1424
|
+
start: mergedStart,
|
|
1425
|
+
end: mergedEnd,
|
|
1426
|
+
},
|
|
1427
|
+
];
|
|
1428
|
+
};
|
|
1429
|
+
const mergeNoteRecords = (records, draft) => {
|
|
1430
|
+
const index = records.findIndex((item) => {
|
|
1431
|
+
return (item.pageId === draft.pageId &&
|
|
1432
|
+
item.start === draft.start &&
|
|
1433
|
+
item.end === draft.end);
|
|
1434
|
+
});
|
|
1435
|
+
if (index === -1) {
|
|
1436
|
+
return [...records, draft];
|
|
1437
|
+
}
|
|
1438
|
+
const next = [...records];
|
|
1439
|
+
const existing = next[index];
|
|
1440
|
+
if (!existing) {
|
|
1441
|
+
return [...records, draft];
|
|
1442
|
+
}
|
|
1443
|
+
next[index] = {
|
|
1444
|
+
...existing,
|
|
1445
|
+
...draft,
|
|
1446
|
+
id: existing.id || draft.id,
|
|
1447
|
+
updatedAt: new Date().toISOString(),
|
|
1448
|
+
};
|
|
1449
|
+
return next;
|
|
1450
|
+
};
|
|
1451
|
+
const summarizePreviewText = (text, fallback, maxLength = 52) => {
|
|
1452
|
+
const raw = String(text || "")
|
|
1453
|
+
.replace(/\s+/g, " ")
|
|
1454
|
+
.trim();
|
|
1455
|
+
if (!raw) {
|
|
1456
|
+
return fallback;
|
|
1457
|
+
}
|
|
1458
|
+
return raw.length > maxLength ? `${raw.slice(0, maxLength)}...` : raw;
|
|
1459
|
+
};
|
|
1460
|
+
const flashPreviewAnnotationTarget = (node) => {
|
|
1461
|
+
if (!node || !node.classList) {
|
|
1462
|
+
return;
|
|
1463
|
+
}
|
|
1464
|
+
node.classList.remove("hyewb-preview-annotation-flash");
|
|
1465
|
+
void node.offsetWidth;
|
|
1466
|
+
node.classList.add("hyewb-preview-annotation-flash");
|
|
1467
|
+
window.setTimeout(() => {
|
|
1468
|
+
node.classList.remove("hyewb-preview-annotation-flash");
|
|
1469
|
+
}, 900);
|
|
1470
|
+
};
|
|
1471
|
+
const focusPreviewAnnotationRecord = (record, kind) => {
|
|
1472
|
+
let target = null;
|
|
1473
|
+
if (kind === "note" && "id" in record && record.id) {
|
|
1474
|
+
const noteId = String(record.id);
|
|
1475
|
+
target = previewArea.querySelector(`mark[data-preview-annotation='note'][data-preview-note-id='${noteId.replace(/["\\]/g, "\\$&")}']`);
|
|
1476
|
+
}
|
|
1477
|
+
if (!target) {
|
|
1478
|
+
const range = createRangeFromOffsets(previewArea, record.start, record.end);
|
|
1479
|
+
if (range && !range.collapsed) {
|
|
1480
|
+
const node = range.startContainer;
|
|
1481
|
+
target =
|
|
1482
|
+
node.nodeType === Node.ELEMENT_NODE
|
|
1483
|
+
? node
|
|
1484
|
+
: node.parentElement;
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
if (!target ||
|
|
1488
|
+
typeof target.scrollIntoView !== "function") {
|
|
1489
|
+
return;
|
|
1490
|
+
}
|
|
1491
|
+
target.scrollIntoView({
|
|
1492
|
+
behavior: "smooth",
|
|
1493
|
+
block: "center",
|
|
1494
|
+
inline: "nearest",
|
|
1495
|
+
});
|
|
1496
|
+
flashPreviewAnnotationTarget(target);
|
|
1497
|
+
};
|
|
1498
|
+
const getPreviewAnnotationsByPage = () => {
|
|
1499
|
+
const pageId = getCurrentPageId();
|
|
1500
|
+
const annotations = normalizePreviewAnnotations(state.doc.meta.previewAnnotations);
|
|
1501
|
+
return {
|
|
1502
|
+
annotations,
|
|
1503
|
+
pageId,
|
|
1504
|
+
highlights: annotations.highlights.filter((item) => item.pageId === pageId),
|
|
1505
|
+
notes: annotations.notes.filter((item) => item.pageId === pageId),
|
|
1506
|
+
};
|
|
1507
|
+
};
|
|
1508
|
+
const renderAnnotationPanel = () => {
|
|
1509
|
+
const shouldShowPanel = state.mode === "preview" &&
|
|
1510
|
+
state.features.preview &&
|
|
1511
|
+
previewAnnotationOptions.showAnnotationList;
|
|
1512
|
+
annotationPanel.style.display = shouldShowPanel ? "grid" : "none";
|
|
1513
|
+
previewLayout.classList.toggle("with-annotation-panel", shouldShowPanel);
|
|
1514
|
+
if (!shouldShowPanel) {
|
|
1515
|
+
return;
|
|
1516
|
+
}
|
|
1517
|
+
const { highlights, notes } = getPreviewAnnotationsByPage();
|
|
1518
|
+
annotationHighlightTab.classList.toggle("active", annotationActiveTab === "highlights");
|
|
1519
|
+
annotationNoteTab.classList.toggle("active", annotationActiveTab === "notes");
|
|
1520
|
+
const activeList = annotationActiveTab === "highlights" ? highlights : notes;
|
|
1521
|
+
annotationList.innerHTML = "";
|
|
1522
|
+
if (!activeList.length) {
|
|
1523
|
+
annotationEmpty.style.display = "block";
|
|
1524
|
+
annotationEmpty.textContent =
|
|
1525
|
+
annotationActiveTab === "highlights"
|
|
1526
|
+
? "当前页暂无高亮"
|
|
1527
|
+
: "当前页暂无笔记";
|
|
1528
|
+
return;
|
|
1529
|
+
}
|
|
1530
|
+
annotationEmpty.style.display = "none";
|
|
1531
|
+
activeList.forEach((record, index) => {
|
|
1532
|
+
const item = document.createElement("li");
|
|
1533
|
+
const button = document.createElement("button");
|
|
1534
|
+
button.type = "button";
|
|
1535
|
+
button.className = "hyewb-preview-annotation-item";
|
|
1536
|
+
const heading = document.createElement("span");
|
|
1537
|
+
heading.className = "hyewb-preview-annotation-item-title";
|
|
1538
|
+
heading.textContent =
|
|
1539
|
+
annotationActiveTab === "highlights"
|
|
1540
|
+
? `高亮 ${index + 1}`
|
|
1541
|
+
: `笔记 ${index + 1}`;
|
|
1542
|
+
const body = document.createElement("span");
|
|
1543
|
+
body.className = "hyewb-preview-annotation-item-body";
|
|
1544
|
+
const fallbackRange = `[${record.start}, ${record.end}]`;
|
|
1545
|
+
body.textContent =
|
|
1546
|
+
annotationActiveTab === "highlights"
|
|
1547
|
+
? summarizePreviewText(record.selectedText, fallbackRange)
|
|
1548
|
+
: summarizePreviewText(record.text, "未命名笔记");
|
|
1549
|
+
button.append(heading, body);
|
|
1550
|
+
button.addEventListener("click", () => {
|
|
1551
|
+
focusPreviewAnnotationRecord(record, annotationActiveTab === "highlights" ? "highlight" : "note");
|
|
1552
|
+
});
|
|
1553
|
+
if (previewAnnotationOptions.annotationActions.canDelete) {
|
|
1554
|
+
const deleteButton = document.createElement("button");
|
|
1555
|
+
deleteButton.type = "button";
|
|
1556
|
+
deleteButton.className = "hyewb-preview-annotation-delete";
|
|
1557
|
+
deleteButton.title = "删除标注";
|
|
1558
|
+
deleteButton.setAttribute("aria-label", "删除标注");
|
|
1559
|
+
deleteButton.append(createIconPlaceholder("trash-2"));
|
|
1560
|
+
deleteButton.addEventListener("click", (event) => {
|
|
1561
|
+
event.preventDefault();
|
|
1562
|
+
event.stopPropagation();
|
|
1563
|
+
if (!window.confirm("确定删除这条标注吗?")) {
|
|
1564
|
+
return;
|
|
1565
|
+
}
|
|
1566
|
+
const current = normalizePreviewAnnotations(state.doc.meta.previewAnnotations);
|
|
1567
|
+
if (annotationActiveTab === "highlights") {
|
|
1568
|
+
current.highlights = current.highlights.filter((item) => {
|
|
1569
|
+
if ("id" in record && record.id && item.id) {
|
|
1570
|
+
return String(item.id) !== String(record.id);
|
|
1571
|
+
}
|
|
1572
|
+
return !(item.pageId === record.pageId &&
|
|
1573
|
+
item.start === record.start &&
|
|
1574
|
+
item.end === record.end);
|
|
1575
|
+
});
|
|
1576
|
+
}
|
|
1577
|
+
else {
|
|
1578
|
+
current.notes = current.notes.filter((item) => {
|
|
1579
|
+
if ("id" in record && record.id && item.id) {
|
|
1580
|
+
return String(item.id) !== String(record.id);
|
|
1581
|
+
}
|
|
1582
|
+
return !(item.pageId === record.pageId &&
|
|
1583
|
+
item.start === record.start &&
|
|
1584
|
+
item.end === record.end);
|
|
1585
|
+
});
|
|
1586
|
+
}
|
|
1587
|
+
savePreviewAnnotations(current);
|
|
1588
|
+
});
|
|
1589
|
+
button.append(deleteButton);
|
|
1590
|
+
}
|
|
1591
|
+
item.append(button);
|
|
1592
|
+
annotationList.append(item);
|
|
1593
|
+
});
|
|
1594
|
+
};
|
|
1595
|
+
const applyPreviewAnnotationsToView = () => {
|
|
1596
|
+
if (state.mode !== "preview") {
|
|
1597
|
+
previewSelectionToolbar.classList.remove("show");
|
|
1598
|
+
return;
|
|
1599
|
+
}
|
|
1600
|
+
const { highlights, notes } = getPreviewAnnotationsByPage();
|
|
1601
|
+
applyHighlightMarks(previewArea, highlights);
|
|
1602
|
+
applyNoteMarks(previewArea, notes);
|
|
1603
|
+
};
|
|
1604
|
+
const hidePreviewSelectionToolbar = () => {
|
|
1605
|
+
previewSelectionToolbar.classList.remove("show");
|
|
1606
|
+
previewSelectionDraft = null;
|
|
1607
|
+
};
|
|
1608
|
+
const syncPreviewSelectionToolbar = () => {
|
|
1609
|
+
if (!previewAnnotationOptions.enablePreviewSelectionToolbar ||
|
|
1610
|
+
state.mode !== "preview") {
|
|
1611
|
+
hidePreviewSelectionToolbar();
|
|
1612
|
+
return;
|
|
1613
|
+
}
|
|
1614
|
+
const selection = window.getSelection();
|
|
1615
|
+
if (!selection || selection.rangeCount === 0 || selection.isCollapsed) {
|
|
1616
|
+
hidePreviewSelectionToolbar();
|
|
1617
|
+
return;
|
|
1618
|
+
}
|
|
1619
|
+
const range = selection.getRangeAt(0);
|
|
1620
|
+
if (!previewArea.contains(range.startContainer) ||
|
|
1621
|
+
!previewArea.contains(range.endContainer)) {
|
|
1622
|
+
hidePreviewSelectionToolbar();
|
|
1623
|
+
return;
|
|
1624
|
+
}
|
|
1625
|
+
const offsets = getSelectionOffsets(previewArea, selection);
|
|
1626
|
+
if (!offsets) {
|
|
1627
|
+
hidePreviewSelectionToolbar();
|
|
1628
|
+
return;
|
|
1629
|
+
}
|
|
1630
|
+
const rect = range.getBoundingClientRect();
|
|
1631
|
+
if (!rect.width && !rect.height) {
|
|
1632
|
+
hidePreviewSelectionToolbar();
|
|
1633
|
+
return;
|
|
1634
|
+
}
|
|
1635
|
+
previewSelectionDraft = {
|
|
1636
|
+
start: offsets.start,
|
|
1637
|
+
end: offsets.end,
|
|
1638
|
+
pageId: getCurrentPageId(),
|
|
1639
|
+
text: selection.toString().trim(),
|
|
1640
|
+
};
|
|
1641
|
+
previewSelectionToolbar.style.left = `${Math.round(rect.left + rect.width / 2)}px`;
|
|
1642
|
+
previewSelectionToolbar.style.top = `${Math.round(rect.top - 8)}px`;
|
|
1643
|
+
previewSelectionToolbar.classList.add("show");
|
|
1644
|
+
};
|
|
1065
1645
|
const hideFloatingToolbar = () => {
|
|
1066
1646
|
floatingToolbar.classList.remove("show");
|
|
1067
1647
|
lastSelection = null;
|
|
@@ -1220,11 +1800,11 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
1220
1800
|
}
|
|
1221
1801
|
cancelTableToolsHide();
|
|
1222
1802
|
const tableRect = activeTableElement.getBoundingClientRect();
|
|
1223
|
-
tableMoveHandle.style.left = `${Math.round(tableRect.left -
|
|
1224
|
-
tableMoveHandle.style.top = `${Math.round(tableRect.top -
|
|
1803
|
+
tableMoveHandle.style.left = `${Math.round(tableRect.left - 14)}px`;
|
|
1804
|
+
tableMoveHandle.style.top = `${Math.round(tableRect.top - 14)}px`;
|
|
1225
1805
|
tableMoveHandle.classList.add("show");
|
|
1226
|
-
tableScaleHandle.style.left = `${Math.round(tableRect.right -
|
|
1227
|
-
tableScaleHandle.style.top = `${Math.round(tableRect.bottom -
|
|
1806
|
+
tableScaleHandle.style.left = `${Math.round(tableRect.right - 10)}px`;
|
|
1807
|
+
tableScaleHandle.style.top = `${Math.round(tableRect.bottom - 10)}px`;
|
|
1228
1808
|
tableScaleHandle.classList.add("show");
|
|
1229
1809
|
tableColEdgeLayer.style.left = `${Math.round(tableRect.left)}px`;
|
|
1230
1810
|
tableColEdgeLayer.style.top = `${Math.round(tableRect.top - 12)}px`;
|
|
@@ -1240,7 +1820,7 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
1240
1820
|
if (activeTableRowElement) {
|
|
1241
1821
|
const rowRect = activeTableRowElement.getBoundingClientRect();
|
|
1242
1822
|
tableRowDeleteBtn.style.left = `${Math.round(rowRect.right - 2)}px`;
|
|
1243
|
-
tableRowDeleteBtn.style.top = `${Math.round(rowRect.top + rowRect.height / 2 -
|
|
1823
|
+
tableRowDeleteBtn.style.top = `${Math.round(rowRect.top + rowRect.height / 2 - 10)}px`;
|
|
1244
1824
|
tableRowDeleteBtn.classList.add("show");
|
|
1245
1825
|
}
|
|
1246
1826
|
else {
|
|
@@ -1587,8 +2167,8 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
1587
2167
|
return best;
|
|
1588
2168
|
};
|
|
1589
2169
|
const updateGapInsertButton = (hover) => {
|
|
1590
|
-
const rowGapOffset = { x: -
|
|
1591
|
-
const colGapOffset = { x: -
|
|
2170
|
+
const rowGapOffset = { x: -1, y: -9 };
|
|
2171
|
+
const colGapOffset = { x: -9, y: -1 };
|
|
1592
2172
|
tableGapHover = hover;
|
|
1593
2173
|
if (!hover || state.mode !== "editor") {
|
|
1594
2174
|
tableRowGapInsertBtn.classList.remove("show");
|
|
@@ -1847,6 +2427,119 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
1847
2427
|
rememberedParagraphIndex = index;
|
|
1848
2428
|
}
|
|
1849
2429
|
};
|
|
2430
|
+
const normalizeVerticalAlignValue = (value) => {
|
|
2431
|
+
return String(value || "")
|
|
2432
|
+
.trim()
|
|
2433
|
+
.toLowerCase();
|
|
2434
|
+
};
|
|
2435
|
+
const detectScriptMarkFromElement = (element) => {
|
|
2436
|
+
let cursor = element;
|
|
2437
|
+
while (cursor && cursor !== editorArea) {
|
|
2438
|
+
const tagName = cursor.tagName.toLowerCase();
|
|
2439
|
+
if (tagName === "sup") {
|
|
2440
|
+
return "superscript";
|
|
2441
|
+
}
|
|
2442
|
+
if (tagName === "sub") {
|
|
2443
|
+
return "subscript";
|
|
2444
|
+
}
|
|
2445
|
+
const inlineAlign = normalizeVerticalAlignValue(cursor.style?.verticalAlign);
|
|
2446
|
+
if (inlineAlign === "super") {
|
|
2447
|
+
return "superscript";
|
|
2448
|
+
}
|
|
2449
|
+
if (inlineAlign === "sub") {
|
|
2450
|
+
return "subscript";
|
|
2451
|
+
}
|
|
2452
|
+
cursor = cursor.parentElement;
|
|
2453
|
+
}
|
|
2454
|
+
return null;
|
|
2455
|
+
};
|
|
2456
|
+
const doesRangeIntersectNode = (range, node) => {
|
|
2457
|
+
try {
|
|
2458
|
+
return range.intersectsNode(node);
|
|
2459
|
+
}
|
|
2460
|
+
catch {
|
|
2461
|
+
return false;
|
|
2462
|
+
}
|
|
2463
|
+
};
|
|
2464
|
+
const resolveScriptStateFromRange = (range) => {
|
|
2465
|
+
if (!range) {
|
|
2466
|
+
return { superscript: false, subscript: false };
|
|
2467
|
+
}
|
|
2468
|
+
const detectFromContainer = (container) => {
|
|
2469
|
+
const element = container.nodeType === Node.ELEMENT_NODE
|
|
2470
|
+
? container
|
|
2471
|
+
: container.parentElement;
|
|
2472
|
+
return detectScriptMarkFromElement(element);
|
|
2473
|
+
};
|
|
2474
|
+
const fromStart = detectFromContainer(range.startContainer);
|
|
2475
|
+
const fromEnd = detectFromContainer(range.endContainer);
|
|
2476
|
+
const mark = fromStart || fromEnd;
|
|
2477
|
+
return {
|
|
2478
|
+
superscript: mark === "superscript",
|
|
2479
|
+
subscript: mark === "subscript",
|
|
2480
|
+
};
|
|
2481
|
+
};
|
|
2482
|
+
const getActiveEditorRange = () => {
|
|
2483
|
+
const selection = window.getSelection();
|
|
2484
|
+
if (selection &&
|
|
2485
|
+
selection.rangeCount > 0 &&
|
|
2486
|
+
editorArea.contains(selection.getRangeAt(0).startContainer) &&
|
|
2487
|
+
editorArea.contains(selection.getRangeAt(0).endContainer)) {
|
|
2488
|
+
return selection.getRangeAt(0);
|
|
2489
|
+
}
|
|
2490
|
+
return rememberedRange;
|
|
2491
|
+
};
|
|
2492
|
+
const clearScriptMarkInRange = (range, command) => {
|
|
2493
|
+
const selector = command === "superscript"
|
|
2494
|
+
? 'sup,span[style*="vertical-align: super"],span[style*="vertical-align:super"]'
|
|
2495
|
+
: 'sub,span[style*="vertical-align: sub"],span[style*="vertical-align:sub"]';
|
|
2496
|
+
const rootNode = range.commonAncestorContainer.nodeType === Node.ELEMENT_NODE
|
|
2497
|
+
? range.commonAncestorContainer
|
|
2498
|
+
: range.commonAncestorContainer.parentElement;
|
|
2499
|
+
if (!rootNode) {
|
|
2500
|
+
return;
|
|
2501
|
+
}
|
|
2502
|
+
const candidateSet = new Set();
|
|
2503
|
+
const addIfMatches = (element) => {
|
|
2504
|
+
let cursor = element;
|
|
2505
|
+
while (cursor && cursor !== editorArea) {
|
|
2506
|
+
if (cursor.matches(selector) && doesRangeIntersectNode(range, cursor)) {
|
|
2507
|
+
candidateSet.add(cursor);
|
|
2508
|
+
}
|
|
2509
|
+
cursor = cursor.parentElement;
|
|
2510
|
+
}
|
|
2511
|
+
};
|
|
2512
|
+
addIfMatches(range.startContainer.nodeType === Node.ELEMENT_NODE
|
|
2513
|
+
? range.startContainer
|
|
2514
|
+
: range.startContainer.parentElement);
|
|
2515
|
+
addIfMatches(range.endContainer.nodeType === Node.ELEMENT_NODE
|
|
2516
|
+
? range.endContainer
|
|
2517
|
+
: range.endContainer.parentElement);
|
|
2518
|
+
rootNode.querySelectorAll(selector).forEach((node) => {
|
|
2519
|
+
if (doesRangeIntersectNode(range, node)) {
|
|
2520
|
+
candidateSet.add(node);
|
|
2521
|
+
}
|
|
2522
|
+
});
|
|
2523
|
+
Array.from(candidateSet).forEach((element) => {
|
|
2524
|
+
const tagName = element.tagName.toLowerCase();
|
|
2525
|
+
if (tagName === "sup" || tagName === "sub") {
|
|
2526
|
+
const parent = element.parentNode;
|
|
2527
|
+
if (!parent) {
|
|
2528
|
+
return;
|
|
2529
|
+
}
|
|
2530
|
+
while (element.firstChild) {
|
|
2531
|
+
parent.insertBefore(element.firstChild, element);
|
|
2532
|
+
}
|
|
2533
|
+
parent.removeChild(element);
|
|
2534
|
+
return;
|
|
2535
|
+
}
|
|
2536
|
+
element.style.removeProperty("vertical-align");
|
|
2537
|
+
element.style.removeProperty("top");
|
|
2538
|
+
if (!element.getAttribute("style")?.trim()) {
|
|
2539
|
+
element.removeAttribute("style");
|
|
2540
|
+
}
|
|
2541
|
+
});
|
|
2542
|
+
};
|
|
1850
2543
|
const syncToolbarState = () => {
|
|
1851
2544
|
if (!state.features.textToolbar || state.mode !== "editor") {
|
|
1852
2545
|
return;
|
|
@@ -1874,11 +2567,14 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
1874
2567
|
const strikeActive = canReflect
|
|
1875
2568
|
? safeQueryCommandState("strikeThrough")
|
|
1876
2569
|
: false;
|
|
2570
|
+
const scriptState = canReflect
|
|
2571
|
+
? resolveScriptStateFromRange(getActiveEditorRange())
|
|
2572
|
+
: { superscript: false, subscript: false };
|
|
1877
2573
|
const superscriptActive = canReflect
|
|
1878
|
-
? safeQueryCommandState("superscript")
|
|
2574
|
+
? safeQueryCommandState("superscript") || scriptState.superscript
|
|
1879
2575
|
: false;
|
|
1880
2576
|
const subscriptActive = canReflect
|
|
1881
|
-
? safeQueryCommandState("subscript")
|
|
2577
|
+
? safeQueryCommandState("subscript") || scriptState.subscript
|
|
1882
2578
|
: false;
|
|
1883
2579
|
[boldBtn, floatBoldBtn].forEach((btn) => setButtonActive(btn, boldActive));
|
|
1884
2580
|
[italicBtn, floatItalicBtn].forEach((btn) => setButtonActive(btn, italicActive));
|
|
@@ -2071,6 +2767,26 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
2071
2767
|
syncToolbarState();
|
|
2072
2768
|
updateFloatingToolbarBySelection();
|
|
2073
2769
|
};
|
|
2770
|
+
const toggleScriptMark = (command, activeMessage) => {
|
|
2771
|
+
withSelectionCommand(() => {
|
|
2772
|
+
const opposite = command === "superscript" ? "subscript" : "superscript";
|
|
2773
|
+
const activeRange = getActiveEditorRange();
|
|
2774
|
+
const currentScriptState = resolveScriptStateFromRange(activeRange);
|
|
2775
|
+
const wasActive = command === "superscript"
|
|
2776
|
+
? currentScriptState.superscript
|
|
2777
|
+
: currentScriptState.subscript;
|
|
2778
|
+
if (activeRange) {
|
|
2779
|
+
clearScriptMarkInRange(activeRange, opposite);
|
|
2780
|
+
}
|
|
2781
|
+
if (wasActive) {
|
|
2782
|
+
if (activeRange) {
|
|
2783
|
+
clearScriptMarkInRange(activeRange, command);
|
|
2784
|
+
}
|
|
2785
|
+
return;
|
|
2786
|
+
}
|
|
2787
|
+
document.execCommand(command, false);
|
|
2788
|
+
}, activeMessage);
|
|
2789
|
+
};
|
|
2074
2790
|
const applyColorFromPalette = (color) => {
|
|
2075
2791
|
if (!activeColorTarget) {
|
|
2076
2792
|
return;
|
|
@@ -2626,7 +3342,14 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
2626
3342
|
selectInlineImage(null);
|
|
2627
3343
|
rememberedParagraphIndex = null;
|
|
2628
3344
|
}
|
|
2629
|
-
|
|
3345
|
+
if (state.mode === "preview") {
|
|
3346
|
+
canvas.style.width = "100%";
|
|
3347
|
+
canvas.style.maxWidth = `${paperWidth}px`;
|
|
3348
|
+
}
|
|
3349
|
+
else {
|
|
3350
|
+
canvas.style.width = `${paperWidth}px`;
|
|
3351
|
+
canvas.style.maxWidth = "100%";
|
|
3352
|
+
}
|
|
2630
3353
|
previewArea.innerHTML = html;
|
|
2631
3354
|
previewArea.classList.toggle("show", state.mode === "preview");
|
|
2632
3355
|
editorArea.style.display = state.mode === "editor" ? "block" : "none";
|
|
@@ -2719,6 +3442,9 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
2719
3442
|
});
|
|
2720
3443
|
updateInlineResizeOverlay();
|
|
2721
3444
|
syncToolbarState();
|
|
3445
|
+
applyPreviewAnnotationsToView();
|
|
3446
|
+
renderAnnotationPanel();
|
|
3447
|
+
syncPreviewSelectionToolbar();
|
|
2722
3448
|
};
|
|
2723
3449
|
boldBtn.addEventListener("click", () => {
|
|
2724
3450
|
withSelectionCommand(() => {
|
|
@@ -2741,14 +3467,10 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
2741
3467
|
}, "已应用删除线");
|
|
2742
3468
|
});
|
|
2743
3469
|
superscriptBtn.addEventListener("click", () => {
|
|
2744
|
-
|
|
2745
|
-
document.execCommand("superscript", false);
|
|
2746
|
-
}, "已应用上角标");
|
|
3470
|
+
toggleScriptMark("superscript", "已切换上角标");
|
|
2747
3471
|
});
|
|
2748
3472
|
subscriptBtn.addEventListener("click", () => {
|
|
2749
|
-
|
|
2750
|
-
document.execCommand("subscript", false);
|
|
2751
|
-
}, "已应用下角标");
|
|
3473
|
+
toggleScriptMark("subscript", "已切换下角标");
|
|
2752
3474
|
});
|
|
2753
3475
|
headingSelect.addEventListener("change", () => {
|
|
2754
3476
|
const value = headingSelect.value === "h1" ||
|
|
@@ -2823,6 +3545,12 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
2823
3545
|
}, 140);
|
|
2824
3546
|
};
|
|
2825
3547
|
[
|
|
3548
|
+
boldBtn,
|
|
3549
|
+
italicBtn,
|
|
3550
|
+
underlineBtn,
|
|
3551
|
+
strikeBtn,
|
|
3552
|
+
superscriptBtn,
|
|
3553
|
+
subscriptBtn,
|
|
2826
3554
|
floatBoldBtn,
|
|
2827
3555
|
floatItalicBtn,
|
|
2828
3556
|
floatUnderlineBtn,
|
|
@@ -2886,14 +3614,10 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
2886
3614
|
}, "已应用删除线");
|
|
2887
3615
|
});
|
|
2888
3616
|
floatSuperscriptBtn.addEventListener("click", () => {
|
|
2889
|
-
|
|
2890
|
-
document.execCommand("superscript", false);
|
|
2891
|
-
}, "已应用上角标");
|
|
3617
|
+
toggleScriptMark("superscript", "已切换上角标");
|
|
2892
3618
|
});
|
|
2893
3619
|
floatSubscriptBtn.addEventListener("click", () => {
|
|
2894
|
-
|
|
2895
|
-
document.execCommand("subscript", false);
|
|
2896
|
-
}, "已应用下角标");
|
|
3620
|
+
toggleScriptMark("subscript", "已切换下角标");
|
|
2897
3621
|
});
|
|
2898
3622
|
floatFontSizeSelect.addEventListener("change", () => {
|
|
2899
3623
|
applyFontSize(floatFontSizeSelect.value);
|
|
@@ -2911,6 +3635,59 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
2911
3635
|
floatBgColorInput.addEventListener("click", () => {
|
|
2912
3636
|
openColorPalette(floatBgColorInput, "background");
|
|
2913
3637
|
});
|
|
3638
|
+
annotationHighlightTab.addEventListener("click", () => {
|
|
3639
|
+
annotationActiveTab = "highlights";
|
|
3640
|
+
renderAnnotationPanel();
|
|
3641
|
+
});
|
|
3642
|
+
annotationNoteTab.addEventListener("click", () => {
|
|
3643
|
+
annotationActiveTab = "notes";
|
|
3644
|
+
renderAnnotationPanel();
|
|
3645
|
+
});
|
|
3646
|
+
previewHighlightBtn.addEventListener("click", () => {
|
|
3647
|
+
if (!previewSelectionDraft) {
|
|
3648
|
+
return;
|
|
3649
|
+
}
|
|
3650
|
+
const current = normalizePreviewAnnotations(state.doc.meta.previewAnnotations);
|
|
3651
|
+
current.highlights = mergeHighlightRecords(current.highlights, {
|
|
3652
|
+
id: `hl-${Date.now()}-${Math.round(Math.random() * 10000)}`,
|
|
3653
|
+
pageId: previewSelectionDraft.pageId,
|
|
3654
|
+
blockId: "preview-flow-text",
|
|
3655
|
+
start: previewSelectionDraft.start,
|
|
3656
|
+
end: previewSelectionDraft.end,
|
|
3657
|
+
color: "#fff59d",
|
|
3658
|
+
selectedText: previewSelectionDraft.text,
|
|
3659
|
+
createdAt: new Date().toISOString(),
|
|
3660
|
+
});
|
|
3661
|
+
annotationActiveTab = "highlights";
|
|
3662
|
+
savePreviewAnnotations(current);
|
|
3663
|
+
window.getSelection()?.removeAllRanges();
|
|
3664
|
+
hidePreviewSelectionToolbar();
|
|
3665
|
+
});
|
|
3666
|
+
previewNoteBtn.addEventListener("click", () => {
|
|
3667
|
+
if (!previewSelectionDraft) {
|
|
3668
|
+
return;
|
|
3669
|
+
}
|
|
3670
|
+
const text = window.prompt("请输入笔记内容", previewSelectionDraft.text || "") || "";
|
|
3671
|
+
const noteText = text.trim();
|
|
3672
|
+
if (!noteText) {
|
|
3673
|
+
return;
|
|
3674
|
+
}
|
|
3675
|
+
const current = normalizePreviewAnnotations(state.doc.meta.previewAnnotations);
|
|
3676
|
+
current.notes = mergeNoteRecords(current.notes, {
|
|
3677
|
+
id: `note-${Date.now()}-${Math.round(Math.random() * 10000)}`,
|
|
3678
|
+
pageId: previewSelectionDraft.pageId,
|
|
3679
|
+
start: previewSelectionDraft.start,
|
|
3680
|
+
end: previewSelectionDraft.end,
|
|
3681
|
+
text: noteText,
|
|
3682
|
+
selectedText: previewSelectionDraft.text,
|
|
3683
|
+
color: "#0e7490",
|
|
3684
|
+
createdAt: new Date().toISOString(),
|
|
3685
|
+
});
|
|
3686
|
+
annotationActiveTab = "notes";
|
|
3687
|
+
savePreviewAnnotations(current);
|
|
3688
|
+
window.getSelection()?.removeAllRanges();
|
|
3689
|
+
hidePreviewSelectionToolbar();
|
|
3690
|
+
});
|
|
2914
3691
|
floatLeftBtn.addEventListener("click", () => updateAlign("left"));
|
|
2915
3692
|
floatCenterBtn.addEventListener("click", () => updateAlign("center"));
|
|
2916
3693
|
floatRightBtn.addEventListener("click", () => updateAlign("right"));
|
|
@@ -3537,12 +4314,14 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
3537
4314
|
rememberActiveParagraphIndex();
|
|
3538
4315
|
updateInlineResizeOverlay();
|
|
3539
4316
|
updateFloatingToolbarBySelection();
|
|
4317
|
+
syncToolbarState();
|
|
3540
4318
|
syncFocusedTableControls();
|
|
3541
4319
|
});
|
|
3542
4320
|
editorArea.addEventListener("keyup", () => {
|
|
3543
4321
|
rememberActiveParagraphIndex();
|
|
3544
4322
|
updateInlineResizeOverlay();
|
|
3545
4323
|
updateFloatingToolbarBySelection();
|
|
4324
|
+
syncToolbarState();
|
|
3546
4325
|
syncFocusedTableControls();
|
|
3547
4326
|
});
|
|
3548
4327
|
editorArea.addEventListener("blur", () => {
|
|
@@ -3563,20 +4342,25 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
3563
4342
|
updateInlineResizeOverlay();
|
|
3564
4343
|
syncToolbarState();
|
|
3565
4344
|
syncFocusedTableControls();
|
|
4345
|
+
syncPreviewSelectionToolbar();
|
|
3566
4346
|
};
|
|
3567
4347
|
const handleWindowResize = () => {
|
|
4348
|
+
updateShellViewportHeight();
|
|
3568
4349
|
updateInlineResizeOverlay();
|
|
3569
4350
|
syncTableToolsPosition();
|
|
3570
4351
|
syncFocusedTableControls();
|
|
4352
|
+
syncPreviewSelectionToolbar();
|
|
3571
4353
|
if (tablePicker.classList.contains("show")) {
|
|
3572
4354
|
showTablePicker();
|
|
3573
4355
|
}
|
|
3574
4356
|
};
|
|
3575
4357
|
const handleWindowScroll = () => {
|
|
4358
|
+
updateShellViewportHeight();
|
|
3576
4359
|
updateInlineResizeOverlay();
|
|
3577
4360
|
updateFloatingToolbarBySelection();
|
|
3578
4361
|
syncTableToolsPosition();
|
|
3579
4362
|
syncFocusedTableControls();
|
|
4363
|
+
syncPreviewSelectionToolbar();
|
|
3580
4364
|
if (tablePicker.classList.contains("show")) {
|
|
3581
4365
|
showTablePicker();
|
|
3582
4366
|
}
|
|
@@ -3592,6 +4376,18 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
3592
4376
|
};
|
|
3593
4377
|
window.addEventListener("resize", handleWindowResize);
|
|
3594
4378
|
window.addEventListener("scroll", handleWindowScroll, true);
|
|
4379
|
+
const handleFullscreenChange = () => {
|
|
4380
|
+
window.requestAnimationFrame(() => {
|
|
4381
|
+
updateFullscreenButtonState();
|
|
4382
|
+
updateShellViewportHeight();
|
|
4383
|
+
updateInlineResizeOverlay();
|
|
4384
|
+
syncTableToolsPosition();
|
|
4385
|
+
syncFocusedTableControls();
|
|
4386
|
+
syncPreviewSelectionToolbar();
|
|
4387
|
+
});
|
|
4388
|
+
};
|
|
4389
|
+
document.addEventListener("fullscreenchange", handleFullscreenChange);
|
|
4390
|
+
document.addEventListener("webkitfullscreenchange", handleFullscreenChange);
|
|
3595
4391
|
document.addEventListener("selectionchange", handleSelectionChange);
|
|
3596
4392
|
const handleDocumentPointerDownForPalette = (event) => {
|
|
3597
4393
|
const clickTarget = event.target;
|
|
@@ -3663,6 +4459,9 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
3663
4459
|
};
|
|
3664
4460
|
document.addEventListener("pointerdown", handleDocumentPointerDownForPalette);
|
|
3665
4461
|
document.addEventListener("keydown", handleDocumentKeyDown);
|
|
4462
|
+
fullscreenBtn.addEventListener("click", () => {
|
|
4463
|
+
void toggleWorkbenchFullscreen();
|
|
4464
|
+
});
|
|
3666
4465
|
tableAddBtn.addEventListener("mousedown", preserveSelectionForInputControl);
|
|
3667
4466
|
videoAddBtn.addEventListener("mousedown", preserveSelectionForInputControl);
|
|
3668
4467
|
videoAddBtn.addEventListener("click", () => {
|
|
@@ -3742,6 +4541,8 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
3742
4541
|
nextPageBtn.addEventListener("click", () => jumpPage(1));
|
|
3743
4542
|
addPageBtn.addEventListener("click", addPage);
|
|
3744
4543
|
render();
|
|
4544
|
+
updateFullscreenButtonState();
|
|
4545
|
+
updateShellViewportHeight();
|
|
3745
4546
|
syncToolbarState();
|
|
3746
4547
|
emitDocumentChange();
|
|
3747
4548
|
return {
|
|
@@ -3755,6 +4556,8 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
3755
4556
|
window.removeEventListener("scroll", handleWindowScroll, true);
|
|
3756
4557
|
document.removeEventListener("pointerdown", handleDocumentPointerDownForPalette);
|
|
3757
4558
|
document.removeEventListener("keydown", handleDocumentKeyDown);
|
|
4559
|
+
document.removeEventListener("fullscreenchange", handleFullscreenChange);
|
|
4560
|
+
document.removeEventListener("webkitfullscreenchange", handleFullscreenChange);
|
|
3758
4561
|
container.innerHTML = "";
|
|
3759
4562
|
},
|
|
3760
4563
|
getDocument: () => clone(state.doc),
|
|
@@ -4593,7 +5396,7 @@ function resolveMammothModule(namespace) {
|
|
|
4593
5396
|
const candidate = namespace?.default ?? namespace;
|
|
4594
5397
|
return candidate;
|
|
4595
5398
|
}
|
|
4596
|
-
async function parseDocxFlowBlocksFromXml(arrayBuffer) {
|
|
5399
|
+
async function parseDocxFlowBlocksFromXml(arrayBuffer, maxFlowBlockWidth) {
|
|
4597
5400
|
try {
|
|
4598
5401
|
const archive = await loadDocxArchive(arrayBuffer);
|
|
4599
5402
|
if (!archive) {
|
|
@@ -4609,7 +5412,7 @@ async function parseDocxFlowBlocksFromXml(arrayBuffer) {
|
|
|
4609
5412
|
const themeXml = await archive
|
|
4610
5413
|
.file("word/theme/theme1.xml")
|
|
4611
5414
|
?.async("string");
|
|
4612
|
-
return parseDocxBodyToFlowBlocks(documentXml, stylesXml, themeXml);
|
|
5415
|
+
return parseDocxBodyToFlowBlocks(documentXml, stylesXml, themeXml, maxFlowBlockWidth);
|
|
4613
5416
|
}
|
|
4614
5417
|
catch {
|
|
4615
5418
|
return undefined;
|
|
@@ -4623,7 +5426,7 @@ async function loadDocxArchive(arrayBuffer) {
|
|
|
4623
5426
|
}
|
|
4624
5427
|
return zipRuntime.loadAsync(arrayBuffer);
|
|
4625
5428
|
}
|
|
4626
|
-
function parseDocxBodyToFlowBlocks(documentXml, stylesXml, themeXml) {
|
|
5429
|
+
function parseDocxBodyToFlowBlocks(documentXml, stylesXml, themeXml, maxFlowBlockWidth) {
|
|
4627
5430
|
const parser = new DOMParser();
|
|
4628
5431
|
const documentDoc = parser.parseFromString(documentXml, "application/xml");
|
|
4629
5432
|
const body = findDescendantByLocalName(documentDoc.documentElement, "body");
|
|
@@ -4642,7 +5445,7 @@ function parseDocxBodyToFlowBlocks(documentXml, stylesXml, themeXml) {
|
|
|
4642
5445
|
continue;
|
|
4643
5446
|
}
|
|
4644
5447
|
if (name === "tbl") {
|
|
4645
|
-
blocks.push(parseDocxTableNode(child, index, styleContext));
|
|
5448
|
+
blocks.push(parseDocxTableNode(child, index, styleContext, maxFlowBlockWidth));
|
|
4646
5449
|
index += 1;
|
|
4647
5450
|
}
|
|
4648
5451
|
}
|
|
@@ -4974,11 +5777,11 @@ function mergeTextMarks(...sources) {
|
|
|
4974
5777
|
}
|
|
4975
5778
|
return merged;
|
|
4976
5779
|
}
|
|
4977
|
-
function parseDocxTableNode(tableNode, index, styleContext) {
|
|
5780
|
+
function parseDocxTableNode(tableNode, index, styleContext, maxFlowBlockWidth) {
|
|
4978
5781
|
const tableProps = childXmlNodeByLocalName(tableNode, "tblPr");
|
|
4979
5782
|
const tableStyleId = xmlAttribute(childXmlNodeByLocalName(tableProps, "tblStyle"), "val");
|
|
4980
5783
|
const tableTextStyle = resolveDocxStyle(styleContext, tableStyleId, "table");
|
|
4981
|
-
const
|
|
5784
|
+
const tableStyleInfo = resolveDocxTableBlockStyle(tableProps, styleContext.themeColorMap, maxFlowBlockWidth);
|
|
4982
5785
|
const tableBorders = resolveDocxTableBorderSet(tableProps, styleContext.themeColorMap);
|
|
4983
5786
|
const rowNodes = Array.from(tableNode.children).filter((node) => {
|
|
4984
5787
|
return xmlLocalName(node) === "tr";
|
|
@@ -5070,12 +5873,15 @@ function parseDocxTableNode(tableNode, index, styleContext) {
|
|
|
5070
5873
|
cells,
|
|
5071
5874
|
};
|
|
5072
5875
|
});
|
|
5876
|
+
const tableWidth = tableStyleInfo.widthPx ??
|
|
5877
|
+
resolveFlowBlockWidthWithinBounds(maxFlowBlockWidth, DEFAULT_FLOW_BLOCK_WIDTH) ??
|
|
5878
|
+
DEFAULT_FLOW_BLOCK_WIDTH;
|
|
5073
5879
|
return {
|
|
5074
5880
|
id: `table-${Date.now()}-${index}`,
|
|
5075
5881
|
type: "table",
|
|
5076
|
-
rect: { x: 80, y: 80 + index * 24, width:
|
|
5882
|
+
rect: { x: 80, y: 80 + index * 24, width: tableWidth, height: 120 },
|
|
5077
5883
|
zIndex: index + 1,
|
|
5078
|
-
...(
|
|
5884
|
+
...(tableStyleInfo.style ? { style: tableStyleInfo.style } : {}),
|
|
5079
5885
|
rows: rows.length
|
|
5080
5886
|
? rows
|
|
5081
5887
|
: [
|
|
@@ -5110,9 +5916,9 @@ function resolvePrimaryTextStyleFromParagraphs(paragraphs) {
|
|
|
5110
5916
|
}
|
|
5111
5917
|
return undefined;
|
|
5112
5918
|
}
|
|
5113
|
-
function resolveDocxTableBlockStyle(tableProps, themeColorMap) {
|
|
5919
|
+
function resolveDocxTableBlockStyle(tableProps, themeColorMap, maxFlowBlockWidth) {
|
|
5114
5920
|
const borders = childXmlNodeByLocalName(tableProps, "tblBorders");
|
|
5115
|
-
const tableWidth = resolveDocxTableWidthPx(tableProps);
|
|
5921
|
+
const tableWidth = resolveFlowBlockWidthWithinBounds(maxFlowBlockWidth, resolveDocxTableWidthPx(tableProps));
|
|
5116
5922
|
const styleTokens = ["border-collapse:collapse"];
|
|
5117
5923
|
const borderSides = [
|
|
5118
5924
|
"top",
|
|
@@ -5132,7 +5938,36 @@ function resolveDocxTableBlockStyle(tableProps, themeColorMap) {
|
|
|
5132
5938
|
if (tableWidth !== undefined) {
|
|
5133
5939
|
styleTokens.push(`width:${tableWidth}px`);
|
|
5134
5940
|
}
|
|
5135
|
-
return
|
|
5941
|
+
return {
|
|
5942
|
+
style: styleTokens.join(";"),
|
|
5943
|
+
widthPx: tableWidth,
|
|
5944
|
+
};
|
|
5945
|
+
}
|
|
5946
|
+
function resolveFlowBlockWidthWithinBounds(maxWidth, preferredWidth) {
|
|
5947
|
+
const safeMax = Number.isFinite(maxWidth) && Number(maxWidth) > 0
|
|
5948
|
+
? Math.max(1, Math.round(Number(maxWidth)))
|
|
5949
|
+
: undefined;
|
|
5950
|
+
const safePreferred = Number.isFinite(preferredWidth) && Number(preferredWidth) > 0
|
|
5951
|
+
? Math.max(1, Math.round(Number(preferredWidth)))
|
|
5952
|
+
: undefined;
|
|
5953
|
+
if (safeMax === undefined) {
|
|
5954
|
+
return safePreferred;
|
|
5955
|
+
}
|
|
5956
|
+
if (safePreferred === undefined) {
|
|
5957
|
+
return safeMax;
|
|
5958
|
+
}
|
|
5959
|
+
return Math.min(safePreferred, safeMax);
|
|
5960
|
+
}
|
|
5961
|
+
function resolveDocxImportMaxFlowBlockWidth(page, fallbackPaperWidth) {
|
|
5962
|
+
const pageWidth = resolvePaperWidth(page.width, fallbackPaperWidth);
|
|
5963
|
+
const marginLeft = Number.isFinite(page.marginLeft)
|
|
5964
|
+
? Math.max(0, page.marginLeft)
|
|
5965
|
+
: 0;
|
|
5966
|
+
const marginRight = Number.isFinite(page.marginRight)
|
|
5967
|
+
? Math.max(0, page.marginRight)
|
|
5968
|
+
: 0;
|
|
5969
|
+
const availableWidth = Math.max(240, pageWidth - marginLeft - marginRight);
|
|
5970
|
+
return Math.min(DEFAULT_FLOW_BLOCK_WIDTH, availableWidth);
|
|
5136
5971
|
}
|
|
5137
5972
|
function resolveDocxTableCellStyle(cellProps, themeColorMap, rowHeight, tableBorders, gridPos) {
|
|
5138
5973
|
if (!cellProps) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyebook/vue3-adapter",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
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.
|
|
20
|
+
"@hyebook/core": "^0.2.2"
|
|
21
21
|
},
|
|
22
22
|
"scripts": {
|
|
23
23
|
"build": "tsc -p tsconfig.json",
|