@prose-reader/core 1.140.0 → 1.141.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.
@@ -89,6 +89,15 @@
89
89
  function deferIdle(callback) {
90
90
  return rxjs.defer(() => idle().pipe(operators.switchMap(callback)));
91
91
  }
92
+ const observeMutation = (target, options) => {
93
+ return new rxjs.Observable((subscriber) => {
94
+ const observer = new MutationObserver((mutations) => {
95
+ subscriber.next(mutations);
96
+ });
97
+ observer.observe(target, options);
98
+ return () => observer.disconnect();
99
+ });
100
+ };
92
101
  class SettingsManagerOverload {
93
102
  constructor(initialSettings, settingsManager) {
94
103
  this.settingsManager = settingsManager;
@@ -194,7 +203,7 @@
194
203
  };
195
204
  const injectCSS = (frameElement, id, style, prepend) => {
196
205
  if (frameElement && frameElement.contentDocument && frameElement.contentDocument.head) {
197
- const userStyle = document.createElement(`style`);
206
+ const userStyle = frameElement.contentDocument.createElement(`style`);
198
207
  userStyle.id = id;
199
208
  userStyle.innerHTML = style;
200
209
  if (prepend) {
@@ -212,7 +221,7 @@
212
221
  }
213
222
  }
214
223
  };
215
- const upsertCSS = (frameElement, id, style, prepend) => {
224
+ const upsertCSSToFrame = (frameElement, id, style, prepend) => {
216
225
  if (!frameElement) return;
217
226
  removeCSS(frameElement, id);
218
227
  injectCSS(frameElement, id, style, prepend);
@@ -293,7 +302,7 @@
293
302
  if (item.renditionLayout !== `pre-paginated`) {
294
303
  const frame = item.renderer.getDocumentFrame();
295
304
  if (frame) {
296
- upsertCSS(frame, `prose-reader-fonts`, getStyle());
305
+ upsertCSSToFrame(frame, `prose-reader-fonts`, getStyle());
297
306
  }
298
307
  }
299
308
  });
@@ -306,7 +315,7 @@
306
315
  if ((item == null ? void 0 : item.renditionLayout) !== `pre-paginated`) {
307
316
  const frame = item == null ? void 0 : item.renderer.getDocumentFrame();
308
317
  if (frame) {
309
- upsertCSS(frame, `prose-reader-fonts`, getStyle());
318
+ upsertCSSToFrame(frame, `prose-reader-fonts`, getStyle());
310
319
  }
311
320
  }
312
321
  });
@@ -531,7 +540,7 @@
531
540
  }
532
541
  const frame = spineItem == null ? void 0 : spineItem.renderer.getDocumentFrame();
533
542
  if (frame) {
534
- upsertCSS(
543
+ upsertCSSToFrame(
535
544
  frame,
536
545
  `prose-layout-enhancer-css`,
537
546
  `
@@ -1695,7 +1704,7 @@
1695
1704
  reader.spineItemsManager.items.forEach((item) => {
1696
1705
  const frame = item.renderer.getDocumentFrame();
1697
1706
  if (frame) {
1698
- upsertCSS(frame, `prose-reader-theme`, getStyle());
1707
+ upsertCSSToFrame(frame, `prose-reader-theme`, getStyle());
1699
1708
  }
1700
1709
  applyChangeToSpineItemElement({ container: item.element });
1701
1710
  });
@@ -1705,7 +1714,7 @@
1705
1714
  if ((item == null ? void 0 : item.renditionLayout) !== "pre-paginated") {
1706
1715
  const frame = item == null ? void 0 : item.renderer.getDocumentFrame();
1707
1716
  if (frame) {
1708
- upsertCSS(frame, `prose-reader-theme`, getStyle());
1717
+ upsertCSSToFrame(frame, `prose-reader-theme`, getStyle());
1709
1718
  }
1710
1719
  }
1711
1720
  });
@@ -5561,10 +5570,25 @@
5561
5570
  layout(params) {
5562
5571
  return rxjs.defer(() => this.onLayout(params)).pipe(
5563
5572
  rxjs.map((dims) => {
5564
- const { height, width } = dims ?? this.lastLayoutDims ?? { height: 0, width: 0 };
5565
- const minHeight = Math.max(height, this.context.getPageSize().height);
5566
- const minWidth = Math.max(width, params.minimumWidth);
5567
- this.lastLayoutDims = { height: minHeight, width: minWidth };
5573
+ var _a, _b;
5574
+ const isPrepaginated = this.item.renditionLayout === `pre-paginated` || !((_a = this.context.manifest) == null ? void 0 : _a.renditionLayout) && ((_b = this.context.manifest) == null ? void 0 : _b.renditionLayout) === `pre-paginated`;
5575
+ if (dims) {
5576
+ const { height, width } = dims;
5577
+ this.lastLayoutDims = { height, width };
5578
+ return this.lastLayoutDims;
5579
+ }
5580
+ if (isPrepaginated) {
5581
+ this.lastLayoutDims = {
5582
+ height: this.context.getPageSize().height,
5583
+ width: this.context.getPageSize().width
5584
+ };
5585
+ } else {
5586
+ this.lastLayoutDims = {
5587
+ height: this.context.getPageSize().height,
5588
+ width: this.context.getPageSize().width,
5589
+ ...this.lastLayoutDims
5590
+ };
5591
+ }
5568
5592
  return this.lastLayoutDims;
5569
5593
  })
5570
5594
  );
@@ -6514,7 +6538,7 @@
6514
6538
  layoutInProgress.next(true);
6515
6539
  const manifest = this.context.manifest;
6516
6540
  const newItemLayoutInformation = [];
6517
- const isGloballyPrePaginated = (manifest == null ? void 0 : manifest.renditionLayout) === `pre-paginated`;
6541
+ const isGloballyPrePaginated = isFullyPrePaginated(manifest) ?? false;
6518
6542
  return rxjs.from(this.spineItemsManager.items).pipe(
6519
6543
  rxjs.reduce(
6520
6544
  (acc$, item, index) => acc$.pipe(
@@ -7403,7 +7427,7 @@
7403
7427
  if (!item) return;
7404
7428
  const frame = item.renderer.getDocumentFrame();
7405
7429
  if (!frame) return;
7406
- upsertCSS(
7430
+ upsertCSSToFrame(
7407
7431
  frame,
7408
7432
  `prose-reader-accessibility`,
7409
7433
  `
@@ -7965,7 +7989,7 @@
7965
7989
  },
7966
7990
  viewportDimensions
7967
7991
  );
7968
- upsertCSS(frameElement, `prose-reader-css`, cssLink);
7992
+ upsertCSSToFrame(frameElement, `prose-reader-css`, cssLink);
7969
7993
  if (viewportDimensions) {
7970
7994
  staticLayout$1(frameElement, {
7971
7995
  width: viewportDimensions.width ?? 1,
@@ -8246,7 +8270,7 @@
8246
8270
  let contentWidth = pageWidth;
8247
8271
  let contentHeight = pageHeight;
8248
8272
  if (viewportDimensions == null ? void 0 : viewportDimensions.hasViewport) {
8249
- upsertCSS(
8273
+ upsertCSSToFrame(
8250
8274
  frameElement,
8251
8275
  `prose-reader-html-renderer-framce-css`,
8252
8276
  buildStyleForViewportFrame()
@@ -8281,7 +8305,7 @@
8281
8305
  pageWidth
8282
8306
  })
8283
8307
  );
8284
- upsertCSS(frameElement, `prose-reader-css`, frameStyle, true);
8308
+ upsertCSSToFrame(frameElement, `prose-reader-css`, frameStyle, true);
8285
8309
  if (isUsingVerticalWriting) {
8286
8310
  const pages = Math.ceil(
8287
8311
  frameElement.contentDocument.documentElement.scrollHeight / pageHeight
@@ -8597,92 +8621,136 @@
8597
8621
  return void 0;
8598
8622
  }
8599
8623
  };
8600
- class SelectionTracker extends DestroyableClass {
8601
- constructor(document2) {
8624
+ class FrameSelectionTracker extends DestroyableClass {
8625
+ constructor(frame) {
8626
+ var _a;
8602
8627
  super();
8603
- this.selectionChange$ = rxjs.fromEvent(document2, "selectionchange").pipe(
8604
- rxjs.map(() => document2.getSelection())
8605
- );
8606
- this.selectionOver$ = rxjs.fromEvent(document2, "pointerdown").pipe(
8607
- rxjs.switchMap(
8608
- () => rxjs.merge(
8609
- rxjs.fromEvent(document2, "pointerup"),
8610
- rxjs.fromEvent(document2, "pointercancel"),
8611
- rxjs.fromEvent(document2, "contextmenu")
8612
- ).pipe(
8613
- rxjs.first(),
8614
- /**
8615
- * The selection is still valid during the event even if it will
8616
- * be discarded. The timeout make sure to detect this edge case.
8617
- */
8618
- rxjs.delay(0),
8619
- rxjs.map((event) => {
8620
- const selection = document2.getSelection();
8621
- return selection && !selection.isCollapsed ? [event, selection] : void 0;
8622
- }),
8623
- rxjs.filter(isDefined)
8628
+ const frameDoc = frame.contentDocument || ((_a = frame.contentWindow) == null ? void 0 : _a.document);
8629
+ if (!frameDoc) {
8630
+ this.selectionChange$ = rxjs.NEVER;
8631
+ this.selectionOver$ = rxjs.NEVER;
8632
+ } else {
8633
+ const frameDocMutation$ = observeMutation(frameDoc.body, {
8634
+ childList: true,
8635
+ subtree: true
8636
+ }).pipe(
8637
+ rxjs.filter(
8638
+ (mutations) => !!mutations.find((mutation) => {
8639
+ return mutation.type === "childList" && mutation.removedNodes.length;
8640
+ })
8624
8641
  )
8625
- )
8626
- );
8642
+ );
8643
+ const iframeDestroyed$ = !frame.parentElement ? rxjs.of(null) : observeMutation(frame.parentElement, {
8644
+ childList: true
8645
+ }).pipe(
8646
+ rxjs.filter(
8647
+ (mutation) => !!mutation.find(
8648
+ (mutation2) => Array.from(mutation2.removedNodes).includes(frame)
8649
+ )
8650
+ )
8651
+ );
8652
+ this.selectionChange$ = rxjs.merge(
8653
+ rxjs.fromEvent(frameDoc, "selectionchange"),
8654
+ frameDocMutation$
8655
+ ).pipe(
8656
+ rxjs.map(() => frameDoc.getSelection()),
8657
+ rxjs.takeUntil(rxjs.merge(iframeDestroyed$, this.destroy$)),
8658
+ rxjs.endWith(null)
8659
+ );
8660
+ this.selectionOver$ = rxjs.fromEvent(frameDoc, "pointerdown").pipe(
8661
+ rxjs.switchMap(
8662
+ () => rxjs.merge(
8663
+ rxjs.fromEvent(frameDoc, "pointerup"),
8664
+ rxjs.fromEvent(frameDoc, "pointercancel"),
8665
+ rxjs.fromEvent(frameDoc, "contextmenu")
8666
+ ).pipe(
8667
+ rxjs.first(),
8668
+ /**
8669
+ * The selection is still valid during the event even if it will
8670
+ * be discarded. The timeout make sure to detect this edge case.
8671
+ */
8672
+ rxjs.delay(0),
8673
+ rxjs.map((event) => {
8674
+ const selection = frameDoc.getSelection();
8675
+ return selection && !selection.isCollapsed ? [event, selection] : void 0;
8676
+ }),
8677
+ rxjs.filter(isDefined)
8678
+ )
8679
+ ),
8680
+ rxjs.takeUntil(rxjs.merge(iframeDestroyed$, this.destroy$))
8681
+ );
8682
+ }
8627
8683
  }
8628
8684
  }
8685
+ const trackSpineItemSelection = (spineItem) => spineItem.loaded$.pipe(
8686
+ rxjs.switchMap(() => {
8687
+ var _a;
8688
+ const frame = spineItem.renderer.getDocumentFrame();
8689
+ const frameDoc = (frame == null ? void 0 : frame.contentDocument) || ((_a = frame == null ? void 0 : frame.contentWindow) == null ? void 0 : _a.document);
8690
+ if (!frame || !frameDoc) return rxjs.NEVER;
8691
+ const selectionTracker = new FrameSelectionTracker(frame);
8692
+ return rxjs.merge(
8693
+ selectionTracker.selectionChange$.pipe(
8694
+ rxjs.map((selection) => {
8695
+ if (selection == null ? void 0 : selection.toString()) {
8696
+ return {
8697
+ type: "change",
8698
+ selection
8699
+ };
8700
+ } else {
8701
+ return void 0;
8702
+ }
8703
+ })
8704
+ ),
8705
+ selectionTracker.selectionOver$.pipe(
8706
+ rxjs.map(([event, selection]) => {
8707
+ return {
8708
+ type: "over",
8709
+ event,
8710
+ selection
8711
+ };
8712
+ })
8713
+ )
8714
+ ).pipe(
8715
+ rxjs.takeUntil(spineItem.unloaded$),
8716
+ rxjs.endWith(void 0),
8717
+ rxjs.finalize(() => {
8718
+ selectionTracker.destroy();
8719
+ })
8720
+ );
8721
+ }),
8722
+ rxjs.distinctUntilChanged()
8723
+ );
8629
8724
  const selectionEnhancer = (next) => (options) => {
8630
8725
  const reader = next(options);
8631
- const selectionSubject = new rxjs.BehaviorSubject(
8632
- void 0
8633
- );
8634
- const selectionOverSubject = new rxjs.Subject();
8635
- reader.hookManager.register(
8636
- `item.onDocumentLoad`,
8637
- ({ itemId, destroy$, destroy }) => {
8638
- var _a;
8639
- const item = reader.spineItemsManager.get(itemId);
8640
- const frame = item == null ? void 0 : item.renderer.getDocumentFrame();
8641
- const itemIndex = reader.spineItemsManager.getSpineItemIndex(itemId) ?? 0;
8642
- if (frame) {
8643
- const frameDoc = frame.contentDocument || ((_a = frame.contentWindow) == null ? void 0 : _a.document);
8644
- if (frameDoc) {
8645
- const selectionTracker = new SelectionTracker(frameDoc);
8646
- rxjs.merge(
8647
- selectionTracker.selectionChange$.pipe(
8648
- rxjs.tap((selection) => {
8649
- if (selection == null ? void 0 : selection.toString()) {
8650
- selectionSubject.next({
8651
- document: frameDoc,
8652
- selection,
8653
- itemIndex
8654
- });
8655
- } else {
8656
- selectionSubject.next(void 0);
8657
- }
8658
- })
8659
- ),
8660
- selectionTracker.selectionOver$.pipe(
8661
- rxjs.tap(([event, selection]) => {
8662
- selectionOverSubject.next([
8663
- event,
8664
- {
8665
- document: frameDoc,
8666
- selection,
8667
- itemIndex
8668
- }
8669
- ]);
8670
- })
8671
- )
8672
- ).pipe(rxjs.takeUntil(destroy$)).subscribe();
8673
- destroy(() => {
8674
- selectionTracker.destroy();
8675
- });
8676
- }
8677
- }
8678
- }
8679
- );
8680
- const selection$ = selectionSubject.pipe(
8726
+ let lasSelection = void 0;
8727
+ const trackedSelection$ = reader.spineItemsManager.items$.pipe(
8728
+ rxjs.switchMap((spineItems) => {
8729
+ const instances = spineItems.map((spineItem) => {
8730
+ const itemIndex = reader.spineItemsManager.getSpineItemIndex(spineItem) ?? 0;
8731
+ return trackSpineItemSelection(spineItem).pipe(
8732
+ rxjs.map((entry) => {
8733
+ if (!entry) return void 0;
8734
+ return {
8735
+ ...entry,
8736
+ itemIndex
8737
+ };
8738
+ })
8739
+ );
8740
+ });
8741
+ return rxjs.merge(...instances);
8742
+ }),
8681
8743
  rxjs.distinctUntilChanged(),
8682
- rxjs.shareReplay(1),
8683
- rxjs.takeUntil(reader.$.destroy$)
8744
+ rxjs.tap((value) => {
8745
+ lasSelection = value;
8746
+ }),
8747
+ rxjs.shareReplay({ refCount: true, bufferSize: 1 })
8748
+ );
8749
+ const selection$ = trackedSelection$.pipe(
8750
+ rxjs.filter((selection) => (selection == null ? void 0 : selection.type) === "change" || !selection),
8751
+ rxjs.share()
8684
8752
  );
8685
- const selectionStart$ = selectionSubject.pipe(
8753
+ const selectionStart$ = trackedSelection$.pipe(
8686
8754
  rxjs.map((selection) => !!selection),
8687
8755
  rxjs.distinctUntilChanged(),
8688
8756
  rxjs.filter((isSelecting) => isSelecting),
@@ -8694,15 +8762,18 @@
8694
8762
  rxjs.filter((selection) => !selection),
8695
8763
  rxjs.share()
8696
8764
  );
8697
- const selectionOver$ = selectionOverSubject.asObservable();
8765
+ const selectionOver$ = trackedSelection$.pipe(
8766
+ rxjs.filter((selection) => (selection == null ? void 0 : selection.type) === "over"),
8767
+ rxjs.share()
8768
+ );
8698
8769
  const lastSelectionOnPointerdown$ = reader.context.containerElement$.pipe(
8699
8770
  rxjs.switchMap((container) => rxjs.fromEvent(container, "pointerdown")),
8700
8771
  rxjs.withLatestFrom(selection$),
8701
8772
  rxjs.map(([, selection]) => selection),
8702
8773
  rxjs.startWith(void 0),
8703
- rxjs.shareReplay(1),
8704
- rxjs.takeUntil(reader.$.destroy$)
8774
+ rxjs.shareReplay(1)
8705
8775
  );
8776
+ selection$.pipe(rxjs.takeUntil(reader.$.destroy$)).subscribe();
8706
8777
  return {
8707
8778
  ...reader,
8708
8779
  selection: {
@@ -8711,12 +8782,8 @@
8711
8782
  selectionEnd$,
8712
8783
  selectionOver$,
8713
8784
  lastSelectionOnPointerdown$,
8714
- getSelection: () => selectionSubject.getValue(),
8785
+ getSelection: () => lasSelection,
8715
8786
  createOrderedRangeFromSelection
8716
- },
8717
- destroy: () => {
8718
- selectionSubject.complete();
8719
- reader.destroy();
8720
8787
  }
8721
8788
  };
8722
8789
  };
@@ -8783,9 +8850,10 @@
8783
8850
  exports2.injectCSS = injectCSS;
8784
8851
  exports2.isHtmlElement = isHtmlElement;
8785
8852
  exports2.mapKeysTo = mapKeysTo;
8853
+ exports2.observeMutation = observeMutation;
8786
8854
  exports2.observeResize = observeResize;
8787
8855
  exports2.removeCSS = removeCSS;
8788
- exports2.upsertCSS = upsertCSS;
8856
+ exports2.upsertCSSToFrame = upsertCSSToFrame;
8789
8857
  exports2.waitForFrameLoad = waitForFrameLoad;
8790
8858
  exports2.waitForFrameReady = waitForFrameReady;
8791
8859
  exports2.waitForSwitch = waitForSwitch;