@hyebook/vue3-adapter 2.3.1 → 2.3.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.
@@ -1,5 +1,5 @@
1
1
  import type { EbookDoc } from "../types/ebook";
2
- import type { EBookPlayerHandle, EBookPlayerOptions, ReaderAnnotationChangeSource, ReaderAnnotationCreateEvent, ReaderAnnotationDeleteEvent, ReaderAnnotations, ReaderAnnotationsChangeEvent, ReaderAnnotationUpdateEvent, ReaderHighlight, ReaderNote } from "../types/player";
2
+ import type { EBookPlayerHandle, EBookPlayerOptions, ReaderAnnotationCreateEvent, ReaderAnnotationDeleteEvent, ReaderAnnotations, ReaderAnnotationsChangeEvent, ReaderAnnotationUpdateEvent, ReaderBookmark, ReaderHighlight, ReaderNote } from "../types/player";
3
3
  export declare class EBookPlayer implements EBookPlayerHandle {
4
4
  private container;
5
5
  private options;
@@ -9,8 +9,10 @@ export declare class EBookPlayer implements EBookPlayerHandle {
9
9
  private content;
10
10
  private selectionToolbar;
11
11
  private highlightBtn;
12
+ private toolbarDivider;
12
13
  private noteBtn;
13
14
  private selectionOptions;
15
+ private inputLimits;
14
16
  private selectionDraft;
15
17
  private loaded;
16
18
  private destroyed;
@@ -26,14 +28,18 @@ export declare class EBookPlayer implements EBookPlayerHandle {
26
28
  getAnnotations(): ReaderAnnotations;
27
29
  getHighlights(): ReaderHighlight[];
28
30
  getNotes(): ReaderNote[];
29
- setAnnotations(annotations: ReaderAnnotations, source?: ReaderAnnotationChangeSource): Promise<ReaderAnnotations>;
31
+ getBookmarks(): ReaderBookmark[];
32
+ setAnnotations(annotations: ReaderAnnotations, source?: "api" | "user"): Promise<ReaderAnnotations>;
30
33
  reloadAnnotations(): Promise<ReaderAnnotations>;
31
- createHighlight(highlight: Omit<ReaderHighlight, "id" | "createdAt" | "updatedAt" | "bookId">, source?: ReaderAnnotationChangeSource): Promise<ReaderHighlight>;
32
- updateHighlight(highlightId: string, patch: Partial<Omit<ReaderHighlight, "id" | "bookId" | "createdAt">>, source?: ReaderAnnotationChangeSource): Promise<ReaderHighlight | null>;
33
- deleteHighlight(highlightId: string, source?: ReaderAnnotationChangeSource): Promise<boolean>;
34
- createNote(note: Omit<ReaderNote, "id" | "createdAt" | "updatedAt" | "bookId">, source?: ReaderAnnotationChangeSource): Promise<ReaderNote>;
35
- updateNote(noteId: string, patch: Partial<Omit<ReaderNote, "id" | "bookId" | "createdAt">>, source?: ReaderAnnotationChangeSource): Promise<ReaderNote | null>;
36
- deleteNote(noteId: string, source?: ReaderAnnotationChangeSource): Promise<boolean>;
34
+ createHighlight(highlight: Omit<ReaderHighlight, "id" | "createdAt" | "updatedAt" | "bookId">, source?: "api" | "user"): Promise<ReaderHighlight>;
35
+ updateHighlight(highlightId: string, patch: Partial<Omit<ReaderHighlight, "id" | "bookId" | "createdAt">>, source?: "api" | "user"): Promise<ReaderHighlight | null>;
36
+ deleteHighlight(highlightId: string, source?: "api" | "user"): Promise<boolean>;
37
+ createNote(note: Omit<ReaderNote, "id" | "createdAt" | "updatedAt" | "bookId">, source?: "api" | "user"): Promise<ReaderNote>;
38
+ updateNote(noteId: string, patch: Partial<Omit<ReaderNote, "id" | "bookId" | "createdAt">>, source?: "api" | "user"): Promise<ReaderNote | null>;
39
+ deleteNote(noteId: string, source?: "api" | "user"): Promise<boolean>;
40
+ setBookmark(pageId: string, blockId: string, source?: "api" | "user"): Promise<ReaderBookmark | null>;
41
+ deleteBookmark(bookmarkId: string, source?: "api" | "user"): Promise<boolean>;
42
+ goToBookmark(bookmarkId: string): number | null;
37
43
  onAnnotationCreate(listener: (event: ReaderAnnotationCreateEvent) => void): () => void;
38
44
  onAnnotationUpdate(listener: (event: ReaderAnnotationUpdateEvent) => void): () => void;
39
45
  onAnnotationDelete(listener: (event: ReaderAnnotationDeleteEvent) => void): () => void;
@@ -47,6 +53,7 @@ export declare class EBookPlayer implements EBookPlayerHandle {
47
53
  private toBlockKey;
48
54
  private applyHighlightMarks;
49
55
  private applyNoteMarks;
56
+ private applyBookmarkMarker;
50
57
  private wrapRangeWithMark;
51
58
  private createRangeFromOffsets;
52
59
  private normalizeOffsetRange;
@@ -61,6 +68,12 @@ export declare class EBookPlayer implements EBookPlayerHandle {
61
68
  private handleNoteClick;
62
69
  private resolveWidth;
63
70
  private resolveSelectionToolbarOptions;
71
+ private resolveInputLimits;
72
+ private normalizeLimitValue;
73
+ private promptTextWithLimit;
74
+ private ensureTextBlockExists;
75
+ private findBookmarkByBlock;
76
+ private setToolbarButtonContent;
64
77
  private ensureLoaded;
65
78
  }
66
79
  //# sourceMappingURL=ebook-player.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ebook-player.d.ts","sourceRoot":"","sources":["../../../../../core/src/player/ebook-player.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ebook-player.d.ts","sourceRoot":"","sources":["../../../../../core/src/player/ebook-player.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,9 @@
1
1
  import { PlayerEngine } from "./engine";
2
2
  const EBOOK_PLAYER_STYLE_ID = "hy-ebook-lite-player-style";
3
3
  const EBOOK_PLAYER_STYLE_VERSION = "0.1.0";
4
+ const HIGHLIGHT_ICON_SVG = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3 22V12.5H6V8.5H18V12.5H21V22H3Z" stroke="#333333" stroke-width="2" stroke-linejoin="round"/><path d="M8.5 8.5V4L15.5 2V8.5" stroke="#333333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
5
+ const NOTE_ICON_SVG = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15.4998 4.49951L19.4998 8.4995" stroke="#333333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M3.99977 15.9995L17.9997 2L21.9998 5.9995L7.99975 19.9995L2.99976 20.9995L3.99977 15.9995Z" stroke="#333333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M4.49976 15.9995L7.99975 19.4995" stroke="#333333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M6.49976 17.4995L17.4998 6.4995" stroke="#333333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
6
+ const BOOKMARK_ICON_SVG = `<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 3C0 1.34315 1.34315 0 3 0H27C28.6569 0 30 1.34315 30 3V38.1989C30 38.9837 29.1374 39.4627 28.4713 39.0477L15 30.6562L1.52873 39.0477C0.862627 39.4627 0 38.9837 0 38.1989L0 3Z" fill="#4FCEBB"/></svg>`;
4
7
  const EBOOK_PLAYER_CSS = `
5
8
  .hyepl-root{position:relative;max-width:100%;margin:0 auto;color:#0f172a;font-size:14px;line-height:1.7}
6
9
  .hyepl-content{position:relative}
@@ -8,12 +11,23 @@ const EBOOK_PLAYER_CSS = `
8
11
  .hyepl-page:last-child{margin-bottom:0}
9
12
  .hyepl-block{margin:0 0 10px;white-space:pre-wrap;word-break:break-word}
10
13
  .hyepl-block:last-child{margin-bottom:0}
14
+ .hyepl-block-text{position:relative;padding-right:18px}
11
15
  .hyepl-block-muted{color:#64748b}
12
16
  .hyepl-highlight{background:var(--hyepl-highlight-color,#fff59d);color:inherit;padding:0 .08em;border-radius:.2em}
13
17
  .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}
18
+ .hyepl-bookmark-flag{position:absolute;top:4px;right:0;display:inline-flex;align-items:center;justify-content:center;width:12px;height:16px;pointer-events:none;user-select:none}
19
+ .hyepl-bookmark-flag svg{display:block;width:12px;height:16px}
20
+ .hyepl-selection-toolbar{position:fixed;z-index:10060;display:none;align-items:stretch;gap:0;padding:8px 10px;border-radius:14px;border:1px solid #e5e7eb;background:#ffffff;box-shadow:0 10px 24px rgba(15,23,42,.14);transform:translate(-50%,-100%);overflow:visible}
21
+ .hyepl-selection-toolbar.show{display:flex}
22
+ .hyepl-selection-toolbar:after{content:"";position:absolute;bottom:-10px;left:50%;transform:translateX(-50%);border-width:10px 10px 0 10px;border-style:solid;border-color:#ffffff transparent transparent transparent;filter:drop-shadow(0 1px 0 #e5e7eb);pointer-events:none}
23
+
24
+ .hyepl-toolbar-btn{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;width:57px;height:67px;padding:10px 8px 8px;border:0;border-radius:10px;background:transparent;color:#111827;cursor:pointer;transition:background .2s ease,color .2s ease}
25
+ .hyepl-toolbar-btn:hover{background:#f3f4f6}
26
+ .hyepl-toolbar-btn:focus-visible{outline:2px solid #38bdf8;outline-offset:2px}
27
+ .hyepl-toolbar-divider{align-self:stretch;width:1px;margin:6px 8px;background:#e5e7eb}
28
+ .hyepl-toolbar-icon{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px}
29
+ .hyepl-toolbar-icon svg{display:block;width:24px;height:24px}
30
+ .hyepl-toolbar-text{font-size:14px;font-weight:700;color:#111827}
17
31
  `;
18
32
  export class EBookPlayer {
19
33
  constructor(container, options) {
@@ -41,6 +55,7 @@ export class EBookPlayer {
41
55
  const runtimeProvider = createRuntimeProvider(options.provider, () => this.runtimeDocument);
42
56
  this.engine = new PlayerEngine(runtimeProvider, options.engineOptions);
43
57
  this.selectionOptions = this.resolveSelectionToolbarOptions(options.selectionToolbar);
58
+ this.inputLimits = this.resolveInputLimits(options.inputLimits);
44
59
  ensureEBookPlayerStyles();
45
60
  this.root = document.createElement("section");
46
61
  this.root.className = "hyepl-root";
@@ -52,14 +67,17 @@ export class EBookPlayer {
52
67
  this.highlightBtn = document.createElement("button");
53
68
  this.highlightBtn.type = "button";
54
69
  this.highlightBtn.className = "hyepl-toolbar-btn";
55
- this.highlightBtn.textContent = this.selectionOptions.highlightButtonText;
70
+ this.setToolbarButtonContent(this.highlightBtn, HIGHLIGHT_ICON_SVG, this.selectionOptions.highlightButtonText);
56
71
  this.highlightBtn.setAttribute("aria-label", this.selectionOptions.highlightButtonText);
72
+ this.toolbarDivider = document.createElement("div");
73
+ this.toolbarDivider.className = "hyepl-toolbar-divider";
74
+ this.toolbarDivider.setAttribute("aria-hidden", "true");
57
75
  this.noteBtn = document.createElement("button");
58
76
  this.noteBtn.type = "button";
59
77
  this.noteBtn.className = "hyepl-toolbar-btn";
60
- this.noteBtn.textContent = this.selectionOptions.noteButtonText;
78
+ this.setToolbarButtonContent(this.noteBtn, NOTE_ICON_SVG, this.selectionOptions.noteButtonText);
61
79
  this.noteBtn.setAttribute("aria-label", this.selectionOptions.noteButtonText);
62
- this.selectionToolbar.append(this.highlightBtn, this.noteBtn);
80
+ this.selectionToolbar.append(this.highlightBtn, this.toolbarDivider, this.noteBtn);
63
81
  this.root.append(this.content, this.selectionToolbar);
64
82
  this.container.innerHTML = "";
65
83
  this.container.append(this.root);
@@ -113,6 +131,9 @@ export class EBookPlayer {
113
131
  getNotes() {
114
132
  return this.engine.getNotes();
115
133
  }
134
+ getBookmarks() {
135
+ return this.engine.getBookmarks();
136
+ }
116
137
  async setAnnotations(annotations, source = "api") {
117
138
  this.ensureLoaded();
118
139
  const all = await this.engine.setAnnotations(annotations, source);
@@ -161,6 +182,28 @@ export class EBookPlayer {
161
182
  this.renderDocument();
162
183
  return deleted;
163
184
  }
185
+ async setBookmark(pageId, blockId, source = "api") {
186
+ this.ensureLoaded();
187
+ this.ensureTextBlockExists(pageId, blockId);
188
+ const current = this.findBookmarkByBlock(pageId, blockId);
189
+ const content = this.promptTextWithLimit("请输入书签内容", current?.content || "", this.inputLimits.bookmarkMaxLength);
190
+ if (content === null) {
191
+ return null;
192
+ }
193
+ const bookmark = await this.engine.setBookmark(pageId, blockId, content, source);
194
+ this.renderDocument();
195
+ return bookmark;
196
+ }
197
+ async deleteBookmark(bookmarkId, source = "api") {
198
+ this.ensureLoaded();
199
+ const deleted = await this.engine.deleteBookmark(bookmarkId, source);
200
+ this.renderDocument();
201
+ return deleted;
202
+ }
203
+ goToBookmark(bookmarkId) {
204
+ this.ensureLoaded();
205
+ return this.engine.goToBookmark(bookmarkId);
206
+ }
164
207
  onAnnotationCreate(listener) {
165
208
  return this.engine.onAnnotationCreate(listener);
166
209
  }
@@ -209,8 +252,12 @@ export class EBookPlayer {
209
252
  const blockKey = this.toBlockKey(pageId, block.id);
210
253
  const highlights = buckets.highlightsByBlock.get(blockKey) || [];
211
254
  const notes = buckets.notesByBlock.get(blockKey) || [];
255
+ const bookmark = buckets.bookmarksByBlock.get(blockKey) || null;
212
256
  this.applyHighlightMarks(blockTextNode, highlights);
213
257
  this.applyNoteMarks(blockTextNode, notes);
258
+ if (bookmark) {
259
+ this.applyBookmarkMarker(blockTextNode, bookmark);
260
+ }
214
261
  return blockTextNode;
215
262
  }
216
263
  renderNonTextBlock(block) {
@@ -241,6 +288,7 @@ export class EBookPlayer {
241
288
  createAnnotationBuckets(annotations) {
242
289
  const highlightsByBlock = new Map();
243
290
  const notesByBlock = new Map();
291
+ const bookmarksByBlock = new Map();
244
292
  annotations.highlights.forEach((item) => {
245
293
  const key = this.toBlockKey(item.pageId, item.blockId);
246
294
  const current = highlightsByBlock.get(key) || [];
@@ -253,7 +301,14 @@ export class EBookPlayer {
253
301
  current.push(item);
254
302
  notesByBlock.set(key, current);
255
303
  });
256
- return { highlightsByBlock, notesByBlock };
304
+ const bookmarks = Array.isArray(annotations.bookmarks)
305
+ ? annotations.bookmarks
306
+ : [];
307
+ bookmarks.forEach((item) => {
308
+ const key = this.toBlockKey(item.pageId, item.blockId);
309
+ bookmarksByBlock.set(key, item);
310
+ });
311
+ return { highlightsByBlock, notesByBlock, bookmarksByBlock };
257
312
  }
258
313
  toBlockKey(pageId, blockId) {
259
314
  return `${pageId}::${blockId}`;
@@ -297,6 +352,15 @@ export class EBookPlayer {
297
352
  this.wrapRangeWithMark(range, mark);
298
353
  });
299
354
  }
355
+ applyBookmarkMarker(container, bookmark) {
356
+ const marker = document.createElement("span");
357
+ marker.className = "hyepl-bookmark-flag";
358
+ marker.dataset.bookmarkId = bookmark.id;
359
+ marker.title = bookmark.content;
360
+ marker.setAttribute("aria-label", `书签:${bookmark.content}`);
361
+ marker.innerHTML = BOOKMARK_ICON_SVG;
362
+ container.append(marker);
363
+ }
300
364
  wrapRangeWithMark(range, mark) {
301
365
  try {
302
366
  range.surroundContents(mark);
@@ -403,7 +467,7 @@ export class EBookPlayer {
403
467
  text: selection.toString().trim(),
404
468
  };
405
469
  this.selectionToolbar.style.left = `${Math.round(rect.left + rect.width / 2)}px`;
406
- this.selectionToolbar.style.top = `${Math.round(rect.top - 8)}px`;
470
+ this.selectionToolbar.style.top = `${Math.round(rect.top - 20)}px`;
407
471
  this.selectionToolbar.classList.add("show");
408
472
  }
409
473
  resolveTextContainer(node) {
@@ -485,9 +549,8 @@ export class EBookPlayer {
485
549
  return;
486
550
  }
487
551
  const defaultText = this.selectionDraft.text || "";
488
- const noteText = window.prompt("请输入笔记内容", defaultText);
489
- const content = noteText?.trim();
490
- if (!content) {
552
+ const content = this.promptTextWithLimit("请输入笔记内容", defaultText, this.inputLimits.noteMaxLength);
553
+ if (content === null) {
491
554
  return;
492
555
  }
493
556
  const payload = {
@@ -534,6 +597,72 @@ export class EBookPlayer {
534
597
  : "#0e7490",
535
598
  };
536
599
  }
600
+ resolveInputLimits(options) {
601
+ const noteMaxLength = this.normalizeLimitValue(options?.noteMaxLength, 100);
602
+ const bookmarkMaxLength = this.normalizeLimitValue(options?.bookmarkMaxLength, 100);
603
+ return {
604
+ noteMaxLength,
605
+ bookmarkMaxLength,
606
+ };
607
+ }
608
+ normalizeLimitValue(value, fallback) {
609
+ if (!Number.isFinite(value)) {
610
+ return fallback;
611
+ }
612
+ return Math.max(1, Math.floor(value));
613
+ }
614
+ promptTextWithLimit(title, defaultText, maxLength) {
615
+ let nextDefault = defaultText;
616
+ while (true) {
617
+ const raw = window.prompt(`${title}(最多${maxLength}字)`, nextDefault);
618
+ if (raw === null) {
619
+ return null;
620
+ }
621
+ const trimmed = raw.trim();
622
+ if (!trimmed) {
623
+ window.alert("内容不能为空");
624
+ nextDefault = "";
625
+ continue;
626
+ }
627
+ if (trimmed.length > maxLength) {
628
+ window.alert(`最多输入${maxLength}字,当前${trimmed.length}字。`);
629
+ nextDefault = trimmed.slice(0, maxLength);
630
+ continue;
631
+ }
632
+ return trimmed;
633
+ }
634
+ }
635
+ ensureTextBlockExists(pageId, blockId) {
636
+ const doc = this.engine.getDocument();
637
+ const page = doc.pages.find((item) => item.id === pageId);
638
+ if (!page) {
639
+ throw new Error(`Page not found: ${pageId}`);
640
+ }
641
+ const block = page.blocks.find((item) => item.id === blockId);
642
+ if (!block) {
643
+ throw new Error(`Block not found: ${blockId}`);
644
+ }
645
+ if (block.type !== "text") {
646
+ throw new Error("Bookmark is only supported on text blocks.");
647
+ }
648
+ }
649
+ findBookmarkByBlock(pageId, blockId) {
650
+ const found = this.engine
651
+ .getBookmarks()
652
+ .find((item) => item.pageId === pageId && item.blockId === blockId);
653
+ return found || null;
654
+ }
655
+ setToolbarButtonContent(button, iconSvg, labelText) {
656
+ button.innerHTML = "";
657
+ const icon = document.createElement("span");
658
+ icon.className = "hyepl-toolbar-icon";
659
+ icon.setAttribute("aria-hidden", "true");
660
+ icon.innerHTML = iconSvg;
661
+ const text = document.createElement("span");
662
+ text.className = "hyepl-toolbar-text";
663
+ text.textContent = labelText;
664
+ button.append(icon, text);
665
+ }
537
666
  ensureLoaded() {
538
667
  if (!this.loaded) {
539
668
  throw new Error("Document is not loaded. Call load() first.");
@@ -598,6 +727,16 @@ function createRuntimeProvider(provider, getRuntimeDocument) {
598
727
  saveNotes: (bookId, notes) => provider.saveNotes(bookId, notes),
599
728
  }
600
729
  : {}),
730
+ ...(provider?.loadBookmarks
731
+ ? {
732
+ loadBookmarks: (bookId) => provider.loadBookmarks(bookId),
733
+ }
734
+ : {}),
735
+ ...(provider?.saveBookmarks
736
+ ? {
737
+ saveBookmarks: (bookId, bookmarks) => provider.saveBookmarks(bookId, bookmarks),
738
+ }
739
+ : {}),
601
740
  ...(provider?.onError
602
741
  ? {
603
742
  onError: (error) => provider.onError(error),
@@ -1,10 +1,11 @@
1
1
  import type { EbookDoc } from "../types/ebook";
2
- import type { ReaderAnnotationChangeSource, ReaderAnnotationCreateEvent, ReaderAnnotationDeleteEvent, ReaderAnnotations, ReaderAnnotationsChangeEvent, ReaderAnnotationUpdateEvent, ReaderHighlight, PlayerDataProvider, PlayerEngineOptions, PlayerFeatures, ReaderNote, ReaderProgress } from "../types/player";
2
+ import type { ReaderAnnotationCreateEvent, ReaderAnnotationDeleteEvent, ReaderAnnotations, ReaderAnnotationsChangeEvent, ReaderAnnotationUpdateEvent, ReaderBookmark, ReaderHighlight, PlayerDataProvider, PlayerEngineOptions, PlayerFeatures, ReaderNote, ReaderProgress } from "../types/player";
3
3
  export interface PlayerState {
4
4
  currentPage: number;
5
5
  zoom: number;
6
6
  highlights: ReaderHighlight[];
7
7
  notes: ReaderNote[];
8
+ bookmarks: ReaderBookmark[];
8
9
  progress: ReaderProgress | null;
9
10
  }
10
11
  type AnnotationCreateListener = (event: ReaderAnnotationCreateEvent) => void;
@@ -26,25 +27,29 @@ export declare class PlayerEngine {
26
27
  getState(): PlayerState;
27
28
  getHighlights(): ReaderHighlight[];
28
29
  getNotes(): ReaderNote[];
30
+ getBookmarks(): ReaderBookmark[];
29
31
  getAnnotations(): ReaderAnnotations;
30
32
  getFeatures(): Required<PlayerFeatures>;
31
33
  isBuiltInNotesModuleEnabled(): boolean;
32
34
  reloadAnnotations(): Promise<ReaderAnnotations>;
33
- setAnnotations(annotations: ReaderAnnotations, source?: ReaderAnnotationChangeSource): Promise<ReaderAnnotations>;
35
+ setAnnotations(annotations: ReaderAnnotations, source?: "api" | "user"): Promise<ReaderAnnotations>;
34
36
  goToHighlight(highlightId: string): number | null;
35
37
  goToNote(noteId: string): number | null;
38
+ goToBookmark(bookmarkId: string): number | null;
36
39
  goToPage(index: number): number;
37
40
  nextPage(): number;
38
41
  prevPage(): number;
39
42
  setZoom(zoom: number): number;
40
43
  saveProgress(): Promise<void>;
41
- createHighlight(highlight: Omit<ReaderHighlight, "id" | "createdAt" | "updatedAt" | "bookId">, source?: ReaderAnnotationChangeSource): Promise<ReaderHighlight>;
42
- updateHighlight(highlightId: string, patch: Partial<Omit<ReaderHighlight, "id" | "bookId" | "createdAt">>, source?: ReaderAnnotationChangeSource): Promise<ReaderHighlight | null>;
43
- deleteHighlight(highlightId: string, source?: ReaderAnnotationChangeSource): Promise<boolean>;
44
+ createHighlight(highlight: Omit<ReaderHighlight, "id" | "createdAt" | "updatedAt" | "bookId">, source?: "api" | "user"): Promise<ReaderHighlight>;
45
+ updateHighlight(highlightId: string, patch: Partial<Omit<ReaderHighlight, "id" | "bookId" | "createdAt">>, source?: "api" | "user"): Promise<ReaderHighlight | null>;
46
+ deleteHighlight(highlightId: string, source?: "api" | "user"): Promise<boolean>;
44
47
  addNote(note: Omit<ReaderNote, "id" | "createdAt" | "updatedAt" | "bookId">): Promise<ReaderNote>;
45
- createNote(note: Omit<ReaderNote, "id" | "createdAt" | "updatedAt" | "bookId">, source?: ReaderAnnotationChangeSource): Promise<ReaderNote>;
46
- updateNote(noteId: string, patch: Partial<Omit<ReaderNote, "id" | "bookId" | "createdAt">>, source?: ReaderAnnotationChangeSource): Promise<ReaderNote | null>;
47
- deleteNote(noteId: string, source?: ReaderAnnotationChangeSource): Promise<boolean>;
48
+ createNote(note: Omit<ReaderNote, "id" | "createdAt" | "updatedAt" | "bookId">, source?: "api" | "user"): Promise<ReaderNote>;
49
+ updateNote(noteId: string, patch: Partial<Omit<ReaderNote, "id" | "bookId" | "createdAt">>, source?: "api" | "user"): Promise<ReaderNote | null>;
50
+ deleteNote(noteId: string, source?: "api" | "user"): Promise<boolean>;
51
+ setBookmark(pageId: string, blockId: string, content: string, source?: "api" | "user"): Promise<ReaderBookmark>;
52
+ deleteBookmark(bookmarkId: string, source?: "api" | "user"): Promise<boolean>;
48
53
  onAnnotationCreate(listener: AnnotationCreateListener): () => void;
49
54
  onAnnotationUpdate(listener: AnnotationUpdateListener): () => void;
50
55
  onAnnotationDelete(listener: AnnotationDeleteListener): () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../../../core/src/player/engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../../../core/src/player/engine.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,7 @@ export class PlayerEngine {
10
10
  zoom: 1,
11
11
  highlights: [],
12
12
  notes: [],
13
+ bookmarks: [],
13
14
  progress: null,
14
15
  };
15
16
  this.annotationCreateListeners = new Set();
@@ -50,10 +51,14 @@ export class PlayerEngine {
50
51
  getNotes() {
51
52
  return clone(this.state.notes);
52
53
  }
54
+ getBookmarks() {
55
+ return clone(this.state.bookmarks);
56
+ }
53
57
  getAnnotations() {
54
58
  return {
55
59
  highlights: this.getHighlights(),
56
60
  notes: this.getNotes(),
61
+ bookmarks: this.getBookmarks(),
57
62
  };
58
63
  }
59
64
  getFeatures() {
@@ -76,6 +81,7 @@ export class PlayerEngine {
76
81
  const normalized = this.normalizeAnnotations(annotations, this.doc.id);
77
82
  this.state.highlights = normalized.highlights;
78
83
  this.state.notes = normalized.notes;
84
+ this.state.bookmarks = normalized.bookmarks || [];
79
85
  await this.persistAnnotations();
80
86
  const all = this.getAnnotations();
81
87
  this.emitAnnotationsChange({
@@ -90,6 +96,12 @@ export class PlayerEngine {
90
96
  source,
91
97
  all,
92
98
  });
99
+ this.emitAnnotationsChange({
100
+ action: "update",
101
+ kind: "bookmark",
102
+ source,
103
+ all,
104
+ });
93
105
  return all;
94
106
  }
95
107
  goToHighlight(highlightId) {
@@ -108,6 +120,14 @@ export class PlayerEngine {
108
120
  const pageIndex = this.findPageIndexByPageId(target.pageId);
109
121
  return pageIndex >= 0 ? this.goToPage(pageIndex) : null;
110
122
  }
123
+ goToBookmark(bookmarkId) {
124
+ const target = this.state.bookmarks.find((item) => item.id === bookmarkId);
125
+ if (!target) {
126
+ return null;
127
+ }
128
+ const pageIndex = this.findPageIndexByPageId(target.pageId);
129
+ return pageIndex >= 0 ? this.goToPage(pageIndex) : null;
130
+ }
111
131
  goToPage(index) {
112
132
  const doc = this.getDocument();
113
133
  const safeIndex = Math.max(0, Math.min(index, doc.pages.length - 1));
@@ -133,14 +153,14 @@ export class PlayerEngine {
133
153
  bookId: this.doc.id,
134
154
  lastPage: this.state.currentPage,
135
155
  zoom: this.state.zoom,
136
- updatedAt: new Date().toISOString(),
156
+ updatedAt: Date.now(),
137
157
  };
138
158
  this.state.progress = progress;
139
159
  await this.provider.saveProgress(progress);
140
160
  }
141
161
  async createHighlight(highlight, source = "api") {
142
162
  const doc = this.getDocument();
143
- const now = new Date().toISOString();
163
+ const now = Date.now();
144
164
  const nextHighlight = {
145
165
  ...highlight,
146
166
  range: this.normalizeRange(highlight.range),
@@ -169,7 +189,7 @@ export class PlayerEngine {
169
189
  id: current.id,
170
190
  bookId: current.bookId,
171
191
  createdAt: current.createdAt,
172
- updatedAt: new Date().toISOString(),
192
+ updatedAt: Date.now(),
173
193
  range: patch.range ? this.normalizeRange(patch.range) : current.range,
174
194
  };
175
195
  this.state.highlights[index] = nextHighlight;
@@ -195,7 +215,7 @@ export class PlayerEngine {
195
215
  }
196
216
  async createNote(note, source = "api") {
197
217
  const doc = this.getDocument();
198
- const now = new Date().toISOString();
218
+ const now = Date.now();
199
219
  const nextNote = {
200
220
  ...note,
201
221
  id: `note-${Date.now()}`,
@@ -223,7 +243,7 @@ export class PlayerEngine {
223
243
  id: current.id,
224
244
  bookId: current.bookId,
225
245
  createdAt: current.createdAt,
226
- updatedAt: new Date().toISOString(),
246
+ updatedAt: Date.now(),
227
247
  ...(patch.range ? { range: this.normalizeRange(patch.range) } : {}),
228
248
  };
229
249
  this.state.notes[index] = nextNote;
@@ -244,6 +264,53 @@ export class PlayerEngine {
244
264
  this.emitAnnotationDelete("note", removedNote, source);
245
265
  return true;
246
266
  }
267
+ async setBookmark(pageId, blockId, content, source = "api") {
268
+ const doc = this.getDocument();
269
+ const now = Date.now();
270
+ const normalizedContent = content.trim();
271
+ const index = this.state.bookmarks.findIndex((item) => item.pageId === pageId && item.blockId === blockId);
272
+ if (index >= 0) {
273
+ const current = this.state.bookmarks[index];
274
+ if (!current) {
275
+ throw new Error("Bookmark update failed.");
276
+ }
277
+ const updatedBookmark = {
278
+ ...current,
279
+ content: normalizedContent,
280
+ updatedAt: now,
281
+ };
282
+ this.state.bookmarks[index] = updatedBookmark;
283
+ await this.persistAnnotations();
284
+ this.emitAnnotationUpdate("bookmark", current, updatedBookmark, source);
285
+ return clone(updatedBookmark);
286
+ }
287
+ const nextBookmark = {
288
+ id: `bookmark-${Date.now()}`,
289
+ bookId: doc.id,
290
+ pageId,
291
+ blockId,
292
+ content: normalizedContent,
293
+ createdAt: now,
294
+ updatedAt: now,
295
+ };
296
+ this.state.bookmarks.push(nextBookmark);
297
+ await this.persistAnnotations();
298
+ this.emitAnnotationCreate("bookmark", nextBookmark, source);
299
+ return clone(nextBookmark);
300
+ }
301
+ async deleteBookmark(bookmarkId, source = "api") {
302
+ const index = this.state.bookmarks.findIndex((item) => item.id === bookmarkId);
303
+ if (index < 0) {
304
+ return false;
305
+ }
306
+ const [removedBookmark] = this.state.bookmarks.splice(index, 1);
307
+ if (!removedBookmark) {
308
+ return false;
309
+ }
310
+ await this.persistAnnotations();
311
+ this.emitAnnotationDelete("bookmark", removedBookmark, source);
312
+ return true;
313
+ }
247
314
  onAnnotationCreate(listener) {
248
315
  this.annotationCreateListeners.add(listener);
249
316
  return () => {
@@ -275,9 +342,13 @@ export class PlayerEngine {
275
342
  if (this.provider.loadProgress) {
276
343
  const progress = await this.provider.loadProgress(this.doc.id);
277
344
  if (progress) {
278
- this.state.progress = progress;
279
- this.state.currentPage = progress.lastPage;
280
- this.state.zoom = progress.zoom;
345
+ const normalizedProgress = {
346
+ ...progress,
347
+ updatedAt: toTimestamp(progress.updatedAt, Date.now()),
348
+ };
349
+ this.state.progress = normalizedProgress;
350
+ this.state.currentPage = normalizedProgress.lastPage;
351
+ this.state.zoom = normalizedProgress.zoom;
281
352
  }
282
353
  }
283
354
  await this.loadAnnotationsState();
@@ -293,6 +364,7 @@ export class PlayerEngine {
293
364
  const normalized = this.normalizeAnnotations(annotations, this.doc.id);
294
365
  this.state.highlights = normalized.highlights;
295
366
  this.state.notes = normalized.notes;
367
+ this.state.bookmarks = normalized.bookmarks || [];
296
368
  restoredFromAnnotationsProvider = true;
297
369
  }
298
370
  }
@@ -300,11 +372,25 @@ export class PlayerEngine {
300
372
  const fromDocument = this.mapPreviewAnnotationsToReader(this.doc.meta.previewAnnotations, this.doc.id);
301
373
  this.state.highlights = fromDocument.highlights;
302
374
  this.state.notes = fromDocument.notes;
375
+ this.state.bookmarks = fromDocument.bookmarks || [];
303
376
  if (this.provider.loadNotes) {
304
377
  const notes = await this.provider.loadNotes(this.doc.id);
305
- this.state.notes = Array.isArray(notes) ? clone(notes) : [];
378
+ const normalized = this.normalizeAnnotations({
379
+ highlights: [],
380
+ notes: Array.isArray(notes) ? notes : [],
381
+ }, this.doc.id);
382
+ this.state.notes = normalized.notes;
306
383
  }
307
384
  }
385
+ if (this.provider.loadBookmarks) {
386
+ const bookmarks = await this.provider.loadBookmarks(this.doc.id);
387
+ const normalized = this.normalizeAnnotations({
388
+ highlights: [],
389
+ notes: [],
390
+ bookmarks: Array.isArray(bookmarks) ? bookmarks : [],
391
+ }, this.doc.id);
392
+ this.state.bookmarks = normalized.bookmarks || [];
393
+ }
308
394
  }
309
395
  findPageIndexByPageId(pageId) {
310
396
  if (!this.doc) {
@@ -320,14 +406,19 @@ export class PlayerEngine {
320
406
  : { start: safeEnd, end: safeStart };
321
407
  }
322
408
  normalizeAnnotations(annotations, bookId) {
323
- const now = new Date().toISOString();
409
+ const now = Date.now();
324
410
  const highlights = Array.isArray(annotations?.highlights)
325
411
  ? annotations.highlights
326
412
  : [];
327
413
  const notes = Array.isArray(annotations?.notes) ? annotations.notes : [];
414
+ const bookmarks = Array.isArray(annotations?.bookmarks)
415
+ ? annotations.bookmarks
416
+ : [];
328
417
  return {
329
418
  highlights: highlights.map((item, index) => {
330
419
  const fallbackId = `highlight-${Date.now()}-${index}`;
420
+ const createdAt = toTimestamp(item.createdAt, now);
421
+ const updatedAt = toTimestamp(item.updatedAt, createdAt);
331
422
  return {
332
423
  ...clone(item),
333
424
  id: item.id || fallbackId,
@@ -335,12 +426,14 @@ export class PlayerEngine {
335
426
  pageId: item.pageId || "",
336
427
  blockId: item.blockId || "preview-flow-text",
337
428
  range: this.normalizeRange(item.range),
338
- createdAt: item.createdAt || now,
339
- updatedAt: item.updatedAt || item.createdAt || now,
429
+ createdAt,
430
+ updatedAt,
340
431
  };
341
432
  }),
342
433
  notes: notes.map((item, index) => {
343
434
  const fallbackId = `note-${Date.now()}-${index}`;
435
+ const createdAt = toTimestamp(item.createdAt, now);
436
+ const updatedAt = toTimestamp(item.updatedAt, createdAt);
344
437
  return {
345
438
  ...clone(item),
346
439
  id: item.id || fallbackId,
@@ -349,17 +442,34 @@ export class PlayerEngine {
349
442
  blockId: item.blockId || "preview-flow-text",
350
443
  ...(item.range ? { range: this.normalizeRange(item.range) } : {}),
351
444
  content: item.content || "",
352
- createdAt: item.createdAt || now,
353
- updatedAt: item.updatedAt || item.createdAt || now,
445
+ createdAt,
446
+ updatedAt,
447
+ };
448
+ }),
449
+ bookmarks: bookmarks.map((item, index) => {
450
+ const fallbackId = `bookmark-${Date.now()}-${index}`;
451
+ const createdAt = toTimestamp(item.createdAt, now);
452
+ const updatedAt = toTimestamp(item.updatedAt, createdAt);
453
+ return {
454
+ ...clone(item),
455
+ id: item.id || fallbackId,
456
+ bookId: item.bookId || bookId || "",
457
+ pageId: item.pageId || "",
458
+ blockId: item.blockId || "",
459
+ content: item.content || "",
460
+ createdAt,
461
+ updatedAt,
354
462
  };
355
463
  }),
356
464
  };
357
465
  }
358
466
  mapPreviewAnnotationsToReader(annotations, bookId) {
359
- const now = new Date().toISOString();
467
+ const now = Date.now();
360
468
  const safe = annotations || { highlights: [], notes: [] };
361
469
  const highlights = safe.highlights.map((item, index) => {
362
470
  const range = this.normalizeRange({ start: item.start, end: item.end });
471
+ const createdAt = toTimestamp(item.createdAt, now);
472
+ const updatedAt = toTimestamp(item.updatedAt, createdAt);
363
473
  return {
364
474
  id: item.id || `highlight-preview-${index}`,
365
475
  bookId,
@@ -370,12 +480,14 @@ export class PlayerEngine {
370
480
  ? { selectedText: item.selectedText }
371
481
  : {}),
372
482
  ...(item.color !== undefined ? { color: item.color } : {}),
373
- createdAt: item.createdAt || now,
374
- updatedAt: item.updatedAt || item.createdAt || now,
483
+ createdAt,
484
+ updatedAt,
375
485
  };
376
486
  });
377
487
  const notes = safe.notes.map((item, index) => {
378
488
  const range = this.normalizeRange({ start: item.start, end: item.end });
489
+ const createdAt = toTimestamp(item.createdAt, now);
490
+ const updatedAt = toTimestamp(item.updatedAt, createdAt);
379
491
  return {
380
492
  id: item.id || `note-preview-${index}`,
381
493
  bookId,
@@ -384,13 +496,14 @@ export class PlayerEngine {
384
496
  range,
385
497
  content: item.text,
386
498
  ...(item.color !== undefined ? { color: item.color } : {}),
387
- createdAt: item.createdAt || now,
388
- updatedAt: item.updatedAt || item.createdAt || now,
499
+ createdAt,
500
+ updatedAt,
389
501
  };
390
502
  });
391
503
  return {
392
504
  highlights,
393
505
  notes,
506
+ bookmarks: [],
394
507
  };
395
508
  }
396
509
  async persistAnnotations() {
@@ -405,6 +518,9 @@ export class PlayerEngine {
405
518
  if (this.provider.saveNotes) {
406
519
  await this.provider.saveNotes(this.doc.id, all.notes);
407
520
  }
521
+ if (this.provider.saveBookmarks) {
522
+ await this.provider.saveBookmarks(this.doc.id, all.bookmarks || []);
523
+ }
408
524
  }
409
525
  emitAnnotationCreate(kind, annotation, source) {
410
526
  const all = this.getAnnotations();
@@ -479,6 +595,26 @@ function toError(error) {
479
595
  }
480
596
  return new Error(String(error));
481
597
  }
598
+ function toTimestamp(value, fallback) {
599
+ if (typeof value === "number" && Number.isFinite(value)) {
600
+ return Math.floor(value);
601
+ }
602
+ if (typeof value === "string") {
603
+ const trimmed = value.trim();
604
+ if (!trimmed) {
605
+ return fallback;
606
+ }
607
+ const numeric = Number(trimmed);
608
+ if (Number.isFinite(numeric)) {
609
+ return Math.floor(numeric);
610
+ }
611
+ const parsed = Date.parse(trimmed);
612
+ if (Number.isFinite(parsed)) {
613
+ return parsed;
614
+ }
615
+ }
616
+ return fallback;
617
+ }
482
618
  function clone(value) {
483
619
  return JSON.parse(JSON.stringify(value));
484
620
  }
@@ -7,7 +7,7 @@ export interface ReaderProgress {
7
7
  bookId: string;
8
8
  lastPage: number;
9
9
  zoom: number;
10
- updatedAt: string;
10
+ updatedAt: number;
11
11
  }
12
12
  export interface ReaderNote {
13
13
  id: string;
@@ -17,8 +17,8 @@ export interface ReaderNote {
17
17
  range?: ReaderRange;
18
18
  content: string;
19
19
  color?: string;
20
- createdAt: string;
21
- updatedAt: string;
20
+ createdAt: number;
21
+ updatedAt: number;
22
22
  }
23
23
  export interface ReaderHighlight {
24
24
  id: string;
@@ -28,40 +28,49 @@ export interface ReaderHighlight {
28
28
  range: ReaderRange;
29
29
  selectedText?: string;
30
30
  color?: string;
31
- createdAt: string;
32
- updatedAt: string;
31
+ createdAt: number;
32
+ updatedAt: number;
33
+ }
34
+ export interface ReaderBookmark {
35
+ id: string;
36
+ bookId: string;
37
+ pageId: string;
38
+ blockId: string;
39
+ content: string;
40
+ createdAt: number;
41
+ updatedAt: number;
33
42
  }
34
43
  export interface ReaderAnnotations {
35
44
  highlights: ReaderHighlight[];
36
45
  notes: ReaderNote[];
46
+ bookmarks?: ReaderBookmark[];
37
47
  }
38
- export type ReaderAnnotationKind = "highlight" | "note";
48
+ export type ReaderAnnotationKind = "highlight" | "note" | "bookmark";
39
49
  export type ReaderAnnotationAction = "create" | "update" | "delete";
40
- export type ReaderAnnotationChangeSource = "api" | "user";
41
- export type ReaderAnnotation = ReaderHighlight | ReaderNote;
50
+ export type ReaderAnnotation = ReaderHighlight | ReaderNote | ReaderBookmark;
42
51
  export interface ReaderAnnotationCreateEvent {
43
52
  kind: ReaderAnnotationKind;
44
- source: ReaderAnnotationChangeSource;
53
+ source: "api" | "user";
45
54
  annotation: ReaderAnnotation;
46
55
  all: ReaderAnnotations;
47
56
  }
48
57
  export interface ReaderAnnotationUpdateEvent {
49
58
  kind: ReaderAnnotationKind;
50
- source: ReaderAnnotationChangeSource;
59
+ source: "api" | "user";
51
60
  previous: ReaderAnnotation;
52
61
  current: ReaderAnnotation;
53
62
  all: ReaderAnnotations;
54
63
  }
55
64
  export interface ReaderAnnotationDeleteEvent {
56
65
  kind: ReaderAnnotationKind;
57
- source: ReaderAnnotationChangeSource;
66
+ source: "api" | "user";
58
67
  annotation: ReaderAnnotation;
59
68
  all: ReaderAnnotations;
60
69
  }
61
70
  export interface ReaderAnnotationsChangeEvent {
62
71
  action: ReaderAnnotationAction;
63
72
  kind: ReaderAnnotationKind;
64
- source: ReaderAnnotationChangeSource;
73
+ source: "api" | "user";
65
74
  all: ReaderAnnotations;
66
75
  current?: ReaderAnnotation;
67
76
  previous?: ReaderAnnotation;
@@ -79,6 +88,10 @@ export interface EBookPlayerSelectionToolbarOptions {
79
88
  highlightColor?: string;
80
89
  noteColor?: string;
81
90
  }
91
+ export interface EBookPlayerInputLimitsOptions {
92
+ noteMaxLength?: number;
93
+ bookmarkMaxLength?: number;
94
+ }
82
95
  export interface PlayerDataProvider {
83
96
  getData: () => Promise<EbookDoc>;
84
97
  loadProgress?: (bookId: string) => Promise<ReaderProgress | null>;
@@ -87,6 +100,8 @@ export interface PlayerDataProvider {
87
100
  saveAnnotations?: (bookId: string, annotations: ReaderAnnotations) => Promise<void>;
88
101
  loadNotes?: (bookId: string) => Promise<ReaderNote[]>;
89
102
  saveNotes?: (bookId: string, notes: ReaderNote[]) => Promise<void>;
103
+ loadBookmarks?: (bookId: string) => Promise<ReaderBookmark[]>;
104
+ saveBookmarks?: (bookId: string, bookmarks: ReaderBookmark[]) => Promise<void>;
90
105
  onError?: (error: Error) => void;
91
106
  }
92
107
  export interface EBookPlayerOptions {
@@ -95,6 +110,7 @@ export interface EBookPlayerOptions {
95
110
  width?: number;
96
111
  initialAnnotations?: ReaderAnnotations;
97
112
  selectionToolbar?: EBookPlayerSelectionToolbarOptions;
113
+ inputLimits?: EBookPlayerInputLimitsOptions;
98
114
  }
99
115
  export interface EBookPlayerHandle {
100
116
  load: (doc?: EbookDoc) => Promise<EbookDoc>;
@@ -103,14 +119,18 @@ export interface EBookPlayerHandle {
103
119
  getAnnotations: () => ReaderAnnotations;
104
120
  getHighlights: () => ReaderHighlight[];
105
121
  getNotes: () => ReaderNote[];
106
- setAnnotations: (annotations: ReaderAnnotations, source?: ReaderAnnotationChangeSource) => Promise<ReaderAnnotations>;
122
+ getBookmarks: () => ReaderBookmark[];
123
+ setAnnotations: (annotations: ReaderAnnotations, source?: "api" | "user") => Promise<ReaderAnnotations>;
107
124
  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>;
125
+ createHighlight: (highlight: Omit<ReaderHighlight, "id" | "createdAt" | "updatedAt" | "bookId">, source?: "api" | "user") => Promise<ReaderHighlight>;
126
+ updateHighlight: (highlightId: string, patch: Partial<Omit<ReaderHighlight, "id" | "bookId" | "createdAt">>, source?: "api" | "user") => Promise<ReaderHighlight | null>;
127
+ deleteHighlight: (highlightId: string, source?: "api" | "user") => Promise<boolean>;
128
+ createNote: (note: Omit<ReaderNote, "id" | "createdAt" | "updatedAt" | "bookId">, source?: "api" | "user") => Promise<ReaderNote>;
129
+ updateNote: (noteId: string, patch: Partial<Omit<ReaderNote, "id" | "bookId" | "createdAt">>, source?: "api" | "user") => Promise<ReaderNote | null>;
130
+ deleteNote: (noteId: string, source?: "api" | "user") => Promise<boolean>;
131
+ setBookmark: (pageId: string, blockId: string, source?: "api" | "user") => Promise<ReaderBookmark | null>;
132
+ deleteBookmark: (bookmarkId: string, source?: "api" | "user") => Promise<boolean>;
133
+ goToBookmark: (bookmarkId: string) => number | null;
114
134
  onAnnotationCreate: (listener: (event: ReaderAnnotationCreateEvent) => void) => () => void;
115
135
  onAnnotationUpdate: (listener: (event: ReaderAnnotationUpdateEvent) => void) => () => void;
116
136
  onAnnotationDelete: (listener: (event: ReaderAnnotationDeleteEvent) => void) => () => void;
@@ -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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"}
@@ -5817,6 +5817,9 @@ function buildDocxStyleContext(stylesXml, themeXml) {
5817
5817
  const pPr = childXmlNodeByLocalName(styleNode, "pPr");
5818
5818
  const rPr = childXmlNodeByLocalName(styleNode, "rPr");
5819
5819
  const parsedAlign = styleType === "paragraph" ? parseDocxParagraphAlign(pPr) : undefined;
5820
+ const parsedIndent = styleType === "paragraph"
5821
+ ? parseDocxParagraphIndent(pPr, defaultTextStyle.fontSize)
5822
+ : undefined;
5820
5823
  const parsedParagraphType = styleType === "paragraph"
5821
5824
  ? resolveParagraphTypeFromDocxStyle(styleId, styleName)
5822
5825
  : undefined;
@@ -5831,15 +5834,18 @@ function buildDocxStyleContext(stylesXml, themeXml) {
5831
5834
  type: styleType,
5832
5835
  ...(basedOn ? { basedOn } : {}),
5833
5836
  ...(parsedAlign ? { align: parsedAlign } : {}),
5837
+ ...(parsedIndent !== undefined ? { indent: parsedIndent } : {}),
5834
5838
  ...(parsedParagraphType ? { paragraphType: parsedParagraphType } : {}),
5835
5839
  marks: tableRunMarks,
5836
5840
  };
5837
5841
  }
5838
5842
  const defaultParagraphAlign = parseDocxParagraphAlign(defaultsParagraphProps);
5843
+ const defaultParagraphIndent = parseDocxParagraphIndent(defaultsParagraphProps, defaultTextStyle.fontSize);
5839
5844
  return {
5840
5845
  defaultTextStyle,
5841
5846
  defaultMarks,
5842
5847
  ...(defaultParagraphAlign ? { defaultParagraphAlign } : {}),
5848
+ ...(defaultParagraphIndent !== undefined ? { defaultParagraphIndent } : {}),
5843
5849
  themeColorMap,
5844
5850
  styles,
5845
5851
  };
@@ -5849,10 +5855,14 @@ function parseDocxParagraphElement(paragraphNode, index, styleContext, extraInhe
5849
5855
  const paragraphStyleId = xmlAttribute(childXmlNodeByLocalName(pPr, "pStyle"), "val");
5850
5856
  const paragraphStyle = resolveDocxStyle(styleContext, paragraphStyleId, "paragraph");
5851
5857
  const directAlign = parseDocxParagraphAlign(pPr);
5858
+ const directIndent = parseDocxParagraphIndent(pPr, styleContext.defaultTextStyle.fontSize);
5852
5859
  const paragraphAlign = directAlign ||
5853
5860
  paragraphStyle?.align ||
5854
5861
  styleContext.defaultParagraphAlign ||
5855
5862
  "left";
5863
+ const paragraphIndent = directIndent ??
5864
+ paragraphStyle?.indent ??
5865
+ styleContext.defaultParagraphIndent;
5856
5866
  const paragraphTypeByStyle = paragraphStyle?.paragraphType || "p";
5857
5867
  const paragraphBaseMarks = mergeTextMarks(styleContext.defaultMarks, extraInheritedMarks, paragraphStyle?.marks, parseDocxRunMarks(childXmlNodeByLocalName(pPr, "rPr"), styleContext.themeColorMap));
5858
5868
  // Keep imported size fidelity first: if style chain already carries explicit
@@ -5863,6 +5873,7 @@ function parseDocxParagraphElement(paragraphNode, index, styleContext, extraInhe
5863
5873
  id: `p-${Date.now()}-${index}`,
5864
5874
  type: paragraphType,
5865
5875
  align: paragraphAlign,
5876
+ ...(paragraphIndent !== undefined ? { indent: paragraphIndent } : {}),
5866
5877
  runs: applyImportedDefaultTextStyle(runs, styleContext.defaultTextStyle),
5867
5878
  };
5868
5879
  }
@@ -5993,6 +6004,59 @@ function parseDocxParagraphAlign(paragraphProps) {
5993
6004
  }
5994
6005
  return undefined;
5995
6006
  }
6007
+ function parseDocxParagraphIndent(paragraphProps, baseFontSizePx) {
6008
+ if (!paragraphProps) {
6009
+ return undefined;
6010
+ }
6011
+ const indentNode = childXmlNodeByLocalName(paragraphProps, "ind");
6012
+ if (!indentNode) {
6013
+ return undefined;
6014
+ }
6015
+ const firstLineChars = parseDocxHundredthCharIndent(xmlAttribute(indentNode, "firstLineChars"));
6016
+ if (firstLineChars !== undefined) {
6017
+ return firstLineChars;
6018
+ }
6019
+ const hangingChars = parseDocxHundredthCharIndent(xmlAttribute(indentNode, "hangingChars"));
6020
+ if (hangingChars !== undefined) {
6021
+ return -hangingChars;
6022
+ }
6023
+ const resolvedBaseFontSizePx = typeof baseFontSizePx === "number" &&
6024
+ Number.isFinite(baseFontSizePx) &&
6025
+ baseFontSizePx > 0
6026
+ ? baseFontSizePx
6027
+ : 16;
6028
+ const firstLineTwip = parseDocxTwip(xmlAttribute(indentNode, "firstLine"));
6029
+ if (firstLineTwip !== undefined) {
6030
+ return convertDocxTwipToEm(firstLineTwip, resolvedBaseFontSizePx);
6031
+ }
6032
+ const hangingTwip = parseDocxTwip(xmlAttribute(indentNode, "hanging"));
6033
+ if (hangingTwip !== undefined) {
6034
+ return -convertDocxTwipToEm(hangingTwip, resolvedBaseFontSizePx);
6035
+ }
6036
+ return undefined;
6037
+ }
6038
+ function parseDocxHundredthCharIndent(raw) {
6039
+ if (!raw) {
6040
+ return undefined;
6041
+ }
6042
+ const value = Number.parseFloat(raw);
6043
+ if (!Number.isFinite(value)) {
6044
+ return undefined;
6045
+ }
6046
+ return Number.parseFloat((value / 100).toFixed(2));
6047
+ }
6048
+ function parseDocxTwip(raw) {
6049
+ if (!raw) {
6050
+ return undefined;
6051
+ }
6052
+ const value = Number.parseFloat(raw);
6053
+ return Number.isFinite(value) ? value : undefined;
6054
+ }
6055
+ function convertDocxTwipToEm(twip, baseFontSizePx) {
6056
+ const px = (twip * 96) / (72 * 20);
6057
+ const em = px / baseFontSizePx;
6058
+ return Number.parseFloat(em.toFixed(2));
6059
+ }
5996
6060
  function resolveParagraphTypeFromDocxStyle(styleId, styleName) {
5997
6061
  const normalized = `${styleId} ${styleName}`.toLowerCase();
5998
6062
  if (normalized.includes("heading 1") ||
@@ -6061,10 +6125,12 @@ function resolveDocxStyle(styleContext, styleId, type, visited = new Set()) {
6061
6125
  ? parent.paragraphType
6062
6126
  : entry.paragraphType || parent.paragraphType;
6063
6127
  const align = entry.align || parent.align;
6128
+ const indent = entry.indent !== undefined ? entry.indent : parent.indent;
6064
6129
  return {
6065
6130
  ...entry,
6066
6131
  marks: mergeTextMarks(parent.marks, entry.marks),
6067
6132
  ...(align ? { align } : {}),
6133
+ ...(indent !== undefined ? { indent } : {}),
6068
6134
  ...(paragraphType ? { paragraphType } : {}),
6069
6135
  };
6070
6136
  }
@@ -6316,6 +6382,9 @@ function resolveDocxTableCellStyle(cellProps, themeColorMap, rowHeight, tableBor
6316
6382
  resolvedCellBorders[side] = borderStyle;
6317
6383
  }
6318
6384
  }
6385
+ if (!Object.keys(resolvedCellBorders).length) {
6386
+ styleTokens.push("border:1px solid #000000");
6387
+ }
6319
6388
  const shadingNode = childXmlNodeByLocalName(cellProps, "shd");
6320
6389
  const fillColor = normalizeImportedCssColor(xmlAttribute(shadingNode, "fill") || "") ||
6321
6390
  themeColorMap[xmlAttribute(shadingNode, "themeFill") || ""];
@@ -6403,7 +6472,7 @@ function resolveDocxBorderStyle(borderNode, themeColorMap) {
6403
6472
  const themeColor = xmlAttribute(borderNode, "themeColor") || "";
6404
6473
  const color = (themeColor && themeColorMap[themeColor]) ||
6405
6474
  normalizeImportedCssColor(colorRaw) ||
6406
- "#cbd5e1";
6475
+ "#000000";
6407
6476
  return `${widthPx}px ${style} ${color}`;
6408
6477
  }
6409
6478
  function resolveDocxTableWidthPx(tableProps) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyebook/vue3-adapter",
3
- "version": "2.3.1",
3
+ "version": "2.3.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": "^2.3.1"
20
+ "@hyebook/core": "^2.3.2"
21
21
  },
22
22
  "scripts": {
23
23
  "build": "tsc -p tsconfig.json",