@hyebook/vue3-adapter 2.2.7 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/src/index.d.ts +1 -0
- package/dist/core/src/index.d.ts.map +1 -1
- package/dist/core/src/index.js +1 -0
- package/dist/core/src/player/ebook-player.d.ts +65 -0
- package/dist/core/src/player/ebook-player.d.ts.map +1 -0
- package/dist/core/src/player/ebook-player.js +550 -0
- package/dist/core/src/player/engine.d.ts +1 -0
- package/dist/core/src/player/engine.d.ts.map +1 -1
- package/dist/core/src/player/engine.js +57 -7
- package/dist/core/src/types/player.d.ts +34 -0
- package/dist/core/src/types/player.d.ts.map +1 -1
- package/dist/core/src/workbench/editor-workbench.d.ts +28 -0
- package/dist/core/src/workbench/editor-workbench.d.ts.map +1 -1
- package/dist/core/src/workbench/editor-workbench.js +167 -16
- package/dist/vue3-adapter/src/index.d.ts +4 -1
- package/dist/vue3-adapter/src/index.d.ts.map +1 -1
- package/dist/vue3-adapter/src/index.js +4 -1
- package/package.json +2 -2
package/dist/core/src/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../core/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../core/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC"}
|
package/dist/core/src/index.js
CHANGED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { EbookDoc } from "../types/ebook";
|
|
2
|
+
import type { EBookPlayerHandle, EBookPlayerOptions, ReaderAnnotationChangeSource, ReaderAnnotationCreateEvent, ReaderAnnotationDeleteEvent, ReaderAnnotations, ReaderAnnotationsChangeEvent, ReaderAnnotationUpdateEvent, ReaderHighlight, ReaderNote } from "../types/player";
|
|
3
|
+
export declare class EBookPlayer implements EBookPlayerHandle {
|
|
4
|
+
private container;
|
|
5
|
+
private options;
|
|
6
|
+
private engine;
|
|
7
|
+
private root;
|
|
8
|
+
private content;
|
|
9
|
+
private selectionToolbar;
|
|
10
|
+
private highlightBtn;
|
|
11
|
+
private noteBtn;
|
|
12
|
+
private selectionOptions;
|
|
13
|
+
private selectionDraft;
|
|
14
|
+
private loaded;
|
|
15
|
+
private destroyed;
|
|
16
|
+
private readonly handleSelectionChangeBound;
|
|
17
|
+
private readonly handleDocumentPointerDownBound;
|
|
18
|
+
private readonly preserveSelectionOnToolbarMouseDownBound;
|
|
19
|
+
private readonly handleHighlightClickBound;
|
|
20
|
+
private readonly handleNoteClickBound;
|
|
21
|
+
constructor(container: HTMLElement, options: EBookPlayerOptions);
|
|
22
|
+
load(): Promise<EbookDoc>;
|
|
23
|
+
destroy(): void;
|
|
24
|
+
getDocument(): EbookDoc;
|
|
25
|
+
getAnnotations(): ReaderAnnotations;
|
|
26
|
+
getHighlights(): ReaderHighlight[];
|
|
27
|
+
getNotes(): ReaderNote[];
|
|
28
|
+
setAnnotations(annotations: ReaderAnnotations, source?: ReaderAnnotationChangeSource): Promise<ReaderAnnotations>;
|
|
29
|
+
reloadAnnotations(): Promise<ReaderAnnotations>;
|
|
30
|
+
createHighlight(highlight: Omit<ReaderHighlight, "id" | "createdAt" | "updatedAt" | "bookId">, source?: ReaderAnnotationChangeSource): Promise<ReaderHighlight>;
|
|
31
|
+
updateHighlight(highlightId: string, patch: Partial<Omit<ReaderHighlight, "id" | "bookId" | "createdAt">>, source?: ReaderAnnotationChangeSource): Promise<ReaderHighlight | null>;
|
|
32
|
+
deleteHighlight(highlightId: string, source?: ReaderAnnotationChangeSource): Promise<boolean>;
|
|
33
|
+
createNote(note: Omit<ReaderNote, "id" | "createdAt" | "updatedAt" | "bookId">, source?: ReaderAnnotationChangeSource): Promise<ReaderNote>;
|
|
34
|
+
updateNote(noteId: string, patch: Partial<Omit<ReaderNote, "id" | "bookId" | "createdAt">>, source?: ReaderAnnotationChangeSource): Promise<ReaderNote | null>;
|
|
35
|
+
deleteNote(noteId: string, source?: ReaderAnnotationChangeSource): Promise<boolean>;
|
|
36
|
+
onAnnotationCreate(listener: (event: ReaderAnnotationCreateEvent) => void): () => void;
|
|
37
|
+
onAnnotationUpdate(listener: (event: ReaderAnnotationUpdateEvent) => void): () => void;
|
|
38
|
+
onAnnotationDelete(listener: (event: ReaderAnnotationDeleteEvent) => void): () => void;
|
|
39
|
+
onAnnotationsChange(listener: (event: ReaderAnnotationsChangeEvent) => void): () => void;
|
|
40
|
+
private renderDocument;
|
|
41
|
+
private renderPage;
|
|
42
|
+
private renderTextBlock;
|
|
43
|
+
private renderNonTextBlock;
|
|
44
|
+
private getTextBlockContent;
|
|
45
|
+
private createAnnotationBuckets;
|
|
46
|
+
private toBlockKey;
|
|
47
|
+
private applyHighlightMarks;
|
|
48
|
+
private applyNoteMarks;
|
|
49
|
+
private wrapRangeWithMark;
|
|
50
|
+
private createRangeFromOffsets;
|
|
51
|
+
private normalizeOffsetRange;
|
|
52
|
+
private handleSelectionChange;
|
|
53
|
+
private resolveTextContainer;
|
|
54
|
+
private getSelectionOffsets;
|
|
55
|
+
private hideSelectionToolbar;
|
|
56
|
+
private clearSelection;
|
|
57
|
+
private handleDocumentPointerDown;
|
|
58
|
+
private preserveSelectionOnToolbarMouseDown;
|
|
59
|
+
private handleHighlightClick;
|
|
60
|
+
private handleNoteClick;
|
|
61
|
+
private resolveWidth;
|
|
62
|
+
private resolveSelectionToolbarOptions;
|
|
63
|
+
private ensureLoaded;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=ebook-player.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ebook-player.d.ts","sourceRoot":"","sources":["../../../../../core/src/player/ebook-player.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,550 @@
|
|
|
1
|
+
import { PlayerEngine } from "./engine";
|
|
2
|
+
const EBOOK_PLAYER_STYLE_ID = "hy-ebook-lite-player-style";
|
|
3
|
+
const EBOOK_PLAYER_STYLE_VERSION = "0.1.0";
|
|
4
|
+
const EBOOK_PLAYER_CSS = `
|
|
5
|
+
.hyepl-root{position:relative;max-width:100%;margin:0 auto;color:#0f172a;font-size:14px;line-height:1.7}
|
|
6
|
+
.hyepl-content{position:relative}
|
|
7
|
+
.hyepl-page{margin:0 0 16px}
|
|
8
|
+
.hyepl-page:last-child{margin-bottom:0}
|
|
9
|
+
.hyepl-block{margin:0 0 10px;white-space:pre-wrap;word-break:break-word}
|
|
10
|
+
.hyepl-block:last-child{margin-bottom:0}
|
|
11
|
+
.hyepl-block-muted{color:#64748b}
|
|
12
|
+
.hyepl-highlight{background:var(--hyepl-highlight-color,#fff59d);color:inherit;padding:0 .08em;border-radius:.2em}
|
|
13
|
+
.hyepl-note{background:rgba(14,116,144,.14);border-bottom:2px solid #0e7490;color:inherit;padding:0 .04em;border-radius:.2em}
|
|
14
|
+
.hyepl-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%)}
|
|
15
|
+
.hyepl-selection-toolbar.show{display:inline-flex}
|
|
16
|
+
.hyepl-toolbar-btn{height:30px;padding:0 10px;border:1px solid #334155;border-radius:8px;background:#1e293b;color:#f8fafc;cursor:pointer;font-size:12px}
|
|
17
|
+
`;
|
|
18
|
+
export class EBookPlayer {
|
|
19
|
+
constructor(container, options) {
|
|
20
|
+
this.selectionDraft = null;
|
|
21
|
+
this.loaded = false;
|
|
22
|
+
this.destroyed = false;
|
|
23
|
+
this.handleSelectionChangeBound = () => {
|
|
24
|
+
this.handleSelectionChange();
|
|
25
|
+
};
|
|
26
|
+
this.handleDocumentPointerDownBound = (event) => {
|
|
27
|
+
this.handleDocumentPointerDown(event);
|
|
28
|
+
};
|
|
29
|
+
this.preserveSelectionOnToolbarMouseDownBound = (event) => {
|
|
30
|
+
this.preserveSelectionOnToolbarMouseDown(event);
|
|
31
|
+
};
|
|
32
|
+
this.handleHighlightClickBound = () => {
|
|
33
|
+
void this.handleHighlightClick();
|
|
34
|
+
};
|
|
35
|
+
this.handleNoteClickBound = () => {
|
|
36
|
+
void this.handleNoteClick();
|
|
37
|
+
};
|
|
38
|
+
this.container = container;
|
|
39
|
+
this.options = options;
|
|
40
|
+
this.engine = new PlayerEngine(options.provider, options.engineOptions);
|
|
41
|
+
this.selectionOptions = this.resolveSelectionToolbarOptions(options.selectionToolbar);
|
|
42
|
+
ensureEBookPlayerStyles();
|
|
43
|
+
this.root = document.createElement("section");
|
|
44
|
+
this.root.className = "hyepl-root";
|
|
45
|
+
this.root.style.width = `${this.resolveWidth(options.width)}px`;
|
|
46
|
+
this.content = document.createElement("div");
|
|
47
|
+
this.content.className = "hyepl-content";
|
|
48
|
+
this.selectionToolbar = document.createElement("div");
|
|
49
|
+
this.selectionToolbar.className = "hyepl-selection-toolbar";
|
|
50
|
+
this.highlightBtn = document.createElement("button");
|
|
51
|
+
this.highlightBtn.type = "button";
|
|
52
|
+
this.highlightBtn.className = "hyepl-toolbar-btn";
|
|
53
|
+
this.highlightBtn.textContent = this.selectionOptions.highlightButtonText;
|
|
54
|
+
this.highlightBtn.setAttribute("aria-label", this.selectionOptions.highlightButtonText);
|
|
55
|
+
this.noteBtn = document.createElement("button");
|
|
56
|
+
this.noteBtn.type = "button";
|
|
57
|
+
this.noteBtn.className = "hyepl-toolbar-btn";
|
|
58
|
+
this.noteBtn.textContent = this.selectionOptions.noteButtonText;
|
|
59
|
+
this.noteBtn.setAttribute("aria-label", this.selectionOptions.noteButtonText);
|
|
60
|
+
this.selectionToolbar.append(this.highlightBtn, this.noteBtn);
|
|
61
|
+
this.root.append(this.content, this.selectionToolbar);
|
|
62
|
+
this.container.innerHTML = "";
|
|
63
|
+
this.container.append(this.root);
|
|
64
|
+
this.highlightBtn.addEventListener("mousedown", this.preserveSelectionOnToolbarMouseDownBound);
|
|
65
|
+
this.noteBtn.addEventListener("mousedown", this.preserveSelectionOnToolbarMouseDownBound);
|
|
66
|
+
this.highlightBtn.addEventListener("click", this.handleHighlightClickBound);
|
|
67
|
+
this.noteBtn.addEventListener("click", this.handleNoteClickBound);
|
|
68
|
+
document.addEventListener("selectionchange", this.handleSelectionChangeBound);
|
|
69
|
+
document.addEventListener("pointerdown", this.handleDocumentPointerDownBound);
|
|
70
|
+
}
|
|
71
|
+
async load() {
|
|
72
|
+
const doc = await this.engine.load();
|
|
73
|
+
this.loaded = true;
|
|
74
|
+
if (this.options.initialAnnotations) {
|
|
75
|
+
await this.engine.setAnnotations(this.options.initialAnnotations, "api");
|
|
76
|
+
}
|
|
77
|
+
this.renderDocument();
|
|
78
|
+
return doc;
|
|
79
|
+
}
|
|
80
|
+
destroy() {
|
|
81
|
+
if (this.destroyed) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
this.destroyed = true;
|
|
85
|
+
this.hideSelectionToolbar();
|
|
86
|
+
document.removeEventListener("selectionchange", this.handleSelectionChangeBound);
|
|
87
|
+
document.removeEventListener("pointerdown", this.handleDocumentPointerDownBound);
|
|
88
|
+
this.highlightBtn.removeEventListener("mousedown", this.preserveSelectionOnToolbarMouseDownBound);
|
|
89
|
+
this.noteBtn.removeEventListener("mousedown", this.preserveSelectionOnToolbarMouseDownBound);
|
|
90
|
+
this.highlightBtn.removeEventListener("click", this.handleHighlightClickBound);
|
|
91
|
+
this.noteBtn.removeEventListener("click", this.handleNoteClickBound);
|
|
92
|
+
if (this.root.parentNode === this.container) {
|
|
93
|
+
this.container.removeChild(this.root);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
getDocument() {
|
|
97
|
+
return this.engine.getDocument();
|
|
98
|
+
}
|
|
99
|
+
getAnnotations() {
|
|
100
|
+
return this.engine.getAnnotations();
|
|
101
|
+
}
|
|
102
|
+
getHighlights() {
|
|
103
|
+
return this.engine.getHighlights();
|
|
104
|
+
}
|
|
105
|
+
getNotes() {
|
|
106
|
+
return this.engine.getNotes();
|
|
107
|
+
}
|
|
108
|
+
async setAnnotations(annotations, source = "api") {
|
|
109
|
+
this.ensureLoaded();
|
|
110
|
+
const all = await this.engine.setAnnotations(annotations, source);
|
|
111
|
+
this.renderDocument();
|
|
112
|
+
return all;
|
|
113
|
+
}
|
|
114
|
+
async reloadAnnotations() {
|
|
115
|
+
this.ensureLoaded();
|
|
116
|
+
const all = await this.engine.reloadAnnotations();
|
|
117
|
+
this.renderDocument();
|
|
118
|
+
return all;
|
|
119
|
+
}
|
|
120
|
+
async createHighlight(highlight, source = "api") {
|
|
121
|
+
this.ensureLoaded();
|
|
122
|
+
const created = await this.engine.createHighlight(highlight, source);
|
|
123
|
+
this.renderDocument();
|
|
124
|
+
return created;
|
|
125
|
+
}
|
|
126
|
+
async updateHighlight(highlightId, patch, source = "api") {
|
|
127
|
+
this.ensureLoaded();
|
|
128
|
+
const updated = await this.engine.updateHighlight(highlightId, patch, source);
|
|
129
|
+
this.renderDocument();
|
|
130
|
+
return updated;
|
|
131
|
+
}
|
|
132
|
+
async deleteHighlight(highlightId, source = "api") {
|
|
133
|
+
this.ensureLoaded();
|
|
134
|
+
const deleted = await this.engine.deleteHighlight(highlightId, source);
|
|
135
|
+
this.renderDocument();
|
|
136
|
+
return deleted;
|
|
137
|
+
}
|
|
138
|
+
async createNote(note, source = "api") {
|
|
139
|
+
this.ensureLoaded();
|
|
140
|
+
const created = await this.engine.createNote(note, source);
|
|
141
|
+
this.renderDocument();
|
|
142
|
+
return created;
|
|
143
|
+
}
|
|
144
|
+
async updateNote(noteId, patch, source = "api") {
|
|
145
|
+
this.ensureLoaded();
|
|
146
|
+
const updated = await this.engine.updateNote(noteId, patch, source);
|
|
147
|
+
this.renderDocument();
|
|
148
|
+
return updated;
|
|
149
|
+
}
|
|
150
|
+
async deleteNote(noteId, source = "api") {
|
|
151
|
+
this.ensureLoaded();
|
|
152
|
+
const deleted = await this.engine.deleteNote(noteId, source);
|
|
153
|
+
this.renderDocument();
|
|
154
|
+
return deleted;
|
|
155
|
+
}
|
|
156
|
+
onAnnotationCreate(listener) {
|
|
157
|
+
return this.engine.onAnnotationCreate(listener);
|
|
158
|
+
}
|
|
159
|
+
onAnnotationUpdate(listener) {
|
|
160
|
+
return this.engine.onAnnotationUpdate(listener);
|
|
161
|
+
}
|
|
162
|
+
onAnnotationDelete(listener) {
|
|
163
|
+
return this.engine.onAnnotationDelete(listener);
|
|
164
|
+
}
|
|
165
|
+
onAnnotationsChange(listener) {
|
|
166
|
+
return this.engine.onAnnotationsChange(listener);
|
|
167
|
+
}
|
|
168
|
+
renderDocument() {
|
|
169
|
+
if (!this.loaded || this.destroyed) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const doc = this.engine.getDocument();
|
|
173
|
+
const buckets = this.createAnnotationBuckets(this.engine.getAnnotations());
|
|
174
|
+
const fragment = document.createDocumentFragment();
|
|
175
|
+
doc.pages.forEach((page) => {
|
|
176
|
+
fragment.append(this.renderPage(page, buckets));
|
|
177
|
+
});
|
|
178
|
+
this.content.innerHTML = "";
|
|
179
|
+
this.content.append(fragment);
|
|
180
|
+
this.hideSelectionToolbar();
|
|
181
|
+
}
|
|
182
|
+
renderPage(page, buckets) {
|
|
183
|
+
const pageSection = document.createElement("section");
|
|
184
|
+
pageSection.className = "hyepl-page";
|
|
185
|
+
pageSection.dataset.pageId = page.id;
|
|
186
|
+
page.blocks.forEach((block) => {
|
|
187
|
+
if (block.type === "text") {
|
|
188
|
+
pageSection.append(this.renderTextBlock(page.id, block, buckets));
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
pageSection.append(this.renderNonTextBlock(block));
|
|
192
|
+
});
|
|
193
|
+
return pageSection;
|
|
194
|
+
}
|
|
195
|
+
renderTextBlock(pageId, block, buckets) {
|
|
196
|
+
const blockTextNode = document.createElement("div");
|
|
197
|
+
blockTextNode.className = "hyepl-block hyepl-block-text";
|
|
198
|
+
blockTextNode.dataset.pageId = pageId;
|
|
199
|
+
blockTextNode.dataset.blockId = block.id;
|
|
200
|
+
blockTextNode.textContent = this.getTextBlockContent(block);
|
|
201
|
+
const blockKey = this.toBlockKey(pageId, block.id);
|
|
202
|
+
const highlights = buckets.highlightsByBlock.get(blockKey) || [];
|
|
203
|
+
const notes = buckets.notesByBlock.get(blockKey) || [];
|
|
204
|
+
this.applyHighlightMarks(blockTextNode, highlights);
|
|
205
|
+
this.applyNoteMarks(blockTextNode, notes);
|
|
206
|
+
return blockTextNode;
|
|
207
|
+
}
|
|
208
|
+
renderNonTextBlock(block) {
|
|
209
|
+
const node = document.createElement("div");
|
|
210
|
+
node.className = "hyepl-block hyepl-block-muted";
|
|
211
|
+
if (block.type === "image") {
|
|
212
|
+
node.textContent = "[图片内容]";
|
|
213
|
+
return node;
|
|
214
|
+
}
|
|
215
|
+
if (block.type === "video") {
|
|
216
|
+
node.textContent = "[视频内容]";
|
|
217
|
+
return node;
|
|
218
|
+
}
|
|
219
|
+
if (block.type === "table") {
|
|
220
|
+
node.textContent = "[表格内容]";
|
|
221
|
+
return node;
|
|
222
|
+
}
|
|
223
|
+
node.textContent = "[内容块]";
|
|
224
|
+
return node;
|
|
225
|
+
}
|
|
226
|
+
getTextBlockContent(block) {
|
|
227
|
+
return block.content.paragraphs
|
|
228
|
+
.map((paragraph) => {
|
|
229
|
+
return paragraph.runs.map((run) => run.text || "").join("");
|
|
230
|
+
})
|
|
231
|
+
.join("\n");
|
|
232
|
+
}
|
|
233
|
+
createAnnotationBuckets(annotations) {
|
|
234
|
+
const highlightsByBlock = new Map();
|
|
235
|
+
const notesByBlock = new Map();
|
|
236
|
+
annotations.highlights.forEach((item) => {
|
|
237
|
+
const key = this.toBlockKey(item.pageId, item.blockId);
|
|
238
|
+
const current = highlightsByBlock.get(key) || [];
|
|
239
|
+
current.push(item);
|
|
240
|
+
highlightsByBlock.set(key, current);
|
|
241
|
+
});
|
|
242
|
+
annotations.notes.forEach((item) => {
|
|
243
|
+
const key = this.toBlockKey(item.pageId, item.blockId);
|
|
244
|
+
const current = notesByBlock.get(key) || [];
|
|
245
|
+
current.push(item);
|
|
246
|
+
notesByBlock.set(key, current);
|
|
247
|
+
});
|
|
248
|
+
return { highlightsByBlock, notesByBlock };
|
|
249
|
+
}
|
|
250
|
+
toBlockKey(pageId, blockId) {
|
|
251
|
+
return `${pageId}::${blockId}`;
|
|
252
|
+
}
|
|
253
|
+
applyHighlightMarks(container, highlights) {
|
|
254
|
+
[...highlights]
|
|
255
|
+
.filter((item) => Number.isFinite(item.range.start) && Number.isFinite(item.range.end))
|
|
256
|
+
.sort((a, b) => b.range.start - a.range.start)
|
|
257
|
+
.forEach((item) => {
|
|
258
|
+
const range = this.createRangeFromOffsets(container, item.range.start, item.range.end);
|
|
259
|
+
if (!range || range.collapsed) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
const mark = document.createElement("mark");
|
|
263
|
+
mark.className = "hyepl-highlight";
|
|
264
|
+
if (item.color) {
|
|
265
|
+
mark.style.setProperty("--hyepl-highlight-color", item.color);
|
|
266
|
+
}
|
|
267
|
+
this.wrapRangeWithMark(range, mark);
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
applyNoteMarks(container, notes) {
|
|
271
|
+
[...notes]
|
|
272
|
+
.filter((item) => !!item.range)
|
|
273
|
+
.sort((a, b) => {
|
|
274
|
+
const startA = a.range?.start || 0;
|
|
275
|
+
const startB = b.range?.start || 0;
|
|
276
|
+
return startB - startA;
|
|
277
|
+
})
|
|
278
|
+
.forEach((item) => {
|
|
279
|
+
if (!item.range) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
const range = this.createRangeFromOffsets(container, item.range.start, item.range.end);
|
|
283
|
+
if (!range || range.collapsed) {
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
const mark = document.createElement("mark");
|
|
287
|
+
mark.className = "hyepl-note";
|
|
288
|
+
mark.dataset.noteId = item.id;
|
|
289
|
+
this.wrapRangeWithMark(range, mark);
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
wrapRangeWithMark(range, mark) {
|
|
293
|
+
try {
|
|
294
|
+
range.surroundContents(mark);
|
|
295
|
+
}
|
|
296
|
+
catch {
|
|
297
|
+
const fragment = range.extractContents();
|
|
298
|
+
mark.append(fragment);
|
|
299
|
+
range.insertNode(mark);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
createRangeFromOffsets(containerNode, start, end) {
|
|
303
|
+
const normalized = this.normalizeOffsetRange(start, end);
|
|
304
|
+
if (!normalized) {
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
307
|
+
const range = document.createRange();
|
|
308
|
+
const walker = document.createTreeWalker(containerNode, NodeFilter.SHOW_TEXT);
|
|
309
|
+
let cursor = 0;
|
|
310
|
+
let startNode = null;
|
|
311
|
+
let endNode = null;
|
|
312
|
+
let startOffset = 0;
|
|
313
|
+
let endOffset = 0;
|
|
314
|
+
let lastTextNode = null;
|
|
315
|
+
while (walker.nextNode()) {
|
|
316
|
+
const node = walker.currentNode;
|
|
317
|
+
const length = node.textContent?.length || 0;
|
|
318
|
+
lastTextNode = node;
|
|
319
|
+
const nextCursor = cursor + length;
|
|
320
|
+
if (!startNode &&
|
|
321
|
+
normalized.start >= cursor &&
|
|
322
|
+
normalized.start < nextCursor) {
|
|
323
|
+
startNode = node;
|
|
324
|
+
startOffset = normalized.start - cursor;
|
|
325
|
+
}
|
|
326
|
+
if (!endNode && normalized.end > cursor && normalized.end <= nextCursor) {
|
|
327
|
+
endNode = node;
|
|
328
|
+
endOffset = normalized.end - cursor;
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
cursor = nextCursor;
|
|
332
|
+
}
|
|
333
|
+
if (!startNode && lastTextNode && normalized.start === cursor) {
|
|
334
|
+
startNode = lastTextNode;
|
|
335
|
+
startOffset = lastTextNode.textContent?.length || 0;
|
|
336
|
+
}
|
|
337
|
+
if (!endNode && lastTextNode && normalized.end === cursor) {
|
|
338
|
+
endNode = lastTextNode;
|
|
339
|
+
endOffset = lastTextNode.textContent?.length || 0;
|
|
340
|
+
}
|
|
341
|
+
if (!startNode || !endNode) {
|
|
342
|
+
return null;
|
|
343
|
+
}
|
|
344
|
+
range.setStart(startNode, startOffset);
|
|
345
|
+
range.setEnd(endNode, endOffset);
|
|
346
|
+
return range;
|
|
347
|
+
}
|
|
348
|
+
normalizeOffsetRange(start, end) {
|
|
349
|
+
const safeStart = Math.max(0, Math.floor(start || 0));
|
|
350
|
+
const safeEnd = Math.max(0, Math.floor(end || 0));
|
|
351
|
+
if (safeStart === safeEnd) {
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
return safeStart < safeEnd
|
|
355
|
+
? { start: safeStart, end: safeEnd }
|
|
356
|
+
: { start: safeEnd, end: safeStart };
|
|
357
|
+
}
|
|
358
|
+
handleSelectionChange() {
|
|
359
|
+
if (!this.selectionOptions.enabled || !this.loaded || this.destroyed) {
|
|
360
|
+
this.hideSelectionToolbar();
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
const selection = window.getSelection();
|
|
364
|
+
if (!selection || selection.rangeCount === 0 || selection.isCollapsed) {
|
|
365
|
+
this.hideSelectionToolbar();
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
const range = selection.getRangeAt(0);
|
|
369
|
+
const startContainer = this.resolveTextContainer(range.startContainer);
|
|
370
|
+
const endContainer = this.resolveTextContainer(range.endContainer);
|
|
371
|
+
if (!startContainer || !endContainer || startContainer !== endContainer) {
|
|
372
|
+
this.hideSelectionToolbar();
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
const offsets = this.getSelectionOffsets(startContainer, selection);
|
|
376
|
+
if (!offsets) {
|
|
377
|
+
this.hideSelectionToolbar();
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
const pageId = startContainer.dataset.pageId;
|
|
381
|
+
const blockId = startContainer.dataset.blockId;
|
|
382
|
+
if (!pageId || !blockId) {
|
|
383
|
+
this.hideSelectionToolbar();
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
const rect = range.getBoundingClientRect();
|
|
387
|
+
if (!rect.width && !rect.height) {
|
|
388
|
+
this.hideSelectionToolbar();
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
this.selectionDraft = {
|
|
392
|
+
pageId,
|
|
393
|
+
blockId,
|
|
394
|
+
range: offsets,
|
|
395
|
+
text: selection.toString().trim(),
|
|
396
|
+
};
|
|
397
|
+
this.selectionToolbar.style.left = `${Math.round(rect.left + rect.width / 2)}px`;
|
|
398
|
+
this.selectionToolbar.style.top = `${Math.round(rect.top - 8)}px`;
|
|
399
|
+
this.selectionToolbar.classList.add("show");
|
|
400
|
+
}
|
|
401
|
+
resolveTextContainer(node) {
|
|
402
|
+
if (!node) {
|
|
403
|
+
return null;
|
|
404
|
+
}
|
|
405
|
+
const baseElement = node.nodeType === Node.ELEMENT_NODE
|
|
406
|
+
? node
|
|
407
|
+
: node.parentElement;
|
|
408
|
+
if (!baseElement) {
|
|
409
|
+
return null;
|
|
410
|
+
}
|
|
411
|
+
const textContainer = baseElement.closest(".hyepl-block-text");
|
|
412
|
+
if (!textContainer || !this.content.contains(textContainer)) {
|
|
413
|
+
return null;
|
|
414
|
+
}
|
|
415
|
+
return textContainer;
|
|
416
|
+
}
|
|
417
|
+
getSelectionOffsets(container, selection) {
|
|
418
|
+
if (selection.rangeCount === 0) {
|
|
419
|
+
return null;
|
|
420
|
+
}
|
|
421
|
+
const range = selection.getRangeAt(0);
|
|
422
|
+
const startRange = document.createRange();
|
|
423
|
+
startRange.selectNodeContents(container);
|
|
424
|
+
startRange.setEnd(range.startContainer, range.startOffset);
|
|
425
|
+
const endRange = document.createRange();
|
|
426
|
+
endRange.selectNodeContents(container);
|
|
427
|
+
endRange.setEnd(range.endContainer, range.endOffset);
|
|
428
|
+
const start = startRange.toString().length;
|
|
429
|
+
const end = endRange.toString().length;
|
|
430
|
+
return this.normalizeOffsetRange(start, end);
|
|
431
|
+
}
|
|
432
|
+
hideSelectionToolbar() {
|
|
433
|
+
this.selectionToolbar.classList.remove("show");
|
|
434
|
+
this.selectionDraft = null;
|
|
435
|
+
}
|
|
436
|
+
clearSelection() {
|
|
437
|
+
window.getSelection()?.removeAllRanges();
|
|
438
|
+
}
|
|
439
|
+
handleDocumentPointerDown(event) {
|
|
440
|
+
const target = event.target;
|
|
441
|
+
if (!target) {
|
|
442
|
+
this.hideSelectionToolbar();
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
if (this.selectionToolbar.contains(target)) {
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
if (!this.root.contains(target)) {
|
|
449
|
+
this.hideSelectionToolbar();
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
preserveSelectionOnToolbarMouseDown(event) {
|
|
453
|
+
event.preventDefault();
|
|
454
|
+
event.stopPropagation();
|
|
455
|
+
}
|
|
456
|
+
async handleHighlightClick() {
|
|
457
|
+
if (!this.selectionDraft) {
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
const payload = {
|
|
461
|
+
pageId: this.selectionDraft.pageId,
|
|
462
|
+
blockId: this.selectionDraft.blockId,
|
|
463
|
+
range: this.selectionDraft.range,
|
|
464
|
+
...(this.selectionDraft.text
|
|
465
|
+
? { selectedText: this.selectionDraft.text }
|
|
466
|
+
: {}),
|
|
467
|
+
...(this.selectionOptions.highlightColor
|
|
468
|
+
? { color: this.selectionOptions.highlightColor }
|
|
469
|
+
: {}),
|
|
470
|
+
};
|
|
471
|
+
await this.createHighlight(payload, "user");
|
|
472
|
+
this.clearSelection();
|
|
473
|
+
this.hideSelectionToolbar();
|
|
474
|
+
}
|
|
475
|
+
async handleNoteClick() {
|
|
476
|
+
if (!this.selectionDraft) {
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
const defaultText = this.selectionDraft.text || "";
|
|
480
|
+
const noteText = window.prompt("请输入笔记内容", defaultText);
|
|
481
|
+
const content = noteText?.trim();
|
|
482
|
+
if (!content) {
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
const payload = {
|
|
486
|
+
pageId: this.selectionDraft.pageId,
|
|
487
|
+
blockId: this.selectionDraft.blockId,
|
|
488
|
+
range: this.selectionDraft.range,
|
|
489
|
+
content,
|
|
490
|
+
...(this.selectionDraft.text
|
|
491
|
+
? { selectedText: this.selectionDraft.text }
|
|
492
|
+
: {}),
|
|
493
|
+
...(this.selectionOptions.noteColor
|
|
494
|
+
? { color: this.selectionOptions.noteColor }
|
|
495
|
+
: {}),
|
|
496
|
+
};
|
|
497
|
+
await this.createNote(payload, "user");
|
|
498
|
+
this.clearSelection();
|
|
499
|
+
this.hideSelectionToolbar();
|
|
500
|
+
}
|
|
501
|
+
resolveWidth(width) {
|
|
502
|
+
if (!Number.isFinite(width)) {
|
|
503
|
+
return 840;
|
|
504
|
+
}
|
|
505
|
+
return Math.max(320, Math.round(width));
|
|
506
|
+
}
|
|
507
|
+
resolveSelectionToolbarOptions(options) {
|
|
508
|
+
const highlightButtonText = typeof options?.highlightButtonText === "string" &&
|
|
509
|
+
options.highlightButtonText.trim()
|
|
510
|
+
? options.highlightButtonText.trim()
|
|
511
|
+
: "高亮";
|
|
512
|
+
const noteButtonText = typeof options?.noteButtonText === "string" &&
|
|
513
|
+
options.noteButtonText.trim()
|
|
514
|
+
? options.noteButtonText.trim()
|
|
515
|
+
: "笔记";
|
|
516
|
+
return {
|
|
517
|
+
enabled: options?.enabled !== false,
|
|
518
|
+
highlightButtonText,
|
|
519
|
+
noteButtonText,
|
|
520
|
+
highlightColor: typeof options?.highlightColor === "string" &&
|
|
521
|
+
options.highlightColor.trim()
|
|
522
|
+
? options.highlightColor.trim()
|
|
523
|
+
: "#fff59d",
|
|
524
|
+
noteColor: typeof options?.noteColor === "string" && options.noteColor.trim()
|
|
525
|
+
? options.noteColor.trim()
|
|
526
|
+
: "#0e7490",
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
ensureLoaded() {
|
|
530
|
+
if (!this.loaded) {
|
|
531
|
+
throw new Error("Document is not loaded. Call load() first.");
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
function ensureEBookPlayerStyles() {
|
|
536
|
+
const existing = document.getElementById(EBOOK_PLAYER_STYLE_ID);
|
|
537
|
+
if (existing instanceof HTMLStyleElement) {
|
|
538
|
+
if (existing.dataset.hyeplVersion !== EBOOK_PLAYER_STYLE_VERSION ||
|
|
539
|
+
existing.textContent !== EBOOK_PLAYER_CSS) {
|
|
540
|
+
existing.textContent = EBOOK_PLAYER_CSS;
|
|
541
|
+
existing.dataset.hyeplVersion = EBOOK_PLAYER_STYLE_VERSION;
|
|
542
|
+
}
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
const style = document.createElement("style");
|
|
546
|
+
style.id = EBOOK_PLAYER_STYLE_ID;
|
|
547
|
+
style.dataset.hyeplVersion = EBOOK_PLAYER_STYLE_VERSION;
|
|
548
|
+
style.textContent = EBOOK_PLAYER_CSS;
|
|
549
|
+
document.head.append(style);
|
|
550
|
+
}
|
|
@@ -30,6 +30,7 @@ export declare class PlayerEngine {
|
|
|
30
30
|
getFeatures(): Required<PlayerFeatures>;
|
|
31
31
|
isBuiltInNotesModuleEnabled(): boolean;
|
|
32
32
|
reloadAnnotations(): Promise<ReaderAnnotations>;
|
|
33
|
+
setAnnotations(annotations: ReaderAnnotations, source?: ReaderAnnotationChangeSource): Promise<ReaderAnnotations>;
|
|
33
34
|
goToHighlight(highlightId: string): number | null;
|
|
34
35
|
goToNote(noteId: string): number | null;
|
|
35
36
|
goToPage(index: number): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../../../core/src/player/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAsB,MAAM,gBAAgB,CAAC;AACnE,OAAO,KAAK,EAEV,4BAA4B,EAC5B,2BAA2B,EAC3B,2BAA2B,EAC3B,iBAAiB,EACjB,4BAA4B,EAC5B,2BAA2B,EAC3B,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,UAAU,EACV,cAAc,EAEf,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;CACjC;AAED,KAAK,wBAAwB,GAAG,CAAC,KAAK,EAAE,2BAA2B,KAAK,IAAI,CAAC;AAC7E,KAAK,wBAAwB,GAAG,CAAC,KAAK,EAAE,2BAA2B,KAAK,IAAI,CAAC;AAC7E,KAAK,wBAAwB,GAAG,CAAC,KAAK,EAAE,2BAA2B,KAAK,IAAI,CAAC;AAC7E,KAAK,yBAAyB,GAAG,CAAC,KAAK,EAAE,4BAA4B,KAAK,IAAI,CAAC;AAM/E,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,QAAQ,CAA2B;IAC3C,OAAO,CAAC,GAAG,CAAyB;IACpC,OAAO,CAAC,KAAK,CAMX;IACF,OAAO,CAAC,yBAAyB,CAAuC;IACxE,OAAO,CAAC,yBAAyB,CAAuC;IACxE,OAAO,CAAC,yBAAyB,CAAuC;IACxE,OAAO,CAAC,0BAA0B,CAAwC;gBAE9D,QAAQ,EAAE,kBAAkB,EAAE,OAAO,GAAE,mBAAwB;IASrE,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC;IAa/B,WAAW,IAAI,QAAQ;IAOvB,QAAQ,IAAI,WAAW;IAIvB,aAAa,IAAI,eAAe,EAAE;IAIlC,QAAQ,IAAI,UAAU,EAAE;IAIxB,cAAc,IAAI,iBAAiB;IAOnC,WAAW,IAAI,QAAQ,CAAC,cAAc,CAAC;IAIvC,2BAA2B,IAAI,OAAO;IAIhC,iBAAiB,IAAI,OAAO,CAAC,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../../../core/src/player/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -69,6 +69,29 @@ export class PlayerEngine {
|
|
|
69
69
|
await this.loadAnnotationsState();
|
|
70
70
|
return this.getAnnotations();
|
|
71
71
|
}
|
|
72
|
+
async setAnnotations(annotations, source = "api") {
|
|
73
|
+
if (!this.doc) {
|
|
74
|
+
throw new Error("Document is not loaded. Call load() first.");
|
|
75
|
+
}
|
|
76
|
+
const normalized = this.normalizeAnnotations(annotations, this.doc.id);
|
|
77
|
+
this.state.highlights = normalized.highlights;
|
|
78
|
+
this.state.notes = normalized.notes;
|
|
79
|
+
await this.persistAnnotations();
|
|
80
|
+
const all = this.getAnnotations();
|
|
81
|
+
this.emitAnnotationsChange({
|
|
82
|
+
action: "update",
|
|
83
|
+
kind: "highlight",
|
|
84
|
+
source,
|
|
85
|
+
all,
|
|
86
|
+
});
|
|
87
|
+
this.emitAnnotationsChange({
|
|
88
|
+
action: "update",
|
|
89
|
+
kind: "note",
|
|
90
|
+
source,
|
|
91
|
+
all,
|
|
92
|
+
});
|
|
93
|
+
return all;
|
|
94
|
+
}
|
|
72
95
|
goToHighlight(highlightId) {
|
|
73
96
|
const target = this.state.highlights.find((item) => item.id === highlightId);
|
|
74
97
|
if (!target) {
|
|
@@ -267,7 +290,7 @@ export class PlayerEngine {
|
|
|
267
290
|
if (this.provider.loadAnnotations) {
|
|
268
291
|
const annotations = await this.provider.loadAnnotations(this.doc.id);
|
|
269
292
|
if (annotations) {
|
|
270
|
-
const normalized = this.normalizeAnnotations(annotations);
|
|
293
|
+
const normalized = this.normalizeAnnotations(annotations, this.doc.id);
|
|
271
294
|
this.state.highlights = normalized.highlights;
|
|
272
295
|
this.state.notes = normalized.notes;
|
|
273
296
|
restoredFromAnnotationsProvider = true;
|
|
@@ -296,14 +319,41 @@ export class PlayerEngine {
|
|
|
296
319
|
? { start: safeStart, end: safeEnd }
|
|
297
320
|
: { start: safeEnd, end: safeStart };
|
|
298
321
|
}
|
|
299
|
-
normalizeAnnotations(annotations) {
|
|
322
|
+
normalizeAnnotations(annotations, bookId) {
|
|
323
|
+
const now = new Date().toISOString();
|
|
300
324
|
const highlights = Array.isArray(annotations?.highlights)
|
|
301
|
-
?
|
|
302
|
-
: [];
|
|
303
|
-
const notes = Array.isArray(annotations?.notes)
|
|
304
|
-
? clone(annotations.notes)
|
|
325
|
+
? annotations.highlights
|
|
305
326
|
: [];
|
|
306
|
-
|
|
327
|
+
const notes = Array.isArray(annotations?.notes) ? annotations.notes : [];
|
|
328
|
+
return {
|
|
329
|
+
highlights: highlights.map((item, index) => {
|
|
330
|
+
const fallbackId = `highlight-${Date.now()}-${index}`;
|
|
331
|
+
return {
|
|
332
|
+
...clone(item),
|
|
333
|
+
id: item.id || fallbackId,
|
|
334
|
+
bookId: item.bookId || bookId || "",
|
|
335
|
+
pageId: item.pageId || "",
|
|
336
|
+
blockId: item.blockId || "preview-flow-text",
|
|
337
|
+
range: this.normalizeRange(item.range),
|
|
338
|
+
createdAt: item.createdAt || now,
|
|
339
|
+
updatedAt: item.updatedAt || item.createdAt || now,
|
|
340
|
+
};
|
|
341
|
+
}),
|
|
342
|
+
notes: notes.map((item, index) => {
|
|
343
|
+
const fallbackId = `note-${Date.now()}-${index}`;
|
|
344
|
+
return {
|
|
345
|
+
...clone(item),
|
|
346
|
+
id: item.id || fallbackId,
|
|
347
|
+
bookId: item.bookId || bookId || "",
|
|
348
|
+
pageId: item.pageId || "",
|
|
349
|
+
blockId: item.blockId || "preview-flow-text",
|
|
350
|
+
...(item.range ? { range: this.normalizeRange(item.range) } : {}),
|
|
351
|
+
content: item.content || "",
|
|
352
|
+
createdAt: item.createdAt || now,
|
|
353
|
+
updatedAt: item.updatedAt || item.createdAt || now,
|
|
354
|
+
};
|
|
355
|
+
}),
|
|
356
|
+
};
|
|
307
357
|
}
|
|
308
358
|
mapPreviewAnnotationsToReader(annotations, bookId) {
|
|
309
359
|
const now = new Date().toISOString();
|
|
@@ -72,6 +72,13 @@ export interface PlayerFeatures {
|
|
|
72
72
|
export interface PlayerEngineOptions {
|
|
73
73
|
features?: PlayerFeatures;
|
|
74
74
|
}
|
|
75
|
+
export interface EBookPlayerSelectionToolbarOptions {
|
|
76
|
+
enabled?: boolean;
|
|
77
|
+
highlightButtonText?: string;
|
|
78
|
+
noteButtonText?: string;
|
|
79
|
+
highlightColor?: string;
|
|
80
|
+
noteColor?: string;
|
|
81
|
+
}
|
|
75
82
|
export interface PlayerDataProvider {
|
|
76
83
|
getData: () => Promise<EbookDoc>;
|
|
77
84
|
loadProgress?: (bookId: string) => Promise<ReaderProgress | null>;
|
|
@@ -82,4 +89,31 @@ export interface PlayerDataProvider {
|
|
|
82
89
|
saveNotes?: (bookId: string, notes: ReaderNote[]) => Promise<void>;
|
|
83
90
|
onError?: (error: Error) => void;
|
|
84
91
|
}
|
|
92
|
+
export interface EBookPlayerOptions {
|
|
93
|
+
provider: PlayerDataProvider;
|
|
94
|
+
engineOptions?: PlayerEngineOptions;
|
|
95
|
+
width?: number;
|
|
96
|
+
initialAnnotations?: ReaderAnnotations;
|
|
97
|
+
selectionToolbar?: EBookPlayerSelectionToolbarOptions;
|
|
98
|
+
}
|
|
99
|
+
export interface EBookPlayerHandle {
|
|
100
|
+
load: () => Promise<EbookDoc>;
|
|
101
|
+
destroy: () => void;
|
|
102
|
+
getDocument: () => EbookDoc;
|
|
103
|
+
getAnnotations: () => ReaderAnnotations;
|
|
104
|
+
getHighlights: () => ReaderHighlight[];
|
|
105
|
+
getNotes: () => ReaderNote[];
|
|
106
|
+
setAnnotations: (annotations: ReaderAnnotations, source?: ReaderAnnotationChangeSource) => Promise<ReaderAnnotations>;
|
|
107
|
+
reloadAnnotations: () => Promise<ReaderAnnotations>;
|
|
108
|
+
createHighlight: (highlight: Omit<ReaderHighlight, "id" | "createdAt" | "updatedAt" | "bookId">, source?: ReaderAnnotationChangeSource) => Promise<ReaderHighlight>;
|
|
109
|
+
updateHighlight: (highlightId: string, patch: Partial<Omit<ReaderHighlight, "id" | "bookId" | "createdAt">>, source?: ReaderAnnotationChangeSource) => Promise<ReaderHighlight | null>;
|
|
110
|
+
deleteHighlight: (highlightId: string, source?: ReaderAnnotationChangeSource) => Promise<boolean>;
|
|
111
|
+
createNote: (note: Omit<ReaderNote, "id" | "createdAt" | "updatedAt" | "bookId">, source?: ReaderAnnotationChangeSource) => Promise<ReaderNote>;
|
|
112
|
+
updateNote: (noteId: string, patch: Partial<Omit<ReaderNote, "id" | "bookId" | "createdAt">>, source?: ReaderAnnotationChangeSource) => Promise<ReaderNote | null>;
|
|
113
|
+
deleteNote: (noteId: string, source?: ReaderAnnotationChangeSource) => Promise<boolean>;
|
|
114
|
+
onAnnotationCreate: (listener: (event: ReaderAnnotationCreateEvent) => void) => () => void;
|
|
115
|
+
onAnnotationUpdate: (listener: (event: ReaderAnnotationUpdateEvent) => void) => () => void;
|
|
116
|
+
onAnnotationDelete: (listener: (event: ReaderAnnotationDeleteEvent) => void) => () => void;
|
|
117
|
+
onAnnotationsChange: (listener: (event: ReaderAnnotationsChangeEvent) => void) => () => void;
|
|
118
|
+
}
|
|
85
119
|
//# sourceMappingURL=player.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"player.d.ts","sourceRoot":"","sources":["../../../../../core/src/types/player.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"player.d.ts","sourceRoot":"","sources":["../../../../../core/src/types/player.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,11 +12,39 @@ export interface EditorWorkbenchOptions {
|
|
|
12
12
|
previewAnnotations?: EditorWorkbenchPreviewAnnotationOptions;
|
|
13
13
|
title?: string;
|
|
14
14
|
pageWidth?: number;
|
|
15
|
+
fullscreen?: EditorWorkbenchFullscreenOptions;
|
|
16
|
+
extension?: EditorWorkbenchExtensionOptions;
|
|
17
|
+
debug?: boolean | EditorWorkbenchDebugOptions;
|
|
15
18
|
upload?: EditorWorkbenchUploadOptions;
|
|
16
19
|
importDocx?: EditorWorkbenchDocxImportOptions;
|
|
17
20
|
onDocumentChange?: (doc: EbookDoc) => void | Promise<void>;
|
|
18
21
|
onFullscreenSave?: (doc: EbookDoc) => void | Promise<void>;
|
|
19
22
|
}
|
|
23
|
+
export interface EditorWorkbenchFullscreenOptions {
|
|
24
|
+
exitButtonText?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface EditorWorkbenchExtensionActionContext {
|
|
27
|
+
getDocument: () => EbookDoc;
|
|
28
|
+
isFullscreen: () => boolean;
|
|
29
|
+
getMode: () => "editor" | "preview";
|
|
30
|
+
setMode: (mode: "editor" | "preview") => void;
|
|
31
|
+
closeFullscreenAndSave: () => Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
export interface EditorWorkbenchExtensionActionButton {
|
|
34
|
+
id: string;
|
|
35
|
+
text: string;
|
|
36
|
+
color?: string;
|
|
37
|
+
textColor?: string;
|
|
38
|
+
borderColor?: string;
|
|
39
|
+
onClick?: (context: EditorWorkbenchExtensionActionContext, event: MouseEvent) => void | Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
export interface EditorWorkbenchExtensionOptions {
|
|
42
|
+
actions?: EditorWorkbenchExtensionActionButton[];
|
|
43
|
+
}
|
|
44
|
+
export interface EditorWorkbenchDebugOptions {
|
|
45
|
+
enabled?: boolean;
|
|
46
|
+
prefix?: string;
|
|
47
|
+
}
|
|
20
48
|
export interface EditorWorkbenchPreviewAnnotationActions {
|
|
21
49
|
canDelete?: boolean;
|
|
22
50
|
}
|
|
@@ -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":"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"}
|
|
@@ -1,15 +1,18 @@
|
|
|
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.
|
|
4
|
+
const WORKBENCH_STYLE_VERSION = "0.3.0";
|
|
5
5
|
const WORKBENCH_CSS = `
|
|
6
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;position:relative;--hyewb-top-shield-height:0px}
|
|
7
7
|
.hyewb-root::before{content:"";position:absolute;left:0;right:0;top:0;height:var(--hyewb-top-shield-height);background:#f8fbff;z-index:119500;pointer-events:none}
|
|
8
8
|
.hyewb-header{display:flex;justify-content:space-between;align-items:center;gap:8px;flex-wrap:wrap}
|
|
9
9
|
.hyewb-title{font-size:14px;font-weight:600}
|
|
10
|
+
.hyewb-header-actions{margin-left:auto;display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap}
|
|
10
11
|
.hyewb-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
|
|
11
12
|
.hyewb-top-control{position:relative;z-index:120000;background:#f8fbff;isolation:isolate}
|
|
12
13
|
.hyewb-btn{border:1px solid #94a3b8;background:#fff;color:#0f172a;border-radius:8px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0;width:34px;height:34px;flex:0 0 auto}
|
|
14
|
+
.hyewb-btn.hyewb-btn-text{width:auto;min-width:96px;padding:0 12px}
|
|
15
|
+
.hyewb-header-action-btn{height:34px}
|
|
13
16
|
.hyewb-btn.active{border-color:#0b7285;background:#0b7285;color:#fff}
|
|
14
17
|
.hyewb-btn:disabled{cursor:not-allowed;opacity:.55}
|
|
15
18
|
.hyewb-btn svg,.hyewb-upload-close svg{width:16px;height:16px;stroke-width:2}
|
|
@@ -25,10 +28,10 @@ const WORKBENCH_CSS = `
|
|
|
25
28
|
.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}
|
|
26
29
|
.hyewb-field-icon svg{width:14px;height:14px;stroke-width:2}
|
|
27
30
|
.hyewb-field-with-icon .hyewb-select,.hyewb-field-with-icon .hyewb-number{padding-left:30px}
|
|
28
|
-
.hyewb-shell{border:1px dashed #b8c3d1;border-radius:10px;background:#eef4ff;padding:10px;overflow-x:auto;overflow-y:auto;overscroll-behavior:
|
|
31
|
+
.hyewb-shell{border:1px dashed #b8c3d1;border-radius:10px;background:#eef4ff;padding:10px;overflow-x:auto;overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
|
|
29
32
|
.hyewb-preview-layout{display:grid;grid-template-columns:minmax(0,1fr);gap:12px;align-items:start}
|
|
30
33
|
.hyewb-preview-layout.with-annotation-panel{grid-template-columns:minmax(0,1fr) 300px}
|
|
31
|
-
.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:
|
|
34
|
+
.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:16px auto;max-width:100%;box-sizing:border-box;}
|
|
32
35
|
.hyewb-editor{min-height:360px;outline:none;line-height:1.7;font-size:16px;color:#1e293b}
|
|
33
36
|
.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)}
|
|
34
37
|
.hyewb-float.show{display:inline-flex}
|
|
@@ -175,10 +178,14 @@ const WORKBENCH_CSS = `
|
|
|
175
178
|
.hyewb-preview-selection-btn svg{width:16px;height:16px}
|
|
176
179
|
.hyewb-preview-annotation-flash{animation:hyewb-preview-annotation-pulse .9s ease}
|
|
177
180
|
@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)}}
|
|
178
|
-
.hyewb-overlay{position:fixed;inset:0;z-index:2147483000;background:rgba(15,23,42,.35);padding:0;box-sizing:border-box;overflow:
|
|
179
|
-
.hyewb-overlay-layer{min-height:
|
|
180
|
-
.hyewb-root.hyewb-overlay-active{width:100%;max-width:none;min-height:
|
|
181
|
-
.hyewb-root.hyewb-overlay-active .hyewb-
|
|
181
|
+
.hyewb-overlay{position:fixed;inset:0;z-index:2147483000;background:rgba(15,23,42,.35);padding:0;box-sizing:border-box;overflow:hidden;overscroll-behavior:contain}
|
|
182
|
+
.hyewb-overlay-layer{min-height:100vh;min-height:100dvh;height:100vh;height:100dvh;display:flex;align-items:stretch;justify-content:stretch;overflow:hidden}
|
|
183
|
+
.hyewb-root.hyewb-overlay-active{width:100%;max-width:none;min-height:100vh;min-height:100dvh;height:100vh;height:100dvh;margin:0;border-radius:0;box-shadow:none;grid-template-rows:auto auto minmax(0,1fr);overflow:hidden}
|
|
184
|
+
.hyewb-root.hyewb-overlay-active .hyewb-preview-layout{height:100%;min-height:0;align-items:stretch;grid-template-rows:minmax(0,1fr)}
|
|
185
|
+
.hyewb-root.hyewb-overlay-active .hyewb-shell{height:100%;max-height:none;min-height:0;padding:0;background:transparent}
|
|
186
|
+
.hyewb-root.hyewb-overlay-active .hyewb-canvas{height:auto;min-height:100%;border-radius:0;box-shadow:none}
|
|
187
|
+
.hyewb-root.hyewb-overlay-active .hyewb-preview-annotation-panel{height:100%;max-height:none}
|
|
188
|
+
.hyewb-root.hyewb-overlay-active .hyewb-editor,.hyewb-root.hyewb-overlay-active .hyewb-preview{min-height:100%}
|
|
182
189
|
`;
|
|
183
190
|
export const DEFAULT_EDITOR_WORKBENCH_FEATURES = {
|
|
184
191
|
textToolbar: true,
|
|
@@ -449,14 +456,50 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
449
456
|
const paperWidth = resolvePaperWidth(options.pageWidth, state.doc.settings.page.width);
|
|
450
457
|
const root = document.createElement("section");
|
|
451
458
|
root.className = "hyewb-root";
|
|
459
|
+
const extensionActionConfigs = Array.isArray(options.extension?.actions)
|
|
460
|
+
? options.extension.actions.filter((action) => {
|
|
461
|
+
return (!!action &&
|
|
462
|
+
typeof action.id === "string" &&
|
|
463
|
+
action.id.trim().length > 0 &&
|
|
464
|
+
typeof action.text === "string" &&
|
|
465
|
+
action.text.trim().length > 0);
|
|
466
|
+
})
|
|
467
|
+
: [];
|
|
452
468
|
const header = document.createElement("header");
|
|
453
469
|
header.className = "hyewb-header hyewb-top-control";
|
|
454
470
|
const title = document.createElement("div");
|
|
455
471
|
title.className = "hyewb-title";
|
|
456
472
|
title.textContent = options.title ?? "hy-ebook Editor Workbench";
|
|
473
|
+
const headerActions = document.createElement("div");
|
|
474
|
+
headerActions.className = "hyewb-header-actions";
|
|
457
475
|
const fullscreenBtn = createButton("fullscreen");
|
|
458
|
-
|
|
459
|
-
|
|
476
|
+
const extensionActionButtons = extensionActionConfigs.map((action) => {
|
|
477
|
+
const button = document.createElement("button");
|
|
478
|
+
button.type = "button";
|
|
479
|
+
button.className = "hyewb-btn hyewb-btn-text hyewb-header-action-btn";
|
|
480
|
+
const text = action.text.trim();
|
|
481
|
+
button.textContent = text;
|
|
482
|
+
button.title = text;
|
|
483
|
+
button.setAttribute("aria-label", text);
|
|
484
|
+
button.style.display = "none";
|
|
485
|
+
const color = typeof action.color === "string" ? action.color.trim() : "";
|
|
486
|
+
if (color) {
|
|
487
|
+
button.style.backgroundColor = color;
|
|
488
|
+
button.style.borderColor = color;
|
|
489
|
+
}
|
|
490
|
+
const textColor = typeof action.textColor === "string" ? action.textColor.trim() : "";
|
|
491
|
+
if (textColor) {
|
|
492
|
+
button.style.color = textColor;
|
|
493
|
+
}
|
|
494
|
+
const borderColor = typeof action.borderColor === "string" ? action.borderColor.trim() : "";
|
|
495
|
+
if (borderColor) {
|
|
496
|
+
button.style.borderColor = borderColor;
|
|
497
|
+
}
|
|
498
|
+
headerActions.append(button);
|
|
499
|
+
return { action, button };
|
|
500
|
+
});
|
|
501
|
+
headerActions.append(fullscreenBtn);
|
|
502
|
+
header.append(title, headerActions);
|
|
460
503
|
const toolbar = document.createElement("div");
|
|
461
504
|
toolbar.className = "hyewb-row hyewb-top-control";
|
|
462
505
|
const boldBtn = createButton("bold");
|
|
@@ -854,6 +897,41 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
854
897
|
const status = document.createElement("p");
|
|
855
898
|
status.className = "hyewb-status";
|
|
856
899
|
status.textContent = "已加载默认编辑器能力";
|
|
900
|
+
const debugEnabled = options.debug === true ||
|
|
901
|
+
(typeof options.debug === "object" &&
|
|
902
|
+
options.debug !== null &&
|
|
903
|
+
options.debug.enabled !== false);
|
|
904
|
+
const debugPrefix = typeof options.debug === "object" &&
|
|
905
|
+
options.debug !== null &&
|
|
906
|
+
options.debug.prefix
|
|
907
|
+
? options.debug.prefix
|
|
908
|
+
: "[hyebook:workbench]";
|
|
909
|
+
const debugLog = (message) => {
|
|
910
|
+
if (!debugEnabled) {
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
console.log(`${debugPrefix} ${message}`);
|
|
914
|
+
};
|
|
915
|
+
let lastDebugStatusMessage = "";
|
|
916
|
+
const flushDebugStatus = () => {
|
|
917
|
+
const nextMessage = String(status.textContent || "").trim();
|
|
918
|
+
if (!nextMessage || nextMessage === lastDebugStatusMessage) {
|
|
919
|
+
return;
|
|
920
|
+
}
|
|
921
|
+
lastDebugStatusMessage = nextMessage;
|
|
922
|
+
debugLog(nextMessage);
|
|
923
|
+
};
|
|
924
|
+
const statusObserver = debugEnabled && typeof MutationObserver !== "undefined"
|
|
925
|
+
? new MutationObserver(() => {
|
|
926
|
+
flushDebugStatus();
|
|
927
|
+
})
|
|
928
|
+
: null;
|
|
929
|
+
statusObserver?.observe(status, {
|
|
930
|
+
childList: true,
|
|
931
|
+
characterData: true,
|
|
932
|
+
subtree: true,
|
|
933
|
+
});
|
|
934
|
+
flushDebugStatus();
|
|
857
935
|
const uploadBackdrop = document.createElement("div");
|
|
858
936
|
uploadBackdrop.className = "hyewb-upload-backdrop";
|
|
859
937
|
const uploadDialog = document.createElement("div");
|
|
@@ -892,7 +970,7 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
892
970
|
const colorGrid = document.createElement("div");
|
|
893
971
|
colorGrid.className = "hyewb-color-grid";
|
|
894
972
|
colorPalette.append(colorGrid);
|
|
895
|
-
root.append(header, toolbar, pageRow, previewLayout,
|
|
973
|
+
root.append(header, toolbar, pageRow, previewLayout, colorPalette, tablePicker, tableTools, tableRowDeleteBtn, tableMoveHandle, tableScaleHandle, tableColEdgeLayer, tableRowEdgeLayer, tableRowGapInsertBtn, tableColGapInsertBtn, tableDropIndicator, tableContextMenu, uploadBackdrop, previewNoteBackdrop, docxInput, previewSelectionToolbar);
|
|
896
974
|
container.innerHTML = "";
|
|
897
975
|
root.append(floatingToolbar);
|
|
898
976
|
container.append(root);
|
|
@@ -940,27 +1018,52 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
940
1018
|
let fullscreenOverlay = null;
|
|
941
1019
|
let fullscreenAnchor = null;
|
|
942
1020
|
let bodyOverflowBeforeOverlay = null;
|
|
1021
|
+
let htmlOverflowBeforeOverlay = null;
|
|
943
1022
|
let isOverlayFullscreen = false;
|
|
1023
|
+
const fullscreenExitButtonText = typeof options.fullscreen?.exitButtonText === "string"
|
|
1024
|
+
? options.fullscreen.exitButtonText.trim()
|
|
1025
|
+
: "";
|
|
944
1026
|
const setButtonIcon = (button, iconName) => {
|
|
945
|
-
button.
|
|
1027
|
+
button.classList.remove("hyewb-btn-text");
|
|
1028
|
+
button.textContent = "";
|
|
946
1029
|
button.append(createIconPlaceholder(iconName));
|
|
947
1030
|
};
|
|
1031
|
+
const setButtonText = (button, text) => {
|
|
1032
|
+
button.classList.add("hyewb-btn-text");
|
|
1033
|
+
button.textContent = text;
|
|
1034
|
+
};
|
|
948
1035
|
const isWorkbenchFullscreen = () => {
|
|
949
1036
|
return isOverlayFullscreen;
|
|
950
1037
|
};
|
|
951
1038
|
const updateFullscreenButtonState = () => {
|
|
952
1039
|
const isFullscreen = isWorkbenchFullscreen();
|
|
953
1040
|
setButtonActive(fullscreenBtn, isFullscreen);
|
|
954
|
-
|
|
1041
|
+
const shouldUseExitText = isFullscreen && fullscreenExitButtonText.length > 0;
|
|
1042
|
+
if (shouldUseExitText) {
|
|
1043
|
+
setButtonText(fullscreenBtn, fullscreenExitButtonText);
|
|
1044
|
+
}
|
|
1045
|
+
else {
|
|
1046
|
+
setButtonIcon(fullscreenBtn, isFullscreen ? "fullscreen-exit" : "fullscreen-enter");
|
|
1047
|
+
}
|
|
955
1048
|
const label = isFullscreen ? "保存并退出" : "全屏";
|
|
956
|
-
|
|
957
|
-
fullscreenBtn.
|
|
1049
|
+
const ariaLabel = shouldUseExitText ? fullscreenExitButtonText : label;
|
|
1050
|
+
fullscreenBtn.title = ariaLabel;
|
|
1051
|
+
fullscreenBtn.setAttribute("aria-label", ariaLabel);
|
|
958
1052
|
fullscreenBtn.style.display = isFullscreen ? "inline-flex" : "none";
|
|
1053
|
+
extensionActionButtons.forEach(({ button }) => {
|
|
1054
|
+
button.style.display = isFullscreen ? "inline-flex" : "none";
|
|
1055
|
+
});
|
|
959
1056
|
};
|
|
960
1057
|
const updateShellViewportHeight = () => {
|
|
1058
|
+
if (isWorkbenchFullscreen()) {
|
|
1059
|
+
shell.style.height = "100%";
|
|
1060
|
+
shell.style.maxHeight = "";
|
|
1061
|
+
return;
|
|
1062
|
+
}
|
|
1063
|
+
shell.style.height = "";
|
|
961
1064
|
const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
|
|
962
1065
|
const top = root.getBoundingClientRect().top;
|
|
963
|
-
const bottomPadding =
|
|
1066
|
+
const bottomPadding = 24;
|
|
964
1067
|
const nextHeight = Math.max(320, Math.floor(viewportHeight - top - bottomPadding));
|
|
965
1068
|
shell.style.maxHeight = `${nextHeight}px`;
|
|
966
1069
|
};
|
|
@@ -1012,10 +1115,13 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
1012
1115
|
fullscreenOverlay.append(fullscreenOverlayLayer);
|
|
1013
1116
|
fullscreenOverlayLayer.append(root);
|
|
1014
1117
|
document.body.append(fullscreenOverlay);
|
|
1118
|
+
htmlOverflowBeforeOverlay = document.documentElement.style.overflow;
|
|
1119
|
+
document.documentElement.style.overflow = "hidden";
|
|
1015
1120
|
bodyOverflowBeforeOverlay = document.body.style.overflow;
|
|
1016
1121
|
document.body.style.overflow = "hidden";
|
|
1017
1122
|
root.classList.add("hyewb-overlay-active");
|
|
1018
1123
|
isOverlayFullscreen = true;
|
|
1124
|
+
render();
|
|
1019
1125
|
status.textContent = "已进入页面全屏编辑";
|
|
1020
1126
|
syncWorkbenchLayoutAfterFullscreenChange();
|
|
1021
1127
|
};
|
|
@@ -1037,10 +1143,15 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
1037
1143
|
fullscreenOverlay = null;
|
|
1038
1144
|
root.classList.remove("hyewb-overlay-active");
|
|
1039
1145
|
isOverlayFullscreen = false;
|
|
1146
|
+
render();
|
|
1040
1147
|
if (bodyOverflowBeforeOverlay !== null) {
|
|
1041
1148
|
document.body.style.overflow = bodyOverflowBeforeOverlay;
|
|
1042
1149
|
bodyOverflowBeforeOverlay = null;
|
|
1043
1150
|
}
|
|
1151
|
+
if (htmlOverflowBeforeOverlay !== null) {
|
|
1152
|
+
document.documentElement.style.overflow = htmlOverflowBeforeOverlay;
|
|
1153
|
+
htmlOverflowBeforeOverlay = null;
|
|
1154
|
+
}
|
|
1044
1155
|
syncWorkbenchLayoutAfterFullscreenChange();
|
|
1045
1156
|
};
|
|
1046
1157
|
const closeWorkbenchFullscreenAndSave = async () => {
|
|
@@ -1064,6 +1175,16 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
1064
1175
|
status.textContent = `保存失败:${errorMessage}`;
|
|
1065
1176
|
}
|
|
1066
1177
|
};
|
|
1178
|
+
const getExtensionActionContext = () => {
|
|
1179
|
+
syncEditorToDoc({ emitChange: false });
|
|
1180
|
+
return {
|
|
1181
|
+
getDocument: () => clone(state.doc),
|
|
1182
|
+
isFullscreen: isWorkbenchFullscreen,
|
|
1183
|
+
getMode: () => state.mode,
|
|
1184
|
+
setMode,
|
|
1185
|
+
closeFullscreenAndSave: closeWorkbenchFullscreenAndSave,
|
|
1186
|
+
};
|
|
1187
|
+
};
|
|
1067
1188
|
const formatUploadProgress = (percent) => {
|
|
1068
1189
|
const safe = Number.isFinite(percent) ? percent : 0;
|
|
1069
1190
|
const clamped = Math.max(0, Math.min(100, safe));
|
|
@@ -3552,7 +3673,14 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
3552
3673
|
return Math.max(max, nextBottom);
|
|
3553
3674
|
}, 0);
|
|
3554
3675
|
const nextCanvasMinHeight = Math.max(420, Math.round(mediaBottom + 60));
|
|
3555
|
-
|
|
3676
|
+
if (isWorkbenchFullscreen()) {
|
|
3677
|
+
const shellHeight = Math.max(0, Math.round(shell.clientHeight));
|
|
3678
|
+
const fullscreenCanvasMinHeight = Math.max(nextCanvasMinHeight, shellHeight);
|
|
3679
|
+
canvas.style.minHeight = `${fullscreenCanvasMinHeight}px`;
|
|
3680
|
+
}
|
|
3681
|
+
else {
|
|
3682
|
+
canvas.style.minHeight = `${nextCanvasMinHeight}px`;
|
|
3683
|
+
}
|
|
3556
3684
|
mediaStage.classList.toggle("preview", state.mode === "preview");
|
|
3557
3685
|
mediaStage.innerHTML = "";
|
|
3558
3686
|
mediaBlocks.forEach((item, index) => {
|
|
@@ -4619,6 +4747,28 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
4619
4747
|
fullscreenBtn.addEventListener("click", () => {
|
|
4620
4748
|
void closeWorkbenchFullscreenAndSave();
|
|
4621
4749
|
});
|
|
4750
|
+
extensionActionButtons.forEach(({ action, button }) => {
|
|
4751
|
+
button.addEventListener("click", (event) => {
|
|
4752
|
+
if (!action.onClick) {
|
|
4753
|
+
return;
|
|
4754
|
+
}
|
|
4755
|
+
try {
|
|
4756
|
+
const result = action.onClick(getExtensionActionContext(), event);
|
|
4757
|
+
void Promise.resolve(result).catch((error) => {
|
|
4758
|
+
const errorMessage = error instanceof Error && error.message
|
|
4759
|
+
? error.message
|
|
4760
|
+
: "请稍后重试";
|
|
4761
|
+
status.textContent = `扩展按钮执行失败:${errorMessage}`;
|
|
4762
|
+
});
|
|
4763
|
+
}
|
|
4764
|
+
catch (error) {
|
|
4765
|
+
const errorMessage = error instanceof Error && error.message
|
|
4766
|
+
? error.message
|
|
4767
|
+
: "请稍后重试";
|
|
4768
|
+
status.textContent = `扩展按钮执行失败:${errorMessage}`;
|
|
4769
|
+
}
|
|
4770
|
+
});
|
|
4771
|
+
});
|
|
4622
4772
|
tableAddBtn.addEventListener("mousedown", preserveSelectionForInputControl);
|
|
4623
4773
|
videoAddBtn.addEventListener("mousedown", preserveSelectionForInputControl);
|
|
4624
4774
|
videoAddBtn.addEventListener("click", () => {
|
|
@@ -4704,6 +4854,7 @@ export function mountEditorWorkbench(container, options = {}) {
|
|
|
4704
4854
|
emitDocumentChange();
|
|
4705
4855
|
return {
|
|
4706
4856
|
destroy: () => {
|
|
4857
|
+
statusObserver?.disconnect();
|
|
4707
4858
|
closeWorkbenchFullscreen();
|
|
4708
4859
|
hideTablePicker();
|
|
4709
4860
|
hideTableTools();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EditorEngine, PlayerEngine, type EditorWorkbenchHandle, type EditorWorkbenchOptions, type EbookDoc, type PlayerDataProvider, type PlayerEngineOptions } from "@hyebook/core";
|
|
1
|
+
import { EBookPlayer, EditorEngine, PlayerEngine, type EBookPlayerOptions, type EditorWorkbenchHandle, type EditorWorkbenchOptions, type EbookDoc, type PlayerDataProvider, type PlayerEngineOptions } from "@hyebook/core";
|
|
2
2
|
export interface Vue3EditorAdapterOptions {
|
|
3
3
|
initialDoc: EbookDoc;
|
|
4
4
|
onDocumentChange?: (doc: EbookDoc) => void;
|
|
@@ -7,11 +7,14 @@ export interface Vue3PlayerAdapterOptions {
|
|
|
7
7
|
provider: PlayerDataProvider;
|
|
8
8
|
engineOptions?: PlayerEngineOptions;
|
|
9
9
|
}
|
|
10
|
+
export interface Vue3EBookPlayerAdapterOptions extends EBookPlayerOptions {
|
|
11
|
+
}
|
|
10
12
|
export interface Vue3EditorWorkbenchOptions extends EditorWorkbenchOptions {
|
|
11
13
|
}
|
|
12
14
|
export interface Vue3EditorWorkbenchHandle extends EditorWorkbenchHandle {
|
|
13
15
|
}
|
|
14
16
|
export declare function createVue3EditorAdapter(options: Vue3EditorAdapterOptions): EditorEngine;
|
|
15
17
|
export declare function createVue3PlayerAdapter(options: Vue3PlayerAdapterOptions): PlayerEngine;
|
|
18
|
+
export declare function createEBookPlayerAdapter(container: HTMLElement, options: Vue3EBookPlayerAdapterOptions): EBookPlayer;
|
|
16
19
|
export declare function mountVue3EditorWorkbench(container: HTMLElement, options?: Vue3EditorWorkbenchOptions): Vue3EditorWorkbenchHandle;
|
|
17
20
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,KAAK,kBAAkB,EAEvB,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,QAAQ,EACb,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACzB,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,QAAQ,CAAC;IACrB,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,IAAI,CAAC;CAC5C;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,aAAa,CAAC,EAAE,mBAAmB,CAAC;CACrC;AAED,MAAM,WAAW,6BAA8B,SAAQ,kBAAkB;CAAG;AAE5E,MAAM,WAAW,0BAA2B,SAAQ,sBAAsB;CAAG;AAE7E,MAAM,WAAW,yBAA0B,SAAQ,qBAAqB;CAAG;AAE3E,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,GAChC,YAAY,CAId;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,GAChC,YAAY,CAEd;AAED,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,WAAW,EACtB,OAAO,EAAE,6BAA6B,GACrC,WAAW,CAEb;AAED,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,WAAW,EACtB,OAAO,GAAE,0BAA+B,GACvC,yBAAyB,CAE3B"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EditorEngine, PlayerEngine, mountEditorWorkbench, } from "@hyebook/core";
|
|
1
|
+
import { EBookPlayer, EditorEngine, PlayerEngine, mountEditorWorkbench, } from "@hyebook/core";
|
|
2
2
|
export function createVue3EditorAdapter(options) {
|
|
3
3
|
const engine = new EditorEngine(options.initialDoc);
|
|
4
4
|
options.onDocumentChange?.(engine.getDocument());
|
|
@@ -7,6 +7,9 @@ export function createVue3EditorAdapter(options) {
|
|
|
7
7
|
export function createVue3PlayerAdapter(options) {
|
|
8
8
|
return new PlayerEngine(options.provider, options.engineOptions);
|
|
9
9
|
}
|
|
10
|
+
export function createEBookPlayerAdapter(container, options) {
|
|
11
|
+
return new EBookPlayer(container, options);
|
|
12
|
+
}
|
|
10
13
|
export function mountVue3EditorWorkbench(container, options = {}) {
|
|
11
14
|
return mountEditorWorkbench(container, options);
|
|
12
15
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyebook/vue3-adapter",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
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": "^2.
|
|
20
|
+
"@hyebook/core": "^2.3.0"
|
|
21
21
|
},
|
|
22
22
|
"scripts": {
|
|
23
23
|
"build": "tsc -p tsconfig.json",
|