@prose-reader/core 1.139.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
  });
@@ -2921,6 +2930,18 @@
2921
2930
  this.removeIllegalOpts();
2922
2931
  }
2923
2932
  }
2933
+ static getTextArea() {
2934
+ if (!_CfiHandler.tempTextArea) {
2935
+ if (!_CfiHandler.tempDocument) {
2936
+ _CfiHandler.tempDocument = document.implementation.createHTMLDocument();
2937
+ }
2938
+ _CfiHandler.tempTextArea = _CfiHandler.tempDocument.createElement("textarea");
2939
+ }
2940
+ return _CfiHandler.tempTextArea;
2941
+ }
2942
+ destroy() {
2943
+ _CfiHandler.tempTextArea = null;
2944
+ }
2924
2945
  removeIllegalOpts(parts) {
2925
2946
  if (!parts) {
2926
2947
  if (this.from) {
@@ -2943,15 +2964,6 @@
2943
2964
  }
2944
2965
  }
2945
2966
  }
2946
- static getTextArea() {
2947
- if (!_CfiHandler.tempTextArea) {
2948
- if (!_CfiHandler.tempDocument) {
2949
- _CfiHandler.tempDocument = document.implementation.createHTMLDocument();
2950
- }
2951
- _CfiHandler.tempTextArea = _CfiHandler.tempDocument.createElement("textarea");
2952
- }
2953
- return _CfiHandler.tempTextArea;
2954
- }
2955
2967
  static generatePart(node, offset, extra) {
2956
2968
  let cfi = ``;
2957
2969
  let o;
@@ -3660,6 +3672,7 @@
3660
3672
  if (doc) {
3661
3673
  try {
3662
3674
  const { node, offset: resolvedOffset } = cfiHandler.resolve(doc, {});
3675
+ cfiHandler.destroy();
3663
3676
  return {
3664
3677
  node,
3665
3678
  offset: offset ?? resolvedOffset,
@@ -5557,10 +5570,25 @@
5557
5570
  layout(params) {
5558
5571
  return rxjs.defer(() => this.onLayout(params)).pipe(
5559
5572
  rxjs.map((dims) => {
5560
- const { height, width } = dims ?? this.lastLayoutDims ?? { height: 0, width: 0 };
5561
- const minHeight = Math.max(height, this.context.getPageSize().height);
5562
- const minWidth = Math.max(width, params.minimumWidth);
5563
- 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
+ }
5564
5592
  return this.lastLayoutDims;
5565
5593
  })
5566
5594
  );
@@ -6510,7 +6538,7 @@
6510
6538
  layoutInProgress.next(true);
6511
6539
  const manifest = this.context.manifest;
6512
6540
  const newItemLayoutInformation = [];
6513
- const isGloballyPrePaginated = (manifest == null ? void 0 : manifest.renditionLayout) === `pre-paginated`;
6541
+ const isGloballyPrePaginated = isFullyPrePaginated(manifest) ?? false;
6514
6542
  return rxjs.from(this.spineItemsManager.items).pipe(
6515
6543
  rxjs.reduce(
6516
6544
  (acc$, item, index) => acc$.pipe(
@@ -7399,7 +7427,7 @@
7399
7427
  if (!item) return;
7400
7428
  const frame = item.renderer.getDocumentFrame();
7401
7429
  if (!frame) return;
7402
- upsertCSS(
7430
+ upsertCSSToFrame(
7403
7431
  frame,
7404
7432
  `prose-reader-accessibility`,
7405
7433
  `
@@ -7961,7 +7989,7 @@
7961
7989
  },
7962
7990
  viewportDimensions
7963
7991
  );
7964
- upsertCSS(frameElement, `prose-reader-css`, cssLink);
7992
+ upsertCSSToFrame(frameElement, `prose-reader-css`, cssLink);
7965
7993
  if (viewportDimensions) {
7966
7994
  staticLayout$1(frameElement, {
7967
7995
  width: viewportDimensions.width ?? 1,
@@ -8242,7 +8270,7 @@
8242
8270
  let contentWidth = pageWidth;
8243
8271
  let contentHeight = pageHeight;
8244
8272
  if (viewportDimensions == null ? void 0 : viewportDimensions.hasViewport) {
8245
- upsertCSS(
8273
+ upsertCSSToFrame(
8246
8274
  frameElement,
8247
8275
  `prose-reader-html-renderer-framce-css`,
8248
8276
  buildStyleForViewportFrame()
@@ -8277,7 +8305,7 @@
8277
8305
  pageWidth
8278
8306
  })
8279
8307
  );
8280
- upsertCSS(frameElement, `prose-reader-css`, frameStyle, true);
8308
+ upsertCSSToFrame(frameElement, `prose-reader-css`, frameStyle, true);
8281
8309
  if (isUsingVerticalWriting) {
8282
8310
  const pages = Math.ceil(
8283
8311
  frameElement.contentDocument.documentElement.scrollHeight / pageHeight
@@ -8593,92 +8621,136 @@
8593
8621
  return void 0;
8594
8622
  }
8595
8623
  };
8596
- class SelectionTracker extends DestroyableClass {
8597
- constructor(document2) {
8624
+ class FrameSelectionTracker extends DestroyableClass {
8625
+ constructor(frame) {
8626
+ var _a;
8598
8627
  super();
8599
- this.selectionChange$ = rxjs.fromEvent(document2, "selectionchange").pipe(
8600
- rxjs.map(() => document2.getSelection())
8601
- );
8602
- this.selectionOver$ = rxjs.fromEvent(document2, "pointerdown").pipe(
8603
- rxjs.switchMap(
8604
- () => rxjs.merge(
8605
- rxjs.fromEvent(document2, "pointerup"),
8606
- rxjs.fromEvent(document2, "pointercancel"),
8607
- rxjs.fromEvent(document2, "contextmenu")
8608
- ).pipe(
8609
- rxjs.first(),
8610
- /**
8611
- * The selection is still valid during the event even if it will
8612
- * be discarded. The timeout make sure to detect this edge case.
8613
- */
8614
- rxjs.delay(0),
8615
- rxjs.map((event) => {
8616
- const selection = document2.getSelection();
8617
- return selection && !selection.isCollapsed ? [event, selection] : void 0;
8618
- }),
8619
- 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
+ })
8620
8641
  )
8621
- )
8622
- );
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
+ }
8623
8683
  }
8624
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
+ );
8625
8724
  const selectionEnhancer = (next) => (options) => {
8626
8725
  const reader = next(options);
8627
- const selectionSubject = new rxjs.BehaviorSubject(
8628
- void 0
8629
- );
8630
- const selectionOverSubject = new rxjs.Subject();
8631
- reader.hookManager.register(
8632
- `item.onDocumentLoad`,
8633
- ({ itemId, destroy$, destroy }) => {
8634
- var _a;
8635
- const item = reader.spineItemsManager.get(itemId);
8636
- const frame = item == null ? void 0 : item.renderer.getDocumentFrame();
8637
- const itemIndex = reader.spineItemsManager.getSpineItemIndex(itemId) ?? 0;
8638
- if (frame) {
8639
- const frameDoc = frame.contentDocument || ((_a = frame.contentWindow) == null ? void 0 : _a.document);
8640
- if (frameDoc) {
8641
- const selectionTracker = new SelectionTracker(frameDoc);
8642
- rxjs.merge(
8643
- selectionTracker.selectionChange$.pipe(
8644
- rxjs.tap((selection) => {
8645
- if (selection == null ? void 0 : selection.toString()) {
8646
- selectionSubject.next({
8647
- document: frameDoc,
8648
- selection,
8649
- itemIndex
8650
- });
8651
- } else {
8652
- selectionSubject.next(void 0);
8653
- }
8654
- })
8655
- ),
8656
- selectionTracker.selectionOver$.pipe(
8657
- rxjs.tap(([event, selection]) => {
8658
- selectionOverSubject.next([
8659
- event,
8660
- {
8661
- document: frameDoc,
8662
- selection,
8663
- itemIndex
8664
- }
8665
- ]);
8666
- })
8667
- )
8668
- ).pipe(rxjs.takeUntil(destroy$)).subscribe();
8669
- destroy(() => {
8670
- selectionTracker.destroy();
8671
- });
8672
- }
8673
- }
8674
- }
8675
- );
8676
- 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
+ }),
8677
8743
  rxjs.distinctUntilChanged(),
8678
- rxjs.shareReplay(1),
8679
- rxjs.takeUntil(reader.$.destroy$)
8744
+ rxjs.tap((value) => {
8745
+ lasSelection = value;
8746
+ }),
8747
+ rxjs.shareReplay({ refCount: true, bufferSize: 1 })
8680
8748
  );
8681
- const selectionStart$ = selectionSubject.pipe(
8749
+ const selection$ = trackedSelection$.pipe(
8750
+ rxjs.filter((selection) => (selection == null ? void 0 : selection.type) === "change" || !selection),
8751
+ rxjs.share()
8752
+ );
8753
+ const selectionStart$ = trackedSelection$.pipe(
8682
8754
  rxjs.map((selection) => !!selection),
8683
8755
  rxjs.distinctUntilChanged(),
8684
8756
  rxjs.filter((isSelecting) => isSelecting),
@@ -8690,15 +8762,18 @@
8690
8762
  rxjs.filter((selection) => !selection),
8691
8763
  rxjs.share()
8692
8764
  );
8693
- const selectionOver$ = selectionOverSubject.asObservable();
8765
+ const selectionOver$ = trackedSelection$.pipe(
8766
+ rxjs.filter((selection) => (selection == null ? void 0 : selection.type) === "over"),
8767
+ rxjs.share()
8768
+ );
8694
8769
  const lastSelectionOnPointerdown$ = reader.context.containerElement$.pipe(
8695
8770
  rxjs.switchMap((container) => rxjs.fromEvent(container, "pointerdown")),
8696
8771
  rxjs.withLatestFrom(selection$),
8697
8772
  rxjs.map(([, selection]) => selection),
8698
8773
  rxjs.startWith(void 0),
8699
- rxjs.shareReplay(1),
8700
- rxjs.takeUntil(reader.$.destroy$)
8774
+ rxjs.shareReplay(1)
8701
8775
  );
8776
+ selection$.pipe(rxjs.takeUntil(reader.$.destroy$)).subscribe();
8702
8777
  return {
8703
8778
  ...reader,
8704
8779
  selection: {
@@ -8707,12 +8782,8 @@
8707
8782
  selectionEnd$,
8708
8783
  selectionOver$,
8709
8784
  lastSelectionOnPointerdown$,
8710
- getSelection: () => selectionSubject.getValue(),
8785
+ getSelection: () => lasSelection,
8711
8786
  createOrderedRangeFromSelection
8712
- },
8713
- destroy: () => {
8714
- selectionSubject.complete();
8715
- reader.destroy();
8716
8787
  }
8717
8788
  };
8718
8789
  };
@@ -8779,9 +8850,10 @@
8779
8850
  exports2.injectCSS = injectCSS;
8780
8851
  exports2.isHtmlElement = isHtmlElement;
8781
8852
  exports2.mapKeysTo = mapKeysTo;
8853
+ exports2.observeMutation = observeMutation;
8782
8854
  exports2.observeResize = observeResize;
8783
8855
  exports2.removeCSS = removeCSS;
8784
- exports2.upsertCSS = upsertCSS;
8856
+ exports2.upsertCSSToFrame = upsertCSSToFrame;
8785
8857
  exports2.waitForFrameLoad = waitForFrameLoad;
8786
8858
  exports2.waitForFrameReady = waitForFrameReady;
8787
8859
  exports2.waitForSwitch = waitForSwitch;