@prose-reader/core 1.14.0 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/context.d.ts +1 -1
- package/dist/createReaderWithEnhancer.d.ts +5467 -4
- package/dist/enhancers/accessibility.d.ts +5464 -1
- package/dist/enhancers/chrome.d.ts +5464 -1
- package/dist/enhancers/fonts.d.ts +5464 -1
- package/dist/enhancers/hotkeys.d.ts +5464 -1
- package/dist/enhancers/layoutEnhancer/layoutEnhancer.d.ts +5464 -1
- package/dist/enhancers/links.d.ts +5465 -2
- package/dist/enhancers/loadingEnhancer.d.ts +5465 -1
- package/dist/enhancers/media.d.ts +5464 -1
- package/dist/enhancers/navigation.d.ts +5464 -1
- package/dist/enhancers/pagination.d.ts +5464 -2
- package/dist/enhancers/progression.d.ts +5464 -2
- package/dist/enhancers/resources/index.d.ts +5464 -1
- package/dist/enhancers/theme.d.ts +5464 -1
- package/dist/enhancers/types/enhancer.d.ts +5464 -1
- package/dist/enhancers/utils.d.ts +5464 -1
- package/dist/enhancers/webkit.d.ts +5464 -1
- package/dist/enhancers/zoom/index.d.ts +5464 -2
- package/dist/prose.js +361 -54
- package/dist/prose.js.map +1 -1
- package/dist/prose.umd.cjs +361 -54
- package/dist/prose.umd.cjs.map +1 -1
- package/dist/reader.d.ts +5474 -4
- package/dist/types/index.d.ts +0 -1
- package/package.json +5 -10
- package/dist/types/Reader.d.ts +0 -68
package/dist/prose.js
CHANGED
|
@@ -2125,7 +2125,15 @@ const fontsEnhancer = (next) => (options) => {
|
|
|
2125
2125
|
});
|
|
2126
2126
|
const reader = next(options);
|
|
2127
2127
|
const getStyle = () => `
|
|
2128
|
-
${
|
|
2128
|
+
${/*
|
|
2129
|
+
Ideally, we would like to use !important but it could break publisher specific
|
|
2130
|
+
cases.
|
|
2131
|
+
Also right now we do not apply it to * since it would also break publisher
|
|
2132
|
+
more specific scaling down the tree.
|
|
2133
|
+
|
|
2134
|
+
body *:not([class^="mjx-"]) {
|
|
2135
|
+
*/
|
|
2136
|
+
``}
|
|
2129
2137
|
body {
|
|
2130
2138
|
${settingsSubject$.value.fontScale !== 1 ? `font-size: ${settingsSubject$.value.fontScale}em !important;` : ``}
|
|
2131
2139
|
${settingsSubject$.value.lineHeight !== `publisher` ? `line-height: ${settingsSubject$.value.lineHeight} !important;` : ``}
|
|
@@ -2167,6 +2175,9 @@ const fontsEnhancer = (next) => (options) => {
|
|
|
2167
2175
|
);
|
|
2168
2176
|
return {
|
|
2169
2177
|
...reader,
|
|
2178
|
+
/**
|
|
2179
|
+
* Absorb current enhancer settings and passthrough the rest to reader
|
|
2180
|
+
*/
|
|
2170
2181
|
setSettings: (settings) => {
|
|
2171
2182
|
const {
|
|
2172
2183
|
fontJustification: fontJustification2 = settingsSubject$.value.fontJustification,
|
|
@@ -2180,6 +2191,9 @@ const fontsEnhancer = (next) => (options) => {
|
|
|
2180
2191
|
}
|
|
2181
2192
|
reader.setSettings(passthroughSettings);
|
|
2182
2193
|
},
|
|
2194
|
+
/**
|
|
2195
|
+
* Combine reader settings with enhancer settings
|
|
2196
|
+
*/
|
|
2183
2197
|
settings$
|
|
2184
2198
|
};
|
|
2185
2199
|
};
|
|
@@ -2447,6 +2461,7 @@ const time = (name, targetDuration = 0) => {
|
|
|
2447
2461
|
};
|
|
2448
2462
|
};
|
|
2449
2463
|
const createReport = (namespace) => ({
|
|
2464
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2450
2465
|
log: (...data) => {
|
|
2451
2466
|
if (window.__PROSE_READER_DEBUG) {
|
|
2452
2467
|
if (namespace)
|
|
@@ -2455,6 +2470,7 @@ const createReport = (namespace) => ({
|
|
|
2455
2470
|
console.log(wrap(ROOT_NAMESPACE), ...data);
|
|
2456
2471
|
}
|
|
2457
2472
|
},
|
|
2473
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2458
2474
|
warn: (...data) => {
|
|
2459
2475
|
if (window.__PROSE_READER_DEBUG) {
|
|
2460
2476
|
if (namespace)
|
|
@@ -2463,9 +2479,22 @@ const createReport = (namespace) => ({
|
|
|
2463
2479
|
console.warn(wrap(ROOT_NAMESPACE), ...data);
|
|
2464
2480
|
}
|
|
2465
2481
|
},
|
|
2482
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2466
2483
|
error: (...data) => {
|
|
2467
2484
|
console.error(...data);
|
|
2468
2485
|
},
|
|
2486
|
+
// time: (label?: string | undefined) => {
|
|
2487
|
+
// if (window.__PROSE_READER_DEBUG) {
|
|
2488
|
+
// // eslint-disable-next-line no-console
|
|
2489
|
+
// console.time(`[prose-reader] [metric] ${label}`);
|
|
2490
|
+
// }
|
|
2491
|
+
// },
|
|
2492
|
+
// timeEnd: (label?: string | undefined) => {
|
|
2493
|
+
// if (window.__PROSE_READER_DEBUG) {
|
|
2494
|
+
// // eslint-disable-next-line no-console
|
|
2495
|
+
// console.timeEnd(`[prose-reader] [metric] ${label}`);
|
|
2496
|
+
// }
|
|
2497
|
+
// },
|
|
2469
2498
|
time,
|
|
2470
2499
|
logMetric: (performanceEntry, targetDuration = 0) => {
|
|
2471
2500
|
if (window.__PROSE_READER_DEBUG) {
|
|
@@ -2479,6 +2508,7 @@ const createReport = (namespace) => ({
|
|
|
2479
2508
|
}
|
|
2480
2509
|
}
|
|
2481
2510
|
},
|
|
2511
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2482
2512
|
measurePerformance: (name, targetDuration = 10, functionToMeasure, { disable } = {}) => {
|
|
2483
2513
|
if (disable || !window.__PROSE_READER_DEBUG)
|
|
2484
2514
|
return functionToMeasure;
|
|
@@ -2673,15 +2703,37 @@ const paginationEnhancer = (next) => (options) => {
|
|
|
2673
2703
|
beginPageIndexInChapter: paginationInfo.beginPageIndex,
|
|
2674
2704
|
beginNumberOfPagesInChapter: paginationInfo.beginNumberOfPages,
|
|
2675
2705
|
beginChapterInfo: beginItem ? chaptersInfo[beginItem.item.id] : void 0,
|
|
2706
|
+
// chapterIndex: number;
|
|
2707
|
+
// pages: number;
|
|
2708
|
+
// pageIndexInBook: number;
|
|
2709
|
+
// pageIndexInChapter: number;
|
|
2710
|
+
// pagesOfChapter: number;
|
|
2711
|
+
// pagePercentageInChapter: number;
|
|
2712
|
+
// offsetPercentageInChapter: number;
|
|
2713
|
+
// domIndex: number;
|
|
2714
|
+
// charOffset: number;
|
|
2715
|
+
// serializeString?: string;
|
|
2676
2716
|
beginSpineItemIndex: paginationInfo.beginSpineItemIndex,
|
|
2717
|
+
// spineItemPath: beginItem?.item.path,
|
|
2718
|
+
// spineItemId: beginItem?.item.id,
|
|
2677
2719
|
beginCfi: paginationInfo.beginCfi,
|
|
2678
2720
|
beginSpineItemReadingDirection: beginItem == null ? void 0 : beginItem.getReadingDirection(),
|
|
2679
2721
|
endChapterInfo: endItem ? chaptersInfo[endItem.item.id] : void 0,
|
|
2680
2722
|
endPageIndexInChapter: paginationInfo.endPageIndex,
|
|
2681
2723
|
endNumberOfPagesInChapter: paginationInfo.endNumberOfPages,
|
|
2682
2724
|
endSpineItemIndex: paginationInfo.endSpineItemIndex,
|
|
2725
|
+
// spineItemPath: endItem?.item.path,
|
|
2726
|
+
// spineItemId: endItem?.item.id,
|
|
2683
2727
|
endSpineItemReadingDirection: endItem == null ? void 0 : endItem.getReadingDirection(),
|
|
2684
2728
|
endCfi: paginationInfo.endCfi,
|
|
2729
|
+
// end: ReadingLocation;
|
|
2730
|
+
// spineItemReadingDirection: focusedSpineItem?.getReadingDirection(),
|
|
2731
|
+
/**
|
|
2732
|
+
* This percentage is based of the weight (kb) of every items and the number of pages.
|
|
2733
|
+
* It is not accurate but gives a general good idea of the overall progress.
|
|
2734
|
+
* It is recommended to use this progress only for reflow books. For pre-paginated books
|
|
2735
|
+
* the number of pages and current index can be used instead since 1 page = 1 chapter.
|
|
2736
|
+
*/
|
|
2685
2737
|
percentageEstimateOfBook: endItem ? reader.progression.getPercentageEstimate(
|
|
2686
2738
|
context,
|
|
2687
2739
|
paginationInfo.endSpineItemIndex ?? 0,
|
|
@@ -2691,6 +2743,11 @@ const paginationEnhancer = (next) => (options) => {
|
|
|
2691
2743
|
endItem
|
|
2692
2744
|
) : 0,
|
|
2693
2745
|
isUsingSpread: context.shouldDisplaySpread()
|
|
2746
|
+
// chaptersOfBook: number;
|
|
2747
|
+
// chapter: string;
|
|
2748
|
+
// hasNextChapter: (reader.spine.spineItemIndex || 0) < (manifest.readingOrder.length - 1),
|
|
2749
|
+
// hasPreviousChapter: (reader.spine.spineItemIndex || 0) < (manifest.readingOrder.length - 1),
|
|
2750
|
+
// numberOfSpineItems: context.getManifest()?.readingOrder.length,
|
|
2694
2751
|
};
|
|
2695
2752
|
};
|
|
2696
2753
|
const getSpineItemNumberOfPages = (spineItem) => {
|
|
@@ -2730,6 +2787,9 @@ const paginationEnhancer = (next) => (options) => {
|
|
|
2730
2787
|
const numberOfPagesPerItems = getNumberOfPagesPerItems();
|
|
2731
2788
|
return {
|
|
2732
2789
|
numberOfPagesPerItems,
|
|
2790
|
+
/**
|
|
2791
|
+
* This may be not accurate for reflowable due to dynamic load / unload.
|
|
2792
|
+
*/
|
|
2733
2793
|
numberOfTotalPages: numberOfPagesPerItems.reduce((acc, numberOfPagesForItem) => acc + numberOfPagesForItem, 0)
|
|
2734
2794
|
};
|
|
2735
2795
|
}),
|
|
@@ -2760,28 +2820,34 @@ const paginationEnhancer = (next) => (options) => {
|
|
|
2760
2820
|
const buildChapterInfoFromSpineItem = (manifest, item) => {
|
|
2761
2821
|
var _a;
|
|
2762
2822
|
const { href } = item;
|
|
2763
|
-
return getChapterInfo(href, ((_a = manifest.nav) == null ? void 0 : _a.toc) ?? []);
|
|
2823
|
+
return getChapterInfo(href, ((_a = manifest.nav) == null ? void 0 : _a.toc) ?? [], manifest);
|
|
2764
2824
|
};
|
|
2765
|
-
const getChapterInfo = (href,
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
const
|
|
2825
|
+
const getChapterInfo = (href, tocItem, manifest) => {
|
|
2826
|
+
const spineItemIndex = manifest.spineItems.findIndex((item) => item.href === href);
|
|
2827
|
+
return tocItem.reduce((acc, tocItem2) => {
|
|
2828
|
+
const indexOfHash = tocItem2.href.indexOf(`#`);
|
|
2829
|
+
const tocItemPathWithoutAnchor = indexOfHash > 0 ? tocItem2.href.substr(0, indexOfHash) : tocItem2.href;
|
|
2769
2830
|
const tocItemHrefWithoutFilename = tocItemPathWithoutAnchor.substring(0, tocItemPathWithoutAnchor.lastIndexOf("/"));
|
|
2770
2831
|
const hrefWithoutFilename = href.substring(0, href.lastIndexOf("/"));
|
|
2771
2832
|
const hrefIsChapterHref = href.endsWith(tocItemPathWithoutAnchor);
|
|
2772
2833
|
const hrefIsWithinChapter = hrefWithoutFilename !== "" && hrefWithoutFilename.endsWith(tocItemHrefWithoutFilename);
|
|
2773
|
-
|
|
2834
|
+
const isPossibleTocItemCandidate = hrefIsChapterHref || hrefIsWithinChapter;
|
|
2835
|
+
if (isPossibleTocItemCandidate) {
|
|
2836
|
+
const spineItemIndexOfPossibleCandidate = manifest.spineItems.findIndex((item) => item.href === tocItem2.href);
|
|
2837
|
+
const spineItemIsBeforeThisTocItem = spineItemIndex < spineItemIndexOfPossibleCandidate;
|
|
2838
|
+
if (spineItemIsBeforeThisTocItem)
|
|
2839
|
+
return acc;
|
|
2774
2840
|
return {
|
|
2775
|
-
title:
|
|
2776
|
-
path:
|
|
2841
|
+
title: tocItem2.title,
|
|
2842
|
+
path: tocItem2.path
|
|
2777
2843
|
};
|
|
2778
2844
|
}
|
|
2779
|
-
const subInfo = getChapterInfo(href,
|
|
2845
|
+
const subInfo = getChapterInfo(href, tocItem2.contents, manifest);
|
|
2780
2846
|
if (subInfo) {
|
|
2781
2847
|
return {
|
|
2782
2848
|
subChapter: subInfo,
|
|
2783
|
-
title:
|
|
2784
|
-
path:
|
|
2849
|
+
title: tocItem2.title,
|
|
2850
|
+
path: tocItem2.path
|
|
2785
2851
|
};
|
|
2786
2852
|
}
|
|
2787
2853
|
return acc;
|
|
@@ -2814,7 +2880,11 @@ const themeEnhancer = (next) => (options) => {
|
|
|
2814
2880
|
}
|
|
2815
2881
|
${(foundTheme == null ? void 0 : foundTheme.foregroundColor) ? `
|
|
2816
2882
|
body * {
|
|
2817
|
-
${
|
|
2883
|
+
${/*
|
|
2884
|
+
Ideally, we would like to use !important but it could break publisher specific
|
|
2885
|
+
cases
|
|
2886
|
+
*/
|
|
2887
|
+
``}
|
|
2818
2888
|
color: ${foundTheme.foregroundColor};
|
|
2819
2889
|
}
|
|
2820
2890
|
` : ``}
|
|
@@ -3412,6 +3482,8 @@ const createLoader = ({
|
|
|
3412
3482
|
take(1)
|
|
3413
3483
|
);
|
|
3414
3484
|
const unload$ = unloadSubject$.asObservable().pipe(
|
|
3485
|
+
// @todo remove iframe when viewport is free
|
|
3486
|
+
// @todo use takeUntil(load$) when it's the case to cancel
|
|
3415
3487
|
withLatestFrom(frameElementSubject$),
|
|
3416
3488
|
filter(([_, frame]) => !!frame),
|
|
3417
3489
|
map(([, frame]) => {
|
|
@@ -3432,13 +3504,16 @@ const createLoader = ({
|
|
|
3432
3504
|
const load$ = loadSubject$.asObservable().pipe(
|
|
3433
3505
|
withLatestFrom(isLoadedSubject$),
|
|
3434
3506
|
filter(([_, isLoaded]) => !isLoaded),
|
|
3507
|
+
// let's ignore later load as long as the first one still runs
|
|
3435
3508
|
exhaustMap(() => {
|
|
3436
3509
|
return createFrame$().pipe(
|
|
3437
3510
|
mergeMap((frame) => waitForViewportFree$.pipe(map(() => frame))),
|
|
3438
3511
|
mergeMap((frame) => {
|
|
3439
3512
|
parent.appendChild(frame);
|
|
3440
3513
|
frameElementSubject$.next(frame);
|
|
3441
|
-
if (!fetchResource && item.href.startsWith(window.location.origin) &&
|
|
3514
|
+
if (!fetchResource && item.href.startsWith(window.location.origin) && // we have an encoding and it's a valid html
|
|
3515
|
+
(item.mediaType && [`application/xhtml+xml`, `application/xml`, `text/html`, `text/xml`].includes(item.mediaType) || // no encoding ? then try to detect html
|
|
3516
|
+
!item.mediaType && ITEM_EXTENSION_VALID_FOR_FRAME_SRC.some((extension) => item.href.endsWith(extension)))) {
|
|
3442
3517
|
frame == null ? void 0 : frame.setAttribute(`src`, item.href);
|
|
3443
3518
|
return of(frame);
|
|
3444
3519
|
} else {
|
|
@@ -3494,6 +3569,7 @@ const createLoader = ({
|
|
|
3494
3569
|
})
|
|
3495
3570
|
);
|
|
3496
3571
|
}),
|
|
3572
|
+
// we stop loading as soon as unload is requested
|
|
3497
3573
|
takeUntil(unloadSubject$)
|
|
3498
3574
|
);
|
|
3499
3575
|
}),
|
|
@@ -3620,6 +3696,12 @@ const createFrameItem = ({
|
|
|
3620
3696
|
getHtmlFromResource,
|
|
3621
3697
|
load,
|
|
3622
3698
|
unload,
|
|
3699
|
+
/**
|
|
3700
|
+
* Upward layout is used when the parent wants to manipulate the iframe without triggering
|
|
3701
|
+
* `layout` event. This is a particular case needed for iframe because the parent can layout following
|
|
3702
|
+
* an iframe `layout` event. Because the parent `layout` may change some of iframe properties we do not
|
|
3703
|
+
* want the iframe to trigger a new `layout` even and have infinite loop.
|
|
3704
|
+
*/
|
|
3623
3705
|
staticLayout: (size) => {
|
|
3624
3706
|
const frame = frameElement$.getValue();
|
|
3625
3707
|
if (frame) {
|
|
@@ -3630,6 +3712,8 @@ const createFrameItem = ({
|
|
|
3630
3712
|
}
|
|
3631
3713
|
}
|
|
3632
3714
|
},
|
|
3715
|
+
// @todo block access, only public API to manipulate / get information (in order to memo / optimize)
|
|
3716
|
+
// manipulate() with cb and return boolean whether re-layout or not
|
|
3633
3717
|
getManipulableFrame,
|
|
3634
3718
|
getReadingDirection: () => {
|
|
3635
3719
|
var _a;
|
|
@@ -3651,6 +3735,10 @@ const createFrameItem = ({
|
|
|
3651
3735
|
loaded$,
|
|
3652
3736
|
ready$,
|
|
3653
3737
|
isReady$: isReadySubject$.asObservable(),
|
|
3738
|
+
/**
|
|
3739
|
+
* This is used as upstream layout change. This event is being listened to by upper app
|
|
3740
|
+
* in order to layout again and adjust every element based on the new content.
|
|
3741
|
+
*/
|
|
3654
3742
|
contentLayoutChange$
|
|
3655
3743
|
}
|
|
3656
3744
|
};
|
|
@@ -3929,6 +4017,8 @@ const createCommonSpineItem = ({
|
|
|
3929
4017
|
const rect = containerElement.getBoundingClientRect();
|
|
3930
4018
|
const normalizedValues = {
|
|
3931
4019
|
...rect,
|
|
4020
|
+
// we want to round to first decimal because it's possible to have half pixel
|
|
4021
|
+
// however browser engine can also gives back x.yyyy based on their precision
|
|
3932
4022
|
width: Math.round(rect.width * 10) / 10,
|
|
3933
4023
|
height: Math.round(rect.height * 10) / 10
|
|
3934
4024
|
};
|
|
@@ -4008,6 +4098,8 @@ const createCommonSpineItem = ({
|
|
|
4008
4098
|
return {
|
|
4009
4099
|
columnHeight,
|
|
4010
4100
|
columnWidth,
|
|
4101
|
+
// horizontalMargin,
|
|
4102
|
+
// verticalMargin,
|
|
4011
4103
|
width
|
|
4012
4104
|
};
|
|
4013
4105
|
};
|
|
@@ -4325,22 +4417,37 @@ const buildDocumentStyle = ({
|
|
|
4325
4417
|
justify-content: ${spreadPosition === `left` ? `flex-end` : spreadPosition === `right` ? `flex-start` : `center`};
|
|
4326
4418
|
` : ``}
|
|
4327
4419
|
}
|
|
4328
|
-
${
|
|
4420
|
+
${/*
|
|
4421
|
+
might be html * but it does mess up things like figure if so.
|
|
4422
|
+
check accessible_epub_3
|
|
4423
|
+
*/
|
|
4424
|
+
``}
|
|
4329
4425
|
html, body {
|
|
4330
4426
|
height: 100%;
|
|
4331
4427
|
width: 100%;
|
|
4332
4428
|
}
|
|
4333
|
-
${
|
|
4429
|
+
${/*
|
|
4430
|
+
This one is important for preventing 100% img to resize above
|
|
4431
|
+
current width. Especially needed for cbz conversion
|
|
4432
|
+
*/
|
|
4433
|
+
``}
|
|
4334
4434
|
html, body {
|
|
4335
4435
|
-max-width: ${columnWidth}px !important;
|
|
4336
4436
|
}
|
|
4337
|
-
${
|
|
4437
|
+
${/*
|
|
4438
|
+
* @see https://hammerjs.github.io/touch-action/
|
|
4439
|
+
* It needs to be disabled when using free scroll
|
|
4440
|
+
*/
|
|
4441
|
+
``}
|
|
4338
4442
|
html, body {
|
|
4339
4443
|
${enableTouch ? `
|
|
4340
4444
|
touch-action: none
|
|
4341
4445
|
` : ``}
|
|
4342
4446
|
}
|
|
4343
|
-
${
|
|
4447
|
+
${/*
|
|
4448
|
+
prevent drag of image instead of touch on firefox
|
|
4449
|
+
*/
|
|
4450
|
+
``}
|
|
4344
4451
|
img {
|
|
4345
4452
|
user-select: none;
|
|
4346
4453
|
-webkit-user-drag: none;
|
|
@@ -4348,9 +4455,18 @@ const buildDocumentStyle = ({
|
|
|
4348
4455
|
-moz-user-drag: none;
|
|
4349
4456
|
-o-user-drag: none;
|
|
4350
4457
|
user-drag: none;
|
|
4351
|
-
${
|
|
4458
|
+
${/*
|
|
4459
|
+
prevent weird overflow or margin. Try `block` if `flex` has weird behavior
|
|
4460
|
+
*/
|
|
4461
|
+
``}
|
|
4352
4462
|
display: flex;
|
|
4353
|
-
${
|
|
4463
|
+
${/*
|
|
4464
|
+
If the document does not have viewport, we cannot scale anything inside.
|
|
4465
|
+
This should never happens with a valid epub document however it will happens if
|
|
4466
|
+
we load .jpg, .png, etc directly in the iframe. This is expected, in this case we force
|
|
4467
|
+
the inner content to display correctly.
|
|
4468
|
+
*/
|
|
4469
|
+
``}
|
|
4354
4470
|
${!viewportDimensions ? `
|
|
4355
4471
|
-width: 100%;
|
|
4356
4472
|
max-width: 100%;
|
|
@@ -4481,7 +4597,10 @@ const buildStyleForViewportFrame = () => {
|
|
|
4481
4597
|
height: 100%;
|
|
4482
4598
|
margin: 0;
|
|
4483
4599
|
}
|
|
4484
|
-
${
|
|
4600
|
+
${/*
|
|
4601
|
+
* @see https://hammerjs.github.io/touch-action/
|
|
4602
|
+
*/
|
|
4603
|
+
``}
|
|
4485
4604
|
html, body {
|
|
4486
4605
|
touch-action: none;
|
|
4487
4606
|
}
|
|
@@ -4489,7 +4608,10 @@ const buildStyleForViewportFrame = () => {
|
|
|
4489
4608
|
};
|
|
4490
4609
|
const buildStyleForReflowableImageOnly = ({ isScrollable, enableTouch }) => {
|
|
4491
4610
|
return `
|
|
4492
|
-
${
|
|
4611
|
+
${/*
|
|
4612
|
+
* @see https://hammerjs.github.io/touch-action/
|
|
4613
|
+
*/
|
|
4614
|
+
``}
|
|
4493
4615
|
html, body {
|
|
4494
4616
|
width: 100%;
|
|
4495
4617
|
margin: 0;
|
|
@@ -4504,9 +4626,14 @@ const buildStyleForReflowableImageOnly = ({ isScrollable, enableTouch }) => {
|
|
|
4504
4626
|
margin: 0;
|
|
4505
4627
|
padding: 0;
|
|
4506
4628
|
box-sizing: border-box;
|
|
4507
|
-
${
|
|
4629
|
+
${// we make sure img spread on entire screen
|
|
4630
|
+
``}
|
|
4508
4631
|
width: 100%;
|
|
4509
|
-
${
|
|
4632
|
+
${/**
|
|
4633
|
+
* line break issue
|
|
4634
|
+
* @see https://stackoverflow.com/questions/37869020/image-not-taking-up-the-full-height-of-container
|
|
4635
|
+
*/
|
|
4636
|
+
``}
|
|
4510
4637
|
display: block;
|
|
4511
4638
|
}
|
|
4512
4639
|
` : ``}
|
|
@@ -4521,13 +4648,28 @@ const buildStyleWithMultiColumn = ({
|
|
|
4521
4648
|
parsererror {
|
|
4522
4649
|
display: none !important;
|
|
4523
4650
|
}
|
|
4524
|
-
${
|
|
4651
|
+
${/*
|
|
4652
|
+
might be html * but it does mess up things like figure if so.
|
|
4653
|
+
check accessible_epub_3
|
|
4654
|
+
*/
|
|
4655
|
+
``}
|
|
4525
4656
|
html, body {
|
|
4526
4657
|
margin: 0;
|
|
4527
4658
|
padding: 0 !important;
|
|
4528
4659
|
-max-width: ${columnWidth}px !important;
|
|
4529
4660
|
}
|
|
4530
|
-
${
|
|
4661
|
+
${/*
|
|
4662
|
+
body {
|
|
4663
|
+
height: ${columnHeight}px !important;
|
|
4664
|
+
width: ${columnWidth}px !important;
|
|
4665
|
+
-margin-left: ${horizontalMargin}px !important;
|
|
4666
|
+
-margin-right: ${horizontalMargin}px !important;
|
|
4667
|
+
-margin: ${verticalMargin}px ${horizontalMargin}px !important;
|
|
4668
|
+
-padding-top: ${horizontalMargin}px !important;
|
|
4669
|
+
-padding-bottom: ${horizontalMargin}px !important;
|
|
4670
|
+
}
|
|
4671
|
+
*/
|
|
4672
|
+
``}
|
|
4531
4673
|
body {
|
|
4532
4674
|
padding: 0 !important;
|
|
4533
4675
|
width: ${width}px !important;
|
|
@@ -4543,18 +4685,33 @@ const buildStyleWithMultiColumn = ({
|
|
|
4543
4685
|
margin: 0;
|
|
4544
4686
|
}
|
|
4545
4687
|
body:focus-visible {
|
|
4546
|
-
${
|
|
4688
|
+
${/*
|
|
4689
|
+
we make sure that there are no outline when we focus something inside the iframe
|
|
4690
|
+
*/
|
|
4691
|
+
``}
|
|
4547
4692
|
outline: none;
|
|
4548
4693
|
}
|
|
4549
|
-
${
|
|
4694
|
+
${/*
|
|
4695
|
+
* @see https://hammerjs.github.io/touch-action/
|
|
4696
|
+
*/
|
|
4697
|
+
``}
|
|
4550
4698
|
html, body {
|
|
4551
4699
|
touch-action: none;
|
|
4552
4700
|
}
|
|
4553
|
-
${
|
|
4701
|
+
${/*
|
|
4702
|
+
this messes up hard, be careful with this
|
|
4703
|
+
*/
|
|
4704
|
+
``}
|
|
4554
4705
|
* {
|
|
4555
4706
|
-max-width: ${columnWidth}px !important;
|
|
4556
4707
|
}
|
|
4557
|
-
${
|
|
4708
|
+
${/*
|
|
4709
|
+
this is necessary to have a proper calculation when determining size
|
|
4710
|
+
of iframe content. If an img is using something like width:100% it would expand to
|
|
4711
|
+
the size of the original image and potentially gives back a wrong size (much larger)
|
|
4712
|
+
@see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Columns/Handling_Overflow_in_Multicol
|
|
4713
|
+
*/
|
|
4714
|
+
``}
|
|
4558
4715
|
img, video, audio, object, svg {
|
|
4559
4716
|
max-width: 100%;
|
|
4560
4717
|
max-width: ${columnWidth}px !important;
|
|
@@ -4573,7 +4730,17 @@ const buildStyleWithMultiColumn = ({
|
|
|
4573
4730
|
box-sizing: border-box;
|
|
4574
4731
|
d-max-width: ${columnWidth}px !important;
|
|
4575
4732
|
}
|
|
4576
|
-
${
|
|
4733
|
+
${/*
|
|
4734
|
+
img, video, audio, object, svg {
|
|
4735
|
+
max-height: ${columnHeight}px !important;
|
|
4736
|
+
box-sizing: border-box;
|
|
4737
|
+
object-fit: contain;
|
|
4738
|
+
-webkit-column-break-inside: avoid;
|
|
4739
|
+
page-break-inside: avoid;
|
|
4740
|
+
break-inside: avoid;
|
|
4741
|
+
}
|
|
4742
|
+
*/
|
|
4743
|
+
``}
|
|
4577
4744
|
table {
|
|
4578
4745
|
max-width: ${columnWidth}px !important;
|
|
4579
4746
|
table-layout: fixed;
|
|
@@ -4770,7 +4937,11 @@ class CFI {
|
|
|
4770
4937
|
this.isRange = false;
|
|
4771
4938
|
this.opts = Object.assign(
|
|
4772
4939
|
{
|
|
4940
|
+
// If CFI is a Simple Range, pretend it isn't
|
|
4941
|
+
// by parsing only the start of the range
|
|
4773
4942
|
flattenRange: false,
|
|
4943
|
+
// Strip temporal, spatial, offset and textLocationAssertion
|
|
4944
|
+
// from places where they don't make sense
|
|
4774
4945
|
stricter: true
|
|
4775
4946
|
},
|
|
4776
4947
|
opts || {}
|
|
@@ -4890,6 +5061,7 @@ class CFI {
|
|
|
4890
5061
|
return cfi.get();
|
|
4891
5062
|
}
|
|
4892
5063
|
}
|
|
5064
|
+
// Takes two CFI paths and compares them
|
|
4893
5065
|
static comparePath(a, b) {
|
|
4894
5066
|
const max = Math.max(a.length, b.length);
|
|
4895
5067
|
let i, cA, cB, diff;
|
|
@@ -4906,11 +5078,13 @@ class CFI {
|
|
|
4906
5078
|
}
|
|
4907
5079
|
return 0;
|
|
4908
5080
|
}
|
|
5081
|
+
// Sort an array of CFI objects
|
|
4909
5082
|
static sort(a) {
|
|
4910
5083
|
a.sort((a2, b) => {
|
|
4911
5084
|
return this.compare(a2, b);
|
|
4912
5085
|
});
|
|
4913
5086
|
}
|
|
5087
|
+
// Takes two CFI objects and compares them.
|
|
4914
5088
|
static compare(a, b) {
|
|
4915
5089
|
let oA = a.get();
|
|
4916
5090
|
let oB = b.get();
|
|
@@ -4930,6 +5104,7 @@ class CFI {
|
|
|
4930
5104
|
return this.comparePath(oA, oB);
|
|
4931
5105
|
}
|
|
4932
5106
|
}
|
|
5107
|
+
// Takes two parsed path parts (assuming path is split on '!') and compares them.
|
|
4933
5108
|
static compareParts(a, b) {
|
|
4934
5109
|
const max = Math.max(a.length, b.length);
|
|
4935
5110
|
let i, cA, cB, diff;
|
|
@@ -4971,6 +5146,7 @@ class CFI {
|
|
|
4971
5146
|
return str;
|
|
4972
5147
|
}
|
|
4973
5148
|
}
|
|
5149
|
+
// decode HTML/XML entities and compute length
|
|
4974
5150
|
trueLength(dom, str) {
|
|
4975
5151
|
return this.decodeEntities(dom, str).length;
|
|
4976
5152
|
}
|
|
@@ -5236,6 +5412,9 @@ class CFI {
|
|
|
5236
5412
|
throw new Error(`Missing child node index in CFI`);
|
|
5237
5413
|
return { parsed: o, offset: i, newDoc: state === `!` };
|
|
5238
5414
|
}
|
|
5415
|
+
// The CFI counts child nodes differently from the DOM
|
|
5416
|
+
// Retrieve the child of parentNode at the specified index
|
|
5417
|
+
// according to the CFI standard way of counting
|
|
5239
5418
|
getChildNodeByCFIIndex(dom, parentNode, index, offset) {
|
|
5240
5419
|
const children = parentNode.childNodes;
|
|
5241
5420
|
if (!children.length)
|
|
@@ -5314,6 +5493,7 @@ class CFI {
|
|
|
5314
5493
|
}
|
|
5315
5494
|
return false;
|
|
5316
5495
|
}
|
|
5496
|
+
// Use a Text Location Assertion to correct and offset
|
|
5317
5497
|
correctOffset(dom, node, offset, assertion) {
|
|
5318
5498
|
let curNode = node;
|
|
5319
5499
|
let matchStr;
|
|
@@ -5411,6 +5591,15 @@ class CFI {
|
|
|
5411
5591
|
}
|
|
5412
5592
|
return o;
|
|
5413
5593
|
}
|
|
5594
|
+
// Each part of a CFI (as separated by '!')
|
|
5595
|
+
// references a separate HTML/XHTML/XML document.
|
|
5596
|
+
// This function takes an index specifying the part
|
|
5597
|
+
// of the CFI and the appropriate Document or XMLDocument
|
|
5598
|
+
// that is referenced by the specified part of the CFI
|
|
5599
|
+
// and returns the URI for the document referenced by
|
|
5600
|
+
// the next part of the CFI
|
|
5601
|
+
// If the opt `ignoreIDs` is true then IDs
|
|
5602
|
+
// will not be used while resolving
|
|
5414
5603
|
resolveURI(index, dom, opts) {
|
|
5415
5604
|
opts = opts || {};
|
|
5416
5605
|
if (index < 0 || index > this.parts.length - 2) {
|
|
@@ -5422,7 +5611,8 @@ class CFI {
|
|
|
5422
5611
|
const o = this.resolveNode(index, subparts, dom, opts);
|
|
5423
5612
|
let node = o.node;
|
|
5424
5613
|
const tagName = node.tagName.toLowerCase();
|
|
5425
|
-
if (tagName === `itemref` &&
|
|
5614
|
+
if (tagName === `itemref` && // @ts-ignore
|
|
5615
|
+
node.parentNode.tagName.toLowerCase() === `spine`) {
|
|
5426
5616
|
const idref = node.getAttribute(`idref`);
|
|
5427
5617
|
if (!idref)
|
|
5428
5618
|
throw new Error(`Referenced node had not 'idref' attribute`);
|
|
@@ -5469,6 +5659,9 @@ class CFI {
|
|
|
5469
5659
|
delete o.offset;
|
|
5470
5660
|
return { ...lastPart, ...o };
|
|
5471
5661
|
}
|
|
5662
|
+
// Takes the Document or XMLDocument for the final
|
|
5663
|
+
// document referenced by the CFI
|
|
5664
|
+
// and returns the node and offset into that node
|
|
5472
5665
|
resolveLast(dom, opts) {
|
|
5473
5666
|
opts = Object.assign(
|
|
5474
5667
|
{
|
|
@@ -5726,7 +5919,22 @@ const createSpine = ({
|
|
|
5726
5919
|
spineItem: beginSpineItem,
|
|
5727
5920
|
spineItemIndex: beginItemIndex,
|
|
5728
5921
|
pageIndex: beginPageIndex,
|
|
5729
|
-
|
|
5922
|
+
/**
|
|
5923
|
+
* Because the start of a navigation may involve animations and interactions we don't resolve heavy CFI here.
|
|
5924
|
+
* We do want to have certain information correct in the pagination right after a navigation (same tick) but we just
|
|
5925
|
+
* defer heavy non vital stuff for later.
|
|
5926
|
+
* There are only 4 different cfi update at this stage:
|
|
5927
|
+
* - navigation comes from cfi, we simply affect the cfi to the pagination
|
|
5928
|
+
* - navigation comes from adjustment with controlled mode, we don't update the cfi, just pass the previous one
|
|
5929
|
+
* - navigation comes from adjustment with free mode, we will update with root cfi if needed because we could be on new page
|
|
5930
|
+
* - navigation is not from adjustment, this means we are on either new page or new reading item, we use light cfi with root (no dom lookup)
|
|
5931
|
+
*
|
|
5932
|
+
* The cfi is later adjusted with heavy dom lookup once the viewport is free.
|
|
5933
|
+
*/
|
|
5934
|
+
cfi: (lastExpectedNavigation == null ? void 0 : lastExpectedNavigation.type) === `navigate-from-cfi` && spineItemToFocus === beginSpineItem ? lastExpectedNavigation.data : data.triggeredBy === `adjust` && context.getSettings().computedPageTurnMode === `controlled` ? pagination.getInfo().beginCfi : beginItemIndex !== pagination.getInfo().beginSpineItemIndex ? cfiLocator.getRootCfi(beginSpineItem) : (
|
|
5935
|
+
/* @todo check ? */
|
|
5936
|
+
cfiLocator.getRootCfi(beginSpineItem)
|
|
5937
|
+
),
|
|
5730
5938
|
options: {
|
|
5731
5939
|
isAtEndOfChapter: false
|
|
5732
5940
|
}
|
|
@@ -5735,7 +5943,10 @@ const createSpine = ({
|
|
|
5735
5943
|
spineItem: endSpineItem,
|
|
5736
5944
|
spineItemIndex: endItemIndex,
|
|
5737
5945
|
pageIndex: endPageIndex,
|
|
5738
|
-
cfi: (lastExpectedNavigation == null ? void 0 : lastExpectedNavigation.type) === `navigate-from-cfi` && spineItemToFocus === endSpineItem ? lastExpectedNavigation.data : data.triggeredBy === `adjust` && context.getSettings().computedPageTurnMode === `controlled` ? pagination.getInfo().endCfi : endItemIndex !== pagination.getInfo().endSpineItemIndex ? cfiLocator.getRootCfi(endSpineItem) :
|
|
5946
|
+
cfi: (lastExpectedNavigation == null ? void 0 : lastExpectedNavigation.type) === `navigate-from-cfi` && spineItemToFocus === endSpineItem ? lastExpectedNavigation.data : data.triggeredBy === `adjust` && context.getSettings().computedPageTurnMode === `controlled` ? pagination.getInfo().endCfi : endItemIndex !== pagination.getInfo().endSpineItemIndex ? cfiLocator.getRootCfi(endSpineItem) : (
|
|
5947
|
+
/* @todo check ? */
|
|
5948
|
+
cfiLocator.getRootCfi(endSpineItem)
|
|
5949
|
+
),
|
|
5739
5950
|
options: {
|
|
5740
5951
|
isAtEndOfChapter: false
|
|
5741
5952
|
}
|
|
@@ -5765,7 +5976,16 @@ const createSpine = ({
|
|
|
5765
5976
|
takeUntil(context.$.destroy$)
|
|
5766
5977
|
).subscribe();
|
|
5767
5978
|
merge(
|
|
5979
|
+
/**
|
|
5980
|
+
* We want to update content after navigation since we are at a different place.
|
|
5981
|
+
* We also wait for navigated items to be updated so that we have access to correct focus.
|
|
5982
|
+
* which is why we use this observer rather than `navigation$`.
|
|
5983
|
+
*/
|
|
5768
5984
|
itemUpdateOnNavigation$,
|
|
5985
|
+
/**
|
|
5986
|
+
* This one make sure we also listen for layout change and that we execute the code once the navigation
|
|
5987
|
+
* has been adjusted (whether it's needed or not).
|
|
5988
|
+
*/
|
|
5769
5989
|
navigationAdjusted$
|
|
5770
5990
|
).pipe(
|
|
5771
5991
|
switchMap(() => {
|
|
@@ -5964,7 +6184,10 @@ const createSpineItemManager = ({ context }) => {
|
|
|
5964
6184
|
const isPrePaginated = ((_a = context.getManifest()) == null ? void 0 : _a.renditionLayout) === `pre-paginated`;
|
|
5965
6185
|
const isUsingFreeScroll = context.getSettings().computedPageTurnMode === `scrollable`;
|
|
5966
6186
|
orderedSpineItemsSubject$.value.forEach((orderedSpineItem, index) => {
|
|
5967
|
-
const isBeforeFocusedWithPreload =
|
|
6187
|
+
const isBeforeFocusedWithPreload = (
|
|
6188
|
+
// we never want to preload anything before on free scroll on flow because it could offset the cursor
|
|
6189
|
+
index < leftIndex && !isPrePaginated && isUsingFreeScroll ? true : index < leftIndex - numberOfAdjacentSpineItemToPreLoad
|
|
6190
|
+
);
|
|
5968
6191
|
const isAfterTailWithPreload = index > rightIndex + numberOfAdjacentSpineItemToPreLoad;
|
|
5969
6192
|
if (!isBeforeFocusedWithPreload && !isAfterTailWithPreload) {
|
|
5970
6193
|
orderedSpineItem.loadContent();
|
|
@@ -6170,7 +6393,8 @@ const createLocationResolver$1 = ({ context }) => {
|
|
|
6170
6393
|
var _a, _b, _c;
|
|
6171
6394
|
const pageSize = context.getPageSize();
|
|
6172
6395
|
const frame = (_b = (_a = spineItem.spineItemFrame) == null ? void 0 : _a.getManipulableFrame()) == null ? void 0 : _b.frame;
|
|
6173
|
-
if (((_c = frame == null ? void 0 : frame.contentWindow) == null ? void 0 : _c.document) &&
|
|
6396
|
+
if (((_c = frame == null ? void 0 : frame.contentWindow) == null ? void 0 : _c.document) && // very important because it is being used by next functions
|
|
6397
|
+
frame.contentWindow.document.body !== null) {
|
|
6174
6398
|
const { x: left, y: top } = getSpineItemPositionFromPageIndex(pageIndex, spineItem);
|
|
6175
6399
|
const viewport = {
|
|
6176
6400
|
left,
|
|
@@ -6740,8 +6964,14 @@ const createManualViewportNavigator = ({
|
|
|
6740
6964
|
chapterPageNavigation$,
|
|
6741
6965
|
leftPageNavigation$,
|
|
6742
6966
|
rightPageNavigation$,
|
|
6967
|
+
// for some reason after too much item ts complains
|
|
6743
6968
|
merge(cfiNavigation$, pageNavigation$)
|
|
6744
6969
|
).pipe(
|
|
6970
|
+
/**
|
|
6971
|
+
* Ideally when manually navigating we expect the navigation to be different from the previous one.
|
|
6972
|
+
* This is because manual navigation is not used with scroll where you can move within the same item. A manual
|
|
6973
|
+
* navigation would theoretically always move to different items.
|
|
6974
|
+
*/
|
|
6745
6975
|
withLatestFrom(currentNavigationSubject$),
|
|
6746
6976
|
filter(([navigation, currentNavigation]) => navigator2.areNavigationDifferent(navigation, currentNavigation)),
|
|
6747
6977
|
map(([navigation]) => navigation)
|
|
@@ -6916,6 +7146,9 @@ const createViewportNavigator = ({
|
|
|
6916
7146
|
}
|
|
6917
7147
|
const { x, y } = element.getBoundingClientRect();
|
|
6918
7148
|
const newValue = {
|
|
7149
|
+
// we want to round to first decimal because it's possible to have half pixel
|
|
7150
|
+
// however browser engine can also gives back x.yyyy based on their precision
|
|
7151
|
+
// @see https://stackoverflow.com/questions/13847053/difference-between-and-math-floor for ~~
|
|
6919
7152
|
x: ~~(Math.abs(x) * 10) / 10,
|
|
6920
7153
|
y: ~~(Math.abs(y) * 10) / 10
|
|
6921
7154
|
};
|
|
@@ -7126,6 +7359,14 @@ const createViewportNavigator = ({
|
|
|
7126
7359
|
const animationDuration = currentEvent.animation === `snap` ? context.getSettings().computedSnapAnimationDuration : context.getSettings().computedPageTurnAnimationDuration;
|
|
7127
7360
|
const pageTurnAnimation = currentEvent.animation === `snap` ? `slide` : context.getSettings().computedPageTurnAnimation;
|
|
7128
7361
|
return of(currentEvent).pipe(
|
|
7362
|
+
/**
|
|
7363
|
+
* @important
|
|
7364
|
+
* Optimization:
|
|
7365
|
+
* When the adjustment does not need animation it means we want to be there as fast as possible
|
|
7366
|
+
* One example is when we adjust position after layout. In this case we don't want to have flicker or see
|
|
7367
|
+
* anything for x ms while we effectively adjust. We want it to be immediate.
|
|
7368
|
+
* However when user is repeatedly turning page, we can improve smoothness by delaying a bit the adjustment
|
|
7369
|
+
*/
|
|
7129
7370
|
currentEvent.shouldAnimate ? delay(1, animationFrameScheduler) : identity$1,
|
|
7130
7371
|
tap((data) => {
|
|
7131
7372
|
const noAdjustmentNeeded = false;
|
|
@@ -7142,6 +7383,14 @@ const createViewportNavigator = ({
|
|
|
7142
7383
|
element.style.setProperty(`opacity`, `1`);
|
|
7143
7384
|
}
|
|
7144
7385
|
}),
|
|
7386
|
+
/**
|
|
7387
|
+
* @important
|
|
7388
|
+
* We always need to adjust the reading offset. Even if the current viewport value
|
|
7389
|
+
* is the same as the payload position. This is because an already running animation could
|
|
7390
|
+
* be active, meaning the viewport is still adjusting itself (after animation duration). So we
|
|
7391
|
+
* need to adjust to anchor to the payload position. This is because we use viewport computed position,
|
|
7392
|
+
* not the value set by `setProperty`
|
|
7393
|
+
*/
|
|
7145
7394
|
withLatestFrom(hooks$),
|
|
7146
7395
|
tap(([data, hooks]) => {
|
|
7147
7396
|
if (pageTurnAnimation !== `fade`) {
|
|
@@ -7180,6 +7429,12 @@ const createViewportNavigator = ({
|
|
|
7180
7429
|
map((states) => states.every((state) => state === `end`) ? `free` : `busy`),
|
|
7181
7430
|
distinctUntilChanged(),
|
|
7182
7431
|
shareReplay(1),
|
|
7432
|
+
/**
|
|
7433
|
+
* @important
|
|
7434
|
+
* Since state$ is being updated from navigation$ and other exported streams we need it to be
|
|
7435
|
+
* hot so it always have the correct value no matter when someone subscribe later.
|
|
7436
|
+
* We cannot wait for the cold stream to start after a navigation already happened for example.
|
|
7437
|
+
*/
|
|
7183
7438
|
makeItHot
|
|
7184
7439
|
);
|
|
7185
7440
|
const waitForViewportFree$ = state$.pipe(
|
|
@@ -7187,6 +7442,24 @@ const createViewportNavigator = ({
|
|
|
7187
7442
|
take$1(1)
|
|
7188
7443
|
);
|
|
7189
7444
|
const navigationAdjustedAfterLayout$ = spine.$.layout$.pipe(
|
|
7445
|
+
/**
|
|
7446
|
+
* @important
|
|
7447
|
+
* Careful with using debounce / throttle here since it can decrease user experience
|
|
7448
|
+
* when layout happens it can means an item before the current one has been unloaded, at current code
|
|
7449
|
+
* we unload and size back each item to the screen so it will have the effect of flicker for user.
|
|
7450
|
+
* Consider this workflow:
|
|
7451
|
+
* - user navigate to page 2
|
|
7452
|
+
* - viewport move to item 2
|
|
7453
|
+
* - page 1 unload and goes back from 2000px to 500px
|
|
7454
|
+
* - layout triggered
|
|
7455
|
+
* - viewport is now on an item far after item 2 because item 1 shrink (PROBLEM)
|
|
7456
|
+
* - sometime after viewport is adjusted back to item 2.
|
|
7457
|
+
*
|
|
7458
|
+
* Two solution to fix this issue:
|
|
7459
|
+
* - maybe later try to implement a different strategy and never shrink back item unless they are loaded
|
|
7460
|
+
* - do not use debounce / throttle and navigate back to the item right on the same tick
|
|
7461
|
+
*/
|
|
7462
|
+
// debounceTime(10, animationFrameScheduler),
|
|
7190
7463
|
switchMap(
|
|
7191
7464
|
() => waitForViewportFree$.pipe(
|
|
7192
7465
|
switchMap(() => {
|
|
@@ -7256,10 +7529,18 @@ const createLocationResolver = ({
|
|
|
7256
7529
|
if (context.isRTL()) {
|
|
7257
7530
|
return {
|
|
7258
7531
|
x: leftEnd - position.x - context.getPageSize().width,
|
|
7532
|
+
// y: (topEnd - position.y) - context.getPageSize().height,
|
|
7259
7533
|
y: Math.max(0, position.y - topStart)
|
|
7260
7534
|
};
|
|
7261
7535
|
}
|
|
7262
7536
|
return {
|
|
7537
|
+
/**
|
|
7538
|
+
* when using spread the item could be on the right and therefore will be negative
|
|
7539
|
+
* @example
|
|
7540
|
+
* 400 (position = viewport), page of 200
|
|
7541
|
+
* 400 - 600 = -200.
|
|
7542
|
+
* However we can assume we are at 0, because we in fact can see the beginning of the item
|
|
7543
|
+
*/
|
|
7263
7544
|
x: Math.max(0, position.x - leftStart),
|
|
7264
7545
|
y: Math.max(0, position.y - topStart)
|
|
7265
7546
|
};
|
|
@@ -7271,6 +7552,7 @@ const createLocationResolver = ({
|
|
|
7271
7552
|
if (context.isRTL()) {
|
|
7272
7553
|
return {
|
|
7273
7554
|
x: leftEnd - spineItemPosition.x - context.getPageSize().width,
|
|
7555
|
+
// y: (topEnd - spineItemPosition.y) - context.getPageSize().height,
|
|
7274
7556
|
y: topStart + spineItemPosition.y
|
|
7275
7557
|
};
|
|
7276
7558
|
}
|
|
@@ -7611,10 +7893,23 @@ const createReader = ({ containerElement, hooks: initialHooks, ...settings }) =>
|
|
|
7611
7893
|
destroy,
|
|
7612
7894
|
setSettings: context.setSettings,
|
|
7613
7895
|
settings$: context.$.settings$,
|
|
7896
|
+
/**
|
|
7897
|
+
* @important
|
|
7898
|
+
* BehaviorSubject
|
|
7899
|
+
*/
|
|
7614
7900
|
pagination$: pagination.$.info$,
|
|
7615
7901
|
$: {
|
|
7616
7902
|
state$: stateSubject$.asObservable(),
|
|
7903
|
+
/**
|
|
7904
|
+
* Dispatched when the reader has loaded a book and is displayed a book.
|
|
7905
|
+
* Using navigation API and getting information about current content will
|
|
7906
|
+
* have an effect.
|
|
7907
|
+
* It can typically be used to hide a loading indicator.
|
|
7908
|
+
*/
|
|
7617
7909
|
ready$: readySubject$.asObservable(),
|
|
7910
|
+
/**
|
|
7911
|
+
* Dispatched when a change in selection happens
|
|
7912
|
+
*/
|
|
7618
7913
|
selection$: selectionSubject$.asObservable(),
|
|
7619
7914
|
viewportState$: viewportNavigator.$.state$,
|
|
7620
7915
|
layout$: spine.$.layout$,
|
|
@@ -7866,6 +8161,10 @@ const resourcesEnhancer = (next) => (options) => {
|
|
|
7866
8161
|
};
|
|
7867
8162
|
return {
|
|
7868
8163
|
...reader,
|
|
8164
|
+
// $: {
|
|
8165
|
+
// ...reader.$,
|
|
8166
|
+
// errors$: merge(reader.$.errors$, errorsSubject$.asObservable())
|
|
8167
|
+
// },
|
|
7869
8168
|
destroy,
|
|
7870
8169
|
load
|
|
7871
8170
|
};
|
|
@@ -8004,7 +8303,11 @@ const accessibilityEnhancer = (next) => (options) => {
|
|
|
8004
8303
|
`prose-reader-accessibility`,
|
|
8005
8304
|
`
|
|
8006
8305
|
:focus-visible {
|
|
8007
|
-
${
|
|
8306
|
+
${/*
|
|
8307
|
+
Some epubs remove the outline, this is not good practice since it reduce accessibility.
|
|
8308
|
+
We will try to restore it by force.
|
|
8309
|
+
*/
|
|
8310
|
+
``}
|
|
8008
8311
|
outline: -webkit-focus-ring-color auto 1px;
|
|
8009
8312
|
}
|
|
8010
8313
|
`
|
|
@@ -8159,23 +8462,27 @@ const defaultLoadingElementCreate = ({ container, item }) => {
|
|
|
8159
8462
|
container.appendChild(detailsElement);
|
|
8160
8463
|
return container;
|
|
8161
8464
|
};
|
|
8162
|
-
const createReaderWithEnhancers =
|
|
8163
|
-
|
|
8164
|
-
|
|
8165
|
-
|
|
8166
|
-
|
|
8167
|
-
|
|
8168
|
-
|
|
8169
|
-
|
|
8170
|
-
|
|
8171
|
-
|
|
8172
|
-
|
|
8173
|
-
|
|
8174
|
-
|
|
8175
|
-
|
|
8176
|
-
|
|
8177
|
-
|
|
8178
|
-
|
|
8465
|
+
const createReaderWithEnhancers = (
|
|
8466
|
+
//__
|
|
8467
|
+
loadingEnhancer(
|
|
8468
|
+
webkitEnhancer(
|
|
8469
|
+
fontsEnhancer(
|
|
8470
|
+
linksEnhancer(
|
|
8471
|
+
accessibilityEnhancer(
|
|
8472
|
+
resourcesEnhancer(
|
|
8473
|
+
utilsEnhancer(
|
|
8474
|
+
layoutEnhancer(
|
|
8475
|
+
zoomEnhancer(
|
|
8476
|
+
mediaEnhancer(
|
|
8477
|
+
chromeEnhancer(
|
|
8478
|
+
navigationEnhancer(
|
|
8479
|
+
themeEnhancer(
|
|
8480
|
+
hotkeysEnhancer(
|
|
8481
|
+
paginationEnhancer(
|
|
8482
|
+
progressionEnhancer(
|
|
8483
|
+
// __
|
|
8484
|
+
createReader
|
|
8485
|
+
)
|
|
8179
8486
|
)
|
|
8180
8487
|
)
|
|
8181
8488
|
)
|