@prose-reader/core 1.53.0 → 1.54.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.
@@ -591,6 +591,63 @@
591
591
  }
592
592
  };
593
593
  };
594
+ const buildChaptersInfo = (href, tocItem, manifest) => {
595
+ const spineItemIndex = manifest.spineItems.findIndex((item) => item.href === href);
596
+ return tocItem.reduce((acc, tocItem2) => {
597
+ const indexOfHash = tocItem2.href.indexOf(`#`);
598
+ const tocItemPathWithoutAnchor = indexOfHash > 0 ? tocItem2.href.substr(0, indexOfHash) : tocItem2.href;
599
+ const tocItemHrefWithoutFilename = tocItemPathWithoutAnchor.substring(0, tocItemPathWithoutAnchor.lastIndexOf("/"));
600
+ const hrefWithoutFilename = href.substring(0, href.lastIndexOf("/"));
601
+ const hrefIsChapterHref = href.endsWith(tocItemPathWithoutAnchor);
602
+ const hrefIsWithinChapter = hrefWithoutFilename !== "" && hrefWithoutFilename.endsWith(tocItemHrefWithoutFilename);
603
+ const isPossibleTocItemCandidate = hrefIsChapterHref || hrefIsWithinChapter;
604
+ if (isPossibleTocItemCandidate) {
605
+ const spineItemIndexOfPossibleCandidate = manifest.spineItems.findIndex((item) => item.href === tocItem2.href);
606
+ const spineItemIsBeforeThisTocItem = spineItemIndex < spineItemIndexOfPossibleCandidate;
607
+ if (spineItemIsBeforeThisTocItem)
608
+ return acc;
609
+ const info = {
610
+ title: tocItem2.title,
611
+ path: tocItem2.path
612
+ };
613
+ const subInfo = buildChaptersInfo(href, tocItem2.contents, manifest);
614
+ if (subInfo) {
615
+ return {
616
+ ...info,
617
+ subChapter: subInfo
618
+ };
619
+ }
620
+ return info;
621
+ }
622
+ return acc;
623
+ }, void 0);
624
+ };
625
+ const buildChapterInfoFromSpineItem = (manifest, item) => {
626
+ var _a;
627
+ const { href } = item;
628
+ return buildChaptersInfo(href, ((_a = manifest.nav) == null ? void 0 : _a.toc) ?? [], manifest);
629
+ };
630
+ const getChaptersInfo = (reader) => {
631
+ const manifest = reader.context.getManifest();
632
+ const items = reader.getSpineItems();
633
+ if (!manifest)
634
+ return {};
635
+ return items.reduce(
636
+ (acc, { item }) => {
637
+ return {
638
+ ...acc,
639
+ [item.id]: buildChapterInfoFromSpineItem(manifest, item)
640
+ };
641
+ },
642
+ {}
643
+ );
644
+ };
645
+ const trackChapterInfo = (reader) => {
646
+ return reader.spineItems$.pipe(
647
+ rxjs.startWith([]),
648
+ rxjs.map(() => getChaptersInfo(reader))
649
+ );
650
+ };
594
651
  const NAMESPACE$6 = `pagination`;
595
652
  const createPagination = ({ context }) => {
596
653
  const paginationSubject$ = new rxjs.BehaviorSubject({
@@ -603,16 +660,16 @@
603
660
  endCfi: void 0,
604
661
  endSpineItemIndex: void 0
605
662
  });
606
- const getSpineItemNumberOfPages = (spineItem) => {
663
+ const getSpineItemNumberOfPages2 = (spineItem) => {
607
664
  const writingMode = spineItem.spineItemFrame.getWritingMode();
608
665
  const { width, height } = spineItem.getElementDimensions();
609
666
  if (writingMode === `vertical-rl`) {
610
- return getNumberOfPages(height, context.getPageSize().height);
667
+ return calculateNumberOfPagesForItem(height, context.getPageSize().height);
611
668
  }
612
- return getNumberOfPages(width, context.getPageSize().width);
669
+ return calculateNumberOfPagesForItem(width, context.getPageSize().width);
613
670
  };
614
671
  const getInfoForUpdate = (info) => {
615
- const numberOfPages = getSpineItemNumberOfPages(info.spineItem);
672
+ const numberOfPages = getSpineItemNumberOfPages2(info.spineItem);
616
673
  return {
617
674
  numberOfPages,
618
675
  pageIndex: info.pageIndex,
@@ -662,103 +719,39 @@
662
719
  const logicalOffset = itemWidth * (pageIndex * pageWidth) / itemWidth;
663
720
  return Math.max(0, Math.min(lastPageOffset, logicalOffset));
664
721
  };
665
- const getNumberOfPages = (itemWidth, pageWidth) => {
722
+ const calculateNumberOfPagesForItem = (itemWidth, pageWidth) => {
666
723
  if ((pageWidth || 0) === 0 || (itemWidth || 0) === 0)
667
724
  return 1;
668
725
  return Math.floor(Math.max(1, itemWidth / pageWidth));
669
726
  };
670
727
  const getClosestValidOffsetFromApproximateOffsetInPages = (offset, pageWidth, itemWidth) => {
671
- const numberOfPages = getNumberOfPages(itemWidth, pageWidth);
728
+ const numberOfPages = calculateNumberOfPagesForItem(itemWidth, pageWidth);
672
729
  const offsetValues = [...Array(numberOfPages)].map((_, i) => i * pageWidth);
673
730
  if (offset >= numberOfPages * pageWidth)
674
731
  return offsetValues[offsetValues.length - 1] || 0;
675
732
  return offsetValues.find((offsetRange) => offset < offsetRange + pageWidth) || 0;
676
733
  };
677
- const NAMESPACE$5 = `paginationEnhancer`;
678
- Report.namespace(NAMESPACE$5);
679
- const paginationEnhancer = (next) => (options) => {
680
- const reader = next(options);
681
- const chaptersInfo = {};
682
- const getChapterInfo2 = (item) => {
683
- const manifest = reader.context.getManifest();
684
- return item && manifest && buildChapterInfoFromSpineItem(manifest, item);
685
- };
686
- const mapPaginationInfoToExtendedInfo = (paginationInfo) => {
687
- const context = reader.context;
688
- const beginItem = paginationInfo.beginSpineItemIndex !== void 0 ? reader.getSpineItem(paginationInfo.beginSpineItemIndex) : void 0;
689
- const endItem = paginationInfo.endSpineItemIndex !== void 0 ? reader.getSpineItem(paginationInfo.endSpineItemIndex) : void 0;
690
- return {
691
- ...paginationInfo,
692
- beginChapterInfo: beginItem ? chaptersInfo[beginItem.item.id] : void 0,
693
- // chapterIndex: number;
694
- // pages: number;
695
- // pageIndexInBook: number;
696
- // pageIndexInChapter: number;
697
- // pagesOfChapter: number;
698
- // pagePercentageInChapter: number;
699
- // offsetPercentageInChapter: number;
700
- // domIndex: number;
701
- // charOffset: number;
702
- // serializeString?: string;
703
- beginSpineItemReadingDirection: beginItem == null ? void 0 : beginItem.getReadingDirection(),
704
- endChapterInfo: endItem ? chaptersInfo[endItem.item.id] : void 0,
705
- endSpineItemReadingDirection: endItem == null ? void 0 : endItem.getReadingDirection(),
706
- // spineItemReadingDirection: focusedSpineItem?.getReadingDirection(),
707
- /**
708
- * This percentage is based of the weight (kb) of every items and the number of pages.
709
- * It is not accurate but gives a general good idea of the overall progress.
710
- * It is recommended to use this progress only for reflow books. For pre-paginated books
711
- * the number of pages and current index can be used instead since 1 page = 1 chapter.
712
- */
713
- percentageEstimateOfBook: endItem ? reader.progression.getPercentageEstimate(
714
- context,
715
- paginationInfo.endSpineItemIndex ?? 0,
716
- paginationInfo.endNumberOfPagesInSpineItem,
717
- paginationInfo.endPageIndexInSpineItem || 0,
718
- reader.getCurrentViewportPosition(),
719
- endItem
720
- ) : 0,
721
- isUsingSpread: context.isUsingSpreadMode() ?? false
722
- // hasNextChapter: (reader.spine.spineItemIndex || 0) < (manifest.readingOrder.length - 1),
723
- // hasPreviousChapter: (reader.spine.spineItemIndex || 0) < (manifest.readingOrder.length - 1),
724
- // numberOfSpineItems: context.getManifest()?.readingOrder.length,
725
- };
726
- };
727
- const getSpineItemNumberOfPages = (spineItem) => {
728
- const writingMode = spineItem.spineItemFrame.getWritingMode();
729
- const { width, height } = spineItem.getElementDimensions();
730
- const settings = reader.settings.getSettings();
731
- if (settings.pageTurnDirection === `vertical` && settings.pageTurnMode === `scrollable`) {
732
- return 1;
733
- }
734
- if (writingMode === `vertical-rl`) {
735
- return getNumberOfPages(height, reader.context.getPageSize().height);
736
- }
737
- return getNumberOfPages(width, reader.context.getPageSize().width);
738
- };
739
- const getNumberOfPagesPerItems = () => reader.getSpineItems().map((item) => {
740
- return getSpineItemNumberOfPages(item);
741
- }, 0);
742
- reader.spineItems$.pipe(
743
- operators.tap(
744
- (items) => items.forEach(({ item }) => {
745
- chaptersInfo[item.id] = getChapterInfo2(item);
746
- })
747
- ),
748
- operators.takeUntil(reader.$.destroy$)
749
- ).subscribe();
750
- const innerPaginationExtendedInfo$ = reader.pagination.paginationInfo$.pipe(
751
- operators.map((info) => ({
752
- ...info,
753
- ...mapPaginationInfoToExtendedInfo(info)
754
- })),
755
- operators.distinctUntilChanged(isShallowEqual)
756
- );
734
+ const getSpineItemNumberOfPages = ({ spineItem, reader }) => {
735
+ const writingMode = spineItem.spineItemFrame.getWritingMode();
736
+ const { width, height } = spineItem.getElementDimensions();
737
+ const settings = reader.settings.getSettings();
738
+ if (settings.pageTurnDirection === `vertical` && settings.pageTurnMode === `scrollable`) {
739
+ return 1;
740
+ }
741
+ if (writingMode === `vertical-rl`) {
742
+ return calculateNumberOfPagesForItem(height, reader.context.getPageSize().height);
743
+ }
744
+ return calculateNumberOfPagesForItem(width, reader.context.getPageSize().width);
745
+ };
746
+ const getNumberOfPagesForAllSpineItems = (reader) => reader.getSpineItems().map((item) => {
747
+ return getSpineItemNumberOfPages({ spineItem: item, reader });
748
+ }, 0);
749
+ const trackTotalPages = (reader) => {
757
750
  const totalPages$ = reader.$.layout$.pipe(
758
- operators.debounceTime(10, rxjs.animationFrameScheduler),
759
- operators.withLatestFrom(reader.pagination.paginationInfo$),
760
- operators.map(() => {
761
- const numberOfPagesPerItems = getNumberOfPagesPerItems();
751
+ rxjs.debounceTime(10, rxjs.animationFrameScheduler),
752
+ rxjs.withLatestFrom(reader.pagination.paginationInfo$),
753
+ rxjs.map(() => {
754
+ const numberOfPagesPerItems = getNumberOfPagesForAllSpineItems(reader);
762
755
  return {
763
756
  numberOfPagesPerItems,
764
757
  /**
@@ -767,69 +760,102 @@
767
760
  numberOfTotalPages: numberOfPagesPerItems.reduce((acc, numberOfPagesForItem) => acc + numberOfPagesForItem, 0)
768
761
  };
769
762
  }),
770
- operators.distinctUntilChanged(isShallowEqual),
771
- operators.startWith({
763
+ rxjs.distinctUntilChanged(isShallowEqual),
764
+ rxjs.startWith({
772
765
  numberOfPagesPerItems: [],
773
766
  numberOfTotalPages: 0
774
767
  })
775
768
  );
776
- const paginationInfo$ = rxjs.combineLatest([
777
- innerPaginationExtendedInfo$,
778
- totalPages$
779
- ]).pipe(
780
- operators.map(([pageInfo, totalPageInfo]) => ({
769
+ return totalPages$;
770
+ };
771
+ const mapPaginationInfoToExtendedInfo = (reader) => (paginationInfo, chaptersInfo) => {
772
+ const context = reader.context;
773
+ const beginItem = paginationInfo.beginSpineItemIndex !== void 0 ? reader.getSpineItem(paginationInfo.beginSpineItemIndex) : void 0;
774
+ const endItem = paginationInfo.endSpineItemIndex !== void 0 ? reader.getSpineItem(paginationInfo.endSpineItemIndex) : void 0;
775
+ return {
776
+ ...paginationInfo,
777
+ beginChapterInfo: beginItem ? chaptersInfo[beginItem.item.id] : void 0,
778
+ // chapterIndex: number;
779
+ // pages: number;
780
+ // pageIndexInBook: number;
781
+ // pageIndexInChapter: number;
782
+ // pagesOfChapter: number;
783
+ // pagePercentageInChapter: number;
784
+ // offsetPercentageInChapter: number;
785
+ // domIndex: number;
786
+ // charOffset: number;
787
+ // serializeString?: string;
788
+ beginSpineItemReadingDirection: beginItem == null ? void 0 : beginItem.getReadingDirection(),
789
+ endChapterInfo: endItem ? chaptersInfo[endItem.item.id] : void 0,
790
+ endSpineItemReadingDirection: endItem == null ? void 0 : endItem.getReadingDirection(),
791
+ // spineItemReadingDirection: focusedSpineItem?.getReadingDirection(),
792
+ /**
793
+ * This percentage is based of the weight (kb) of every items and the number of pages.
794
+ * It is not accurate but gives a general good idea of the overall progress.
795
+ * It is recommended to use this progress only for reflow books. For pre-paginated books
796
+ * the number of pages and current index can be used instead since 1 page = 1 chapter.
797
+ */
798
+ percentageEstimateOfBook: endItem ? reader.progression.getPercentageEstimate(
799
+ context,
800
+ paginationInfo.endSpineItemIndex ?? 0,
801
+ paginationInfo.endNumberOfPagesInSpineItem,
802
+ paginationInfo.endPageIndexInSpineItem || 0,
803
+ reader.getCurrentViewportPosition(),
804
+ endItem
805
+ ) : 0,
806
+ isUsingSpread: context.isUsingSpreadMode() ?? false
807
+ // hasNextChapter: (reader.spine.spineItemIndex || 0) < (manifest.readingOrder.length - 1),
808
+ // hasPreviousChapter: (reader.spine.spineItemIndex || 0) < (manifest.readingOrder.length - 1),
809
+ // numberOfSpineItems: context.getManifest()?.readingOrder.length,
810
+ };
811
+ };
812
+ const trackPaginationInfo = (reader) => {
813
+ const chaptersInfo$ = trackChapterInfo(reader);
814
+ const totalPages$ = trackTotalPages(reader);
815
+ const currentValue = new rxjs.BehaviorSubject({
816
+ ...reader.pagination.getPaginationInfo(),
817
+ ...mapPaginationInfoToExtendedInfo(reader)(reader.pagination.getPaginationInfo(), getChaptersInfo(reader)),
818
+ beginAbsolutePageIndex: 0,
819
+ endAbsolutePageIndex: 0,
820
+ numberOfTotalPages: 0
821
+ });
822
+ const extandedBasePagination$ = reader.pagination.paginationInfo$.pipe(
823
+ rxjs.combineLatestWith(chaptersInfo$),
824
+ rxjs.map(([info, chaptersInfo]) => ({
825
+ ...info,
826
+ ...mapPaginationInfoToExtendedInfo(reader)(info, chaptersInfo)
827
+ })),
828
+ rxjs.distinctUntilChanged(isShallowEqual)
829
+ );
830
+ const paginationInfo$ = rxjs.combineLatest([extandedBasePagination$, totalPages$]).pipe(
831
+ rxjs.map(([pageInfo, totalPageInfo]) => ({
781
832
  ...pageInfo,
782
833
  ...totalPageInfo,
783
834
  beginAbsolutePageIndex: totalPageInfo.numberOfPagesPerItems.slice(0, pageInfo.beginSpineItemIndex).reduce((acc, numberOfPagesForItem) => acc + numberOfPagesForItem, pageInfo.beginPageIndexInSpineItem ?? 0),
784
835
  endAbsolutePageIndex: totalPageInfo.numberOfPagesPerItems.slice(0, pageInfo.endSpineItemIndex).reduce((acc, numberOfPagesForItem) => acc + numberOfPagesForItem, pageInfo.endPageIndexInSpineItem ?? 0)
785
836
  })),
786
- operators.shareReplay(1),
787
- operators.takeUntil(reader.$.destroy$)
837
+ rxjs.tap((value) => {
838
+ currentValue.next(value);
839
+ }),
840
+ rxjs.shareReplay(1)
788
841
  );
842
+ return { paginationInfo$, getPaginationInfo: () => currentValue.value };
843
+ };
844
+ const NAMESPACE$5 = `paginationEnhancer`;
845
+ Report.namespace(NAMESPACE$5);
846
+ const paginationEnhancer = (next) => (options) => {
847
+ const reader = next(options);
848
+ const { paginationInfo$, getPaginationInfo } = trackPaginationInfo(reader);
849
+ paginationInfo$.pipe(rxjs.takeUntil(reader.$.destroy$)).subscribe();
789
850
  return {
790
851
  ...reader,
791
852
  pagination: {
792
853
  ...reader.pagination,
854
+ getPaginationInfo,
793
855
  paginationInfo$
794
856
  }
795
857
  };
796
858
  };
797
- const buildChapterInfoFromSpineItem = (manifest, item) => {
798
- var _a;
799
- const { href } = item;
800
- return getChapterInfo(href, ((_a = manifest.nav) == null ? void 0 : _a.toc) ?? [], manifest);
801
- };
802
- const getChapterInfo = (href, tocItem, manifest) => {
803
- const spineItemIndex = manifest.spineItems.findIndex((item) => item.href === href);
804
- return tocItem.reduce((acc, tocItem2) => {
805
- const indexOfHash = tocItem2.href.indexOf(`#`);
806
- const tocItemPathWithoutAnchor = indexOfHash > 0 ? tocItem2.href.substr(0, indexOfHash) : tocItem2.href;
807
- const tocItemHrefWithoutFilename = tocItemPathWithoutAnchor.substring(0, tocItemPathWithoutAnchor.lastIndexOf("/"));
808
- const hrefWithoutFilename = href.substring(0, href.lastIndexOf("/"));
809
- const hrefIsChapterHref = href.endsWith(tocItemPathWithoutAnchor);
810
- const hrefIsWithinChapter = hrefWithoutFilename !== "" && hrefWithoutFilename.endsWith(tocItemHrefWithoutFilename);
811
- const isPossibleTocItemCandidate = hrefIsChapterHref || hrefIsWithinChapter;
812
- if (isPossibleTocItemCandidate) {
813
- const spineItemIndexOfPossibleCandidate = manifest.spineItems.findIndex((item) => item.href === tocItem2.href);
814
- const spineItemIsBeforeThisTocItem = spineItemIndex < spineItemIndexOfPossibleCandidate;
815
- if (spineItemIsBeforeThisTocItem)
816
- return acc;
817
- const info = {
818
- title: tocItem2.title,
819
- path: tocItem2.path
820
- };
821
- const subInfo = getChapterInfo(href, tocItem2.contents, manifest);
822
- if (subInfo) {
823
- return {
824
- ...info,
825
- subChapter: subInfo
826
- };
827
- }
828
- return info;
829
- }
830
- return acc;
831
- }, void 0);
832
- };
833
859
  const defaultThemes = [
834
860
  {
835
861
  name: `bright`,
@@ -4314,10 +4340,10 @@
4314
4340
  const safePosition = getSafePosition(position, spineItem);
4315
4341
  const offset = context.isRTL() ? itemWidth - safePosition.x - context.getPageSize().width : safePosition.x;
4316
4342
  if (spineItem.isUsingVerticalWriting()) {
4317
- const numberOfPages = getNumberOfPages(itemHeight, pageHeight);
4343
+ const numberOfPages = calculateNumberOfPagesForItem(itemHeight, pageHeight);
4318
4344
  return getPageFromOffset(position.y, pageHeight, numberOfPages);
4319
4345
  } else {
4320
- const numberOfPages = getNumberOfPages(itemWidth, pageWidth);
4346
+ const numberOfPages = calculateNumberOfPagesForItem(itemWidth, pageWidth);
4321
4347
  const pageIndex = getPageFromOffset(offset, pageWidth, numberOfPages);
4322
4348
  return pageIndex;
4323
4349
  }
@@ -4438,11 +4464,11 @@
4438
4464
  const getNavigationForLastPage = (spineItem) => {
4439
4465
  if (spineItem.isUsingVerticalWriting()) {
4440
4466
  const pageHeight = context.getPageSize().height;
4441
- const numberOfPages = getNumberOfPages(spineItem.getElementDimensions().height, pageHeight);
4467
+ const numberOfPages = calculateNumberOfPagesForItem(spineItem.getElementDimensions().height, pageHeight);
4442
4468
  return getNavigationForPage(numberOfPages - 1, spineItem);
4443
4469
  } else {
4444
4470
  const pageWidth = context.getPageSize().width;
4445
- const numberOfPages = getNumberOfPages(spineItem.getElementDimensions().width, pageWidth);
4471
+ const numberOfPages = calculateNumberOfPagesForItem(spineItem.getElementDimensions().width, pageWidth);
4446
4472
  return getNavigationForPage(numberOfPages - 1, spineItem);
4447
4473
  }
4448
4474
  };