@prose-reader/core 1.126.0 → 1.128.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/createReaderWithEnhancer.d.ts +2 -7
- package/dist/enhancers/html/renderer/HtmlRenderer.d.ts +4 -4
- package/dist/enhancers/media/ImageRenderer.d.ts +4 -4
- package/dist/enhancers/pagination/pagination.d.ts +1 -1
- package/dist/enhancers/progression.d.ts +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +517 -412
- package/dist/index.js.map +1 -1
- package/dist/index.umd.cjs +515 -410
- package/dist/index.umd.cjs.map +1 -1
- package/dist/navigation/tests/SpineItemsManagerMock.d.ts +4 -1
- package/dist/reader.d.ts +1 -6
- package/dist/settings/types.d.ts +1 -1
- package/dist/spine/SpineLayout.d.ts +9 -7
- package/dist/spine/layout/layoutItem.d.ts +20 -0
- package/dist/spineItem/SpineItem.d.ts +14 -20
- package/dist/spineItem/renderer/DefaultRenderer.d.ts +8 -0
- package/dist/spineItem/{DocumentRenderer.d.ts → renderer/DocumentRenderer.d.ts} +17 -20
- package/dist/utils/rxjs.d.ts +1 -0
- package/package.json +3 -3
package/dist/index.umd.cjs
CHANGED
|
@@ -112,6 +112,78 @@
|
|
|
112
112
|
};
|
|
113
113
|
}
|
|
114
114
|
};
|
|
115
|
+
const getAttributeValueFromString = (string, key) => {
|
|
116
|
+
const regExp = new RegExp(key + `\\s*=\\s*([0-9.]+)`, `i`);
|
|
117
|
+
const match = string.match(regExp) || [];
|
|
118
|
+
const firstMatch = match[1] || `0`;
|
|
119
|
+
return match && parseFloat(firstMatch) || 0;
|
|
120
|
+
};
|
|
121
|
+
const injectCSS = (frameElement, id, style, prepend) => {
|
|
122
|
+
if (frameElement && frameElement.contentDocument && frameElement.contentDocument.head) {
|
|
123
|
+
const userStyle = document.createElement(`style`);
|
|
124
|
+
userStyle.id = id;
|
|
125
|
+
userStyle.innerHTML = style;
|
|
126
|
+
if (prepend) {
|
|
127
|
+
frameElement.contentDocument.head.prepend(userStyle);
|
|
128
|
+
} else {
|
|
129
|
+
frameElement.contentDocument.head.appendChild(userStyle);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
const removeCSS = (frameElement, id) => {
|
|
134
|
+
if (frameElement && frameElement.contentDocument && frameElement.contentDocument.head) {
|
|
135
|
+
const styleElement = frameElement.contentDocument.getElementById(id);
|
|
136
|
+
if (styleElement) {
|
|
137
|
+
styleElement.remove();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
const upsertCSS = (frameElement, id, style, prepend) => {
|
|
142
|
+
if (!frameElement) return;
|
|
143
|
+
removeCSS(frameElement, id);
|
|
144
|
+
injectCSS(frameElement, id, style, prepend);
|
|
145
|
+
};
|
|
146
|
+
const getFrameViewportInfo = (frame) => {
|
|
147
|
+
if (frame && (frame == null ? void 0 : frame.contentDocument)) {
|
|
148
|
+
const doc = frame.contentDocument;
|
|
149
|
+
const viewportMetaElement = doc.querySelector(`meta[name='viewport']`);
|
|
150
|
+
if (viewportMetaElement) {
|
|
151
|
+
const viewportContent = viewportMetaElement.getAttribute(`content`);
|
|
152
|
+
if (viewportContent) {
|
|
153
|
+
const width = getAttributeValueFromString(viewportContent, `width`);
|
|
154
|
+
const height = getAttributeValueFromString(viewportContent, `height`);
|
|
155
|
+
if (width > 0 && height > 0) {
|
|
156
|
+
return {
|
|
157
|
+
hasViewport: true,
|
|
158
|
+
width,
|
|
159
|
+
height
|
|
160
|
+
};
|
|
161
|
+
} else {
|
|
162
|
+
return { hasViewport: true };
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return { hasViewport: false };
|
|
168
|
+
};
|
|
169
|
+
const waitForFrameLoad = (stream) => stream.pipe(
|
|
170
|
+
rxjs.switchMap(
|
|
171
|
+
(frame) => rxjs.fromEvent(frame, `load`).pipe(
|
|
172
|
+
rxjs.take(1),
|
|
173
|
+
rxjs.map(() => frame)
|
|
174
|
+
)
|
|
175
|
+
)
|
|
176
|
+
);
|
|
177
|
+
const waitForFrameReady = (stream) => stream.pipe(
|
|
178
|
+
rxjs.switchMap(
|
|
179
|
+
(frame) => {
|
|
180
|
+
var _a;
|
|
181
|
+
return rxjs.from(((_a = frame == null ? void 0 : frame.contentDocument) == null ? void 0 : _a.fonts.ready) || rxjs.of(void 0)).pipe(
|
|
182
|
+
rxjs.map(() => frame)
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
)
|
|
186
|
+
);
|
|
115
187
|
const fontsEnhancer = (next) => (options) => {
|
|
116
188
|
const { fontScale, lineHeight, fontWeight, fontJustification } = options;
|
|
117
189
|
const changes$ = new rxjs.Subject();
|
|
@@ -144,9 +216,12 @@
|
|
|
144
216
|
`;
|
|
145
217
|
const applyChangeToSpineItems = (requireLayout) => {
|
|
146
218
|
reader.spineItemsManager.items.forEach((item) => {
|
|
147
|
-
var _a;
|
|
148
219
|
if (item.item.renditionLayout !== `pre-paginated`) {
|
|
149
|
-
|
|
220
|
+
item.renderer.layers.forEach((layer) => {
|
|
221
|
+
if (layer.element instanceof HTMLIFrameElement) {
|
|
222
|
+
upsertCSS(layer.element, `prose-reader-fonts`, getStyle());
|
|
223
|
+
}
|
|
224
|
+
});
|
|
150
225
|
}
|
|
151
226
|
});
|
|
152
227
|
if (requireLayout) {
|
|
@@ -156,7 +231,11 @@
|
|
|
156
231
|
reader.hookManager.register(`item.onDocumentLoad`, ({ itemId }) => {
|
|
157
232
|
const item = reader.spineItemsManager.get(itemId);
|
|
158
233
|
if ((item == null ? void 0 : item.item.renditionLayout) !== `pre-paginated`) {
|
|
159
|
-
item == null ? void 0 : item.
|
|
234
|
+
item == null ? void 0 : item.renderer.layers.forEach((layer) => {
|
|
235
|
+
if (layer.element instanceof HTMLIFrameElement) {
|
|
236
|
+
upsertCSS(layer.element, `prose-reader-fonts`, getStyle());
|
|
237
|
+
}
|
|
238
|
+
});
|
|
160
239
|
}
|
|
161
240
|
});
|
|
162
241
|
const shouldRequireLayout = (source) => source.pipe(
|
|
@@ -314,78 +393,19 @@
|
|
|
314
393
|
)
|
|
315
394
|
)
|
|
316
395
|
);
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
userStyle.id = id;
|
|
327
|
-
userStyle.innerHTML = style;
|
|
328
|
-
if (prepend) {
|
|
329
|
-
frameElement.contentDocument.head.prepend(userStyle);
|
|
330
|
-
} else {
|
|
331
|
-
frameElement.contentDocument.head.appendChild(userStyle);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
};
|
|
335
|
-
const removeCSS = (frameElement, id) => {
|
|
336
|
-
if (frameElement && frameElement.contentDocument && frameElement.contentDocument.head) {
|
|
337
|
-
const styleElement = frameElement.contentDocument.getElementById(id);
|
|
338
|
-
if (styleElement) {
|
|
339
|
-
styleElement.remove();
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
};
|
|
343
|
-
const upsertCSS = (frameElement, id, style, prepend) => {
|
|
344
|
-
if (!frameElement) return;
|
|
345
|
-
removeCSS(frameElement, id);
|
|
346
|
-
injectCSS(frameElement, id, style, prepend);
|
|
347
|
-
};
|
|
348
|
-
const getFrameViewportInfo = (frame) => {
|
|
349
|
-
if (frame && (frame == null ? void 0 : frame.contentDocument)) {
|
|
350
|
-
const doc = frame.contentDocument;
|
|
351
|
-
const viewportMetaElement = doc.querySelector(`meta[name='viewport']`);
|
|
352
|
-
if (viewportMetaElement) {
|
|
353
|
-
const viewportContent = viewportMetaElement.getAttribute(`content`);
|
|
354
|
-
if (viewportContent) {
|
|
355
|
-
const width = getAttributeValueFromString(viewportContent, `width`);
|
|
356
|
-
const height = getAttributeValueFromString(viewportContent, `height`);
|
|
357
|
-
if (width > 0 && height > 0) {
|
|
358
|
-
return {
|
|
359
|
-
hasViewport: true,
|
|
360
|
-
width,
|
|
361
|
-
height
|
|
362
|
-
};
|
|
363
|
-
} else {
|
|
364
|
-
return { hasViewport: true };
|
|
365
|
-
}
|
|
366
|
-
}
|
|
396
|
+
const deferNextResult = (stream) => {
|
|
397
|
+
let value;
|
|
398
|
+
const sub = stream.subscribe((result) => {
|
|
399
|
+
value = { result };
|
|
400
|
+
});
|
|
401
|
+
return () => {
|
|
402
|
+
sub.unsubscribe();
|
|
403
|
+
if (value) {
|
|
404
|
+
return rxjs.of(value.result);
|
|
367
405
|
}
|
|
368
|
-
|
|
369
|
-
|
|
406
|
+
return stream;
|
|
407
|
+
};
|
|
370
408
|
};
|
|
371
|
-
const waitForFrameLoad = (stream) => stream.pipe(
|
|
372
|
-
rxjs.switchMap(
|
|
373
|
-
(frame) => rxjs.fromEvent(frame, `load`).pipe(
|
|
374
|
-
rxjs.take(1),
|
|
375
|
-
rxjs.map(() => frame)
|
|
376
|
-
)
|
|
377
|
-
)
|
|
378
|
-
);
|
|
379
|
-
const waitForFrameReady = (stream) => stream.pipe(
|
|
380
|
-
rxjs.switchMap(
|
|
381
|
-
(frame) => {
|
|
382
|
-
var _a;
|
|
383
|
-
return rxjs.from(((_a = frame == null ? void 0 : frame.contentDocument) == null ? void 0 : _a.fonts.ready) || rxjs.of(void 0)).pipe(
|
|
384
|
-
rxjs.map(() => frame)
|
|
385
|
-
);
|
|
386
|
-
}
|
|
387
|
-
)
|
|
388
|
-
);
|
|
389
409
|
const fixReflowable = (reader) => {
|
|
390
410
|
reader.hookManager.register(
|
|
391
411
|
`item.onAfterLayout`,
|
|
@@ -479,28 +499,33 @@
|
|
|
479
499
|
columnWidth = columnHeight;
|
|
480
500
|
columnGap = pageVerticalMargin2 * 2;
|
|
481
501
|
}
|
|
482
|
-
spineItem == null ? void 0 : spineItem.
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
502
|
+
spineItem == null ? void 0 : spineItem.renderer.layers.forEach((layer) => {
|
|
503
|
+
if (layer.element instanceof HTMLIFrameElement) {
|
|
504
|
+
upsertCSS(
|
|
505
|
+
layer.element,
|
|
506
|
+
`prose-layout-enhancer-css`,
|
|
507
|
+
`
|
|
508
|
+
body {
|
|
509
|
+
width: ${width}px !important;
|
|
510
|
+
margin: ${pageVerticalMargin2}px ${pageHorizontalMargin2}px !important;
|
|
511
|
+
column-gap: ${columnGap}px !important;
|
|
512
|
+
column-width: ${columnWidth}px !important;
|
|
513
|
+
height: ${columnHeight}px !important;
|
|
514
|
+
}
|
|
515
|
+
img, video, audio, object, svg {
|
|
516
|
+
max-width: ${columnWidth}px !important;
|
|
517
|
+
max-height: ${columnHeight}px !important;
|
|
518
|
+
}
|
|
519
|
+
table {
|
|
520
|
+
max-width: ${columnWidth}px !important;
|
|
521
|
+
}
|
|
522
|
+
td {
|
|
523
|
+
max-width: ${columnWidth}px;
|
|
524
|
+
}
|
|
525
|
+
`
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
});
|
|
504
529
|
}
|
|
505
530
|
});
|
|
506
531
|
fixReflowable(reader);
|
|
@@ -1350,66 +1375,79 @@
|
|
|
1350
1375
|
);
|
|
1351
1376
|
return totalPages$;
|
|
1352
1377
|
};
|
|
1353
|
-
const mapPaginationInfoToExtendedInfo = (reader
|
|
1378
|
+
const mapPaginationInfoToExtendedInfo = (reader, paginationInfo, chaptersInfo) => {
|
|
1354
1379
|
const context = reader.context;
|
|
1355
1380
|
const beginItem = paginationInfo.beginSpineItemIndex !== void 0 ? reader.spineItemsManager.get(paginationInfo.beginSpineItemIndex) : void 0;
|
|
1356
1381
|
const endItem = paginationInfo.endSpineItemIndex !== void 0 ? reader.spineItemsManager.get(paginationInfo.endSpineItemIndex) : void 0;
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1382
|
+
const endItemProgression$ = endItem ? reader.progression.getPercentageEstimate(
|
|
1383
|
+
context,
|
|
1384
|
+
paginationInfo.endSpineItemIndex ?? 0,
|
|
1385
|
+
paginationInfo.endNumberOfPagesInSpineItem,
|
|
1386
|
+
paginationInfo.endPageIndexInSpineItem || 0,
|
|
1387
|
+
reader.navigation.getNavigation().position,
|
|
1388
|
+
endItem
|
|
1389
|
+
) : rxjs.of(0);
|
|
1390
|
+
return endItemProgression$.pipe(
|
|
1391
|
+
rxjs.map((percentageEstimateOfBook) => ({
|
|
1392
|
+
...paginationInfo,
|
|
1393
|
+
beginChapterInfo: beginItem ? chaptersInfo[beginItem.item.id] : void 0,
|
|
1394
|
+
// chapterIndex: number;
|
|
1395
|
+
// pages: number;
|
|
1396
|
+
// pageIndexInBook: number;
|
|
1397
|
+
// pageIndexInChapter: number;
|
|
1398
|
+
// pagesOfChapter: number;
|
|
1399
|
+
// pagePercentageInChapter: number;
|
|
1400
|
+
// offsetPercentageInChapter: number;
|
|
1401
|
+
// domIndex: number;
|
|
1402
|
+
// charOffset: number;
|
|
1403
|
+
// serializeString?: string;
|
|
1404
|
+
beginSpineItemReadingDirection: beginItem == null ? void 0 : beginItem.readingDirection,
|
|
1405
|
+
endChapterInfo: endItem ? chaptersInfo[endItem.item.id] : void 0,
|
|
1406
|
+
endSpineItemReadingDirection: endItem == null ? void 0 : endItem.readingDirection,
|
|
1407
|
+
// spineItemReadingDirection: focusedSpineItem?.getReadingDirection(),
|
|
1408
|
+
/**
|
|
1409
|
+
* This percentage is based of the weight (kb) of every items and the number of pages.
|
|
1410
|
+
* It is not accurate but gives a general good idea of the overall progress.
|
|
1411
|
+
* It is recommended to use this progress only for reflow books. For pre-paginated books
|
|
1412
|
+
* the number of pages and current index can be used instead since 1 page = 1 chapter.
|
|
1413
|
+
*/
|
|
1414
|
+
percentageEstimateOfBook,
|
|
1415
|
+
isUsingSpread: context.state.isUsingSpreadMode ?? false
|
|
1416
|
+
// hasNextChapter: (reader.spine.spineItemIndex || 0) < (manifest.readingOrder.length - 1),
|
|
1417
|
+
// hasPreviousChapter: (reader.spine.spineItemIndex || 0) < (manifest.readingOrder.length - 1),
|
|
1418
|
+
// numberOfSpineItems: context.manifest?.readingOrder.length,
|
|
1419
|
+
}))
|
|
1420
|
+
);
|
|
1393
1421
|
};
|
|
1394
1422
|
const trackPaginationInfo = (reader) => {
|
|
1395
1423
|
const chaptersInfo$ = trackChapterInfo(reader);
|
|
1396
1424
|
const totalPages$ = trackTotalPages(reader);
|
|
1397
1425
|
const currentValue = new rxjs.BehaviorSubject({
|
|
1398
1426
|
...reader.pagination.getState(),
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1427
|
+
beginChapterInfo: void 0,
|
|
1428
|
+
beginCfi: void 0,
|
|
1429
|
+
beginPageIndexInSpineItem: void 0,
|
|
1430
|
+
isUsingSpread: false,
|
|
1403
1431
|
beginAbsolutePageIndex: 0,
|
|
1404
1432
|
endAbsolutePageIndex: 0,
|
|
1405
|
-
numberOfTotalPages: 0
|
|
1433
|
+
numberOfTotalPages: 0,
|
|
1434
|
+
beginSpineItemReadingDirection: void 0,
|
|
1435
|
+
beginSpineItemIndex: void 0,
|
|
1436
|
+
endCfi: void 0,
|
|
1437
|
+
endChapterInfo: void 0,
|
|
1438
|
+
endSpineItemReadingDirection: void 0,
|
|
1439
|
+
percentageEstimateOfBook: 0
|
|
1406
1440
|
});
|
|
1407
1441
|
const extandedBasePagination$ = reader.pagination.state$.pipe(
|
|
1408
1442
|
rxjs.combineLatestWith(chaptersInfo$),
|
|
1409
|
-
rxjs.
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1443
|
+
rxjs.switchMap(
|
|
1444
|
+
([info, chaptersInfo]) => mapPaginationInfoToExtendedInfo(reader, info, chaptersInfo).pipe(
|
|
1445
|
+
rxjs.map((extendedInfo) => ({
|
|
1446
|
+
...info,
|
|
1447
|
+
...extendedInfo
|
|
1448
|
+
}))
|
|
1449
|
+
)
|
|
1450
|
+
),
|
|
1413
1451
|
rxjs.distinctUntilChanged(shared.isShallowEqual)
|
|
1414
1452
|
);
|
|
1415
1453
|
const paginationInfo$ = rxjs.combineLatest([
|
|
@@ -1508,15 +1546,22 @@
|
|
|
1508
1546
|
};
|
|
1509
1547
|
const applyChangeToSpineItem = () => {
|
|
1510
1548
|
reader.spineItemsManager.items.forEach((item) => {
|
|
1511
|
-
|
|
1512
|
-
|
|
1549
|
+
item.renderer.layers.forEach((layer) => {
|
|
1550
|
+
if (layer.element instanceof HTMLIFrameElement) {
|
|
1551
|
+
upsertCSS(layer.element, `prose-reader-theme`, getStyle());
|
|
1552
|
+
}
|
|
1553
|
+
});
|
|
1513
1554
|
applyChangeToSpineItemElement({ container: item.element });
|
|
1514
1555
|
});
|
|
1515
1556
|
};
|
|
1516
1557
|
reader.hookManager.register(`item.onDocumentLoad`, ({ itemId }) => {
|
|
1517
1558
|
const item = reader.spineItemsManager.get(itemId);
|
|
1518
1559
|
if ((item == null ? void 0 : item.item.renditionLayout) !== "pre-paginated") {
|
|
1519
|
-
item == null ? void 0 : item.
|
|
1560
|
+
item == null ? void 0 : item.renderer.layers.forEach((layer) => {
|
|
1561
|
+
if (layer.element instanceof HTMLIFrameElement) {
|
|
1562
|
+
upsertCSS(layer.element, `prose-reader-theme`, getStyle());
|
|
1563
|
+
}
|
|
1564
|
+
});
|
|
1520
1565
|
}
|
|
1521
1566
|
});
|
|
1522
1567
|
reader.spineItemsManager.items$.pipe(
|
|
@@ -1923,7 +1968,8 @@
|
|
|
1923
1968
|
function createRangeOrCaretFromPoint(doc, startX, startY) {
|
|
1924
1969
|
if (`caretPositionFromPoint` in doc) {
|
|
1925
1970
|
return doc.caretPositionFromPoint(startX, startY);
|
|
1926
|
-
} else if (
|
|
1971
|
+
} else if ("caretRangeFromPoint" in doc && // @ts-expect-error limited availability
|
|
1972
|
+
typeof doc.caretRangeFromPoint !== `undefined`) {
|
|
1927
1973
|
return doc.caretRangeFromPoint(startX, startY);
|
|
1928
1974
|
}
|
|
1929
1975
|
}
|
|
@@ -5169,14 +5215,35 @@
|
|
|
5169
5215
|
const endCFI = generateCfi(endNode, end, item);
|
|
5170
5216
|
return { start: startCFI, end: endCFI };
|
|
5171
5217
|
};
|
|
5172
|
-
|
|
5218
|
+
const defaultGetResource = (item) => new URL(item.href);
|
|
5219
|
+
class ResourceHandler {
|
|
5220
|
+
constructor(item, settings) {
|
|
5221
|
+
this.item = item;
|
|
5222
|
+
this.settings = settings;
|
|
5223
|
+
}
|
|
5224
|
+
async getResource() {
|
|
5225
|
+
var _a, _b;
|
|
5226
|
+
const resource = await rxjs.lastValueFrom(
|
|
5227
|
+
((_b = (_a = this.settings.values).getResource) == null ? void 0 : _b.call(_a, this.item)) ?? rxjs.of(void 0)
|
|
5228
|
+
);
|
|
5229
|
+
return resource ?? defaultGetResource(this.item);
|
|
5230
|
+
}
|
|
5231
|
+
async fetchResource() {
|
|
5232
|
+
const resource = await this.getResource();
|
|
5233
|
+
if (resource instanceof Response) return resource;
|
|
5234
|
+
if (resource instanceof URL) return fetch(resource);
|
|
5235
|
+
return resource;
|
|
5236
|
+
}
|
|
5237
|
+
}
|
|
5238
|
+
class DocumentRenderer extends DestroyableClass {
|
|
5173
5239
|
constructor(params) {
|
|
5240
|
+
super();
|
|
5174
5241
|
this.triggerSubject = new rxjs.Subject();
|
|
5175
5242
|
this.stateSubject = new rxjs.BehaviorSubject(`idle`);
|
|
5176
5243
|
this.unload$ = this.triggerSubject.pipe(
|
|
5177
5244
|
rxjs.withLatestFrom(this.stateSubject),
|
|
5178
5245
|
rxjs.filter(
|
|
5179
|
-
([trigger, state]) => trigger === `unload` && state !== "idle" && state !== "unloading"
|
|
5246
|
+
([trigger, state]) => trigger.type === `unload` && state !== "idle" && state !== "unloading"
|
|
5180
5247
|
),
|
|
5181
5248
|
rxjs.map(() => void 0),
|
|
5182
5249
|
rxjs.share()
|
|
@@ -5184,21 +5251,26 @@
|
|
|
5184
5251
|
this.load$ = this.triggerSubject.pipe(
|
|
5185
5252
|
rxjs.withLatestFrom(this.stateSubject),
|
|
5186
5253
|
rxjs.filter(
|
|
5187
|
-
([trigger, state]) => trigger === `load` && state !== "
|
|
5254
|
+
([trigger, state]) => trigger.type === `load` && state !== "loaded" && state !== "loading"
|
|
5188
5255
|
),
|
|
5189
5256
|
rxjs.map(() => void 0),
|
|
5190
5257
|
rxjs.share()
|
|
5191
5258
|
);
|
|
5192
5259
|
this.layers = [];
|
|
5193
|
-
this.destroy$ = this.triggerSubject.pipe(
|
|
5194
|
-
rxjs.filter((trigger) => trigger === `destroy`)
|
|
5195
|
-
);
|
|
5196
5260
|
this.context = params.context;
|
|
5197
5261
|
this.settings = params.settings;
|
|
5198
5262
|
this.hookManager = params.hookManager;
|
|
5199
5263
|
this.item = params.item;
|
|
5200
5264
|
this.containerElement = params.containerElement;
|
|
5201
5265
|
this.resourcesHandler = params.resourcesHandler;
|
|
5266
|
+
const unloadTrigger$ = this.triggerSubject.pipe(
|
|
5267
|
+
rxjs.withLatestFrom(this.stateSubject),
|
|
5268
|
+
rxjs.filter(
|
|
5269
|
+
([trigger, state]) => trigger.type === `unload` && state !== "idle" && state !== "unloading"
|
|
5270
|
+
),
|
|
5271
|
+
rxjs.map(() => void 0),
|
|
5272
|
+
rxjs.share()
|
|
5273
|
+
);
|
|
5202
5274
|
this.load$.pipe(
|
|
5203
5275
|
rxjs.switchMap(() => {
|
|
5204
5276
|
this.stateSubject.next(`loading`);
|
|
@@ -5232,13 +5304,12 @@
|
|
|
5232
5304
|
}),
|
|
5233
5305
|
rxjs.tap(() => {
|
|
5234
5306
|
this.stateSubject.next(`loaded`);
|
|
5235
|
-
this.stateSubject.next(`ready`);
|
|
5236
5307
|
}),
|
|
5237
|
-
rxjs.takeUntil(rxjs.merge(this.destroy$,
|
|
5308
|
+
rxjs.takeUntil(rxjs.merge(this.destroy$, unloadTrigger$))
|
|
5238
5309
|
);
|
|
5239
5310
|
})
|
|
5240
5311
|
).subscribe();
|
|
5241
|
-
|
|
5312
|
+
const unload$ = unloadTrigger$.pipe(
|
|
5242
5313
|
rxjs.switchMap(() => {
|
|
5243
5314
|
this.stateSubject.next(`unloading`);
|
|
5244
5315
|
return this.context.bridgeEvent.viewportFree$.pipe(
|
|
@@ -5247,29 +5318,32 @@
|
|
|
5247
5318
|
this.hookManager.destroy(`item.onDocumentLoad`, this.item.id);
|
|
5248
5319
|
}),
|
|
5249
5320
|
rxjs.switchMap(() => {
|
|
5250
|
-
const
|
|
5251
|
-
return
|
|
5321
|
+
const onUnload$ = this.onUnload().pipe(rxjs.endWith(null), rxjs.first());
|
|
5322
|
+
return onUnload$;
|
|
5252
5323
|
}),
|
|
5253
5324
|
rxjs.tap(() => {
|
|
5254
5325
|
this.stateSubject.next(`idle`);
|
|
5255
5326
|
}),
|
|
5256
|
-
rxjs.takeUntil(
|
|
5327
|
+
rxjs.takeUntil(this.load$)
|
|
5257
5328
|
);
|
|
5258
5329
|
})
|
|
5259
|
-
)
|
|
5330
|
+
);
|
|
5331
|
+
rxjs.merge(unload$).pipe(rxjs.takeUntil(this.destroy$)).subscribe();
|
|
5260
5332
|
}
|
|
5261
5333
|
get state$() {
|
|
5262
5334
|
return this.stateSubject;
|
|
5263
5335
|
}
|
|
5336
|
+
get isLoaded$() {
|
|
5337
|
+
return this.state$.pipe(rxjs.map((state) => state === `loaded`));
|
|
5338
|
+
}
|
|
5264
5339
|
load() {
|
|
5265
|
-
this.triggerSubject.next(`load`);
|
|
5340
|
+
this.triggerSubject.next({ type: `load` });
|
|
5266
5341
|
}
|
|
5267
5342
|
unload() {
|
|
5268
|
-
this.triggerSubject.next(`unload`);
|
|
5343
|
+
this.triggerSubject.next({ type: `unload` });
|
|
5269
5344
|
}
|
|
5270
5345
|
destroy() {
|
|
5271
|
-
|
|
5272
|
-
this.triggerSubject.complete();
|
|
5346
|
+
super.destroy();
|
|
5273
5347
|
this.stateSubject.complete();
|
|
5274
5348
|
}
|
|
5275
5349
|
get writingMode() {
|
|
@@ -5289,39 +5363,21 @@
|
|
|
5289
5363
|
onLoadDocument() {
|
|
5290
5364
|
return rxjs.EMPTY;
|
|
5291
5365
|
}
|
|
5292
|
-
|
|
5293
|
-
return void 0;
|
|
5294
|
-
}
|
|
5295
|
-
}
|
|
5296
|
-
const defaultGetResource = (item) => new URL(item.href);
|
|
5297
|
-
class ResourceHandler {
|
|
5298
|
-
constructor(item, settings) {
|
|
5299
|
-
this.item = item;
|
|
5300
|
-
this.settings = settings;
|
|
5301
|
-
}
|
|
5302
|
-
async getResource() {
|
|
5303
|
-
var _a, _b;
|
|
5304
|
-
const resource = await rxjs.lastValueFrom(
|
|
5305
|
-
((_b = (_a = this.settings.values).getResource) == null ? void 0 : _b.call(_a, this.item)) ?? rxjs.of(void 0)
|
|
5306
|
-
);
|
|
5307
|
-
return resource ?? defaultGetResource(this.item);
|
|
5308
|
-
}
|
|
5309
|
-
async fetchResource() {
|
|
5310
|
-
const resource = await this.getResource();
|
|
5311
|
-
if (resource instanceof Response) return resource;
|
|
5312
|
-
if (resource instanceof URL) return fetch(resource);
|
|
5313
|
-
return resource;
|
|
5366
|
+
onLayout() {
|
|
5367
|
+
return rxjs.of(void 0);
|
|
5314
5368
|
}
|
|
5315
5369
|
}
|
|
5316
|
-
class SpineItem {
|
|
5370
|
+
class SpineItem extends DestroyableClass {
|
|
5317
5371
|
constructor(item, parentElement, context, settings, hookManager, index) {
|
|
5318
5372
|
var _a, _b;
|
|
5373
|
+
super();
|
|
5319
5374
|
this.item = item;
|
|
5320
5375
|
this.parentElement = parentElement;
|
|
5321
5376
|
this.context = context;
|
|
5322
5377
|
this.settings = settings;
|
|
5323
5378
|
this.hookManager = hookManager;
|
|
5324
5379
|
this.index = index;
|
|
5380
|
+
this.layoutTriggerSubject = new rxjs.Subject();
|
|
5325
5381
|
this.adjustPositionOfElement = ({
|
|
5326
5382
|
right,
|
|
5327
5383
|
left,
|
|
@@ -5353,31 +5409,10 @@
|
|
|
5353
5409
|
return (_e = (_d = frameElement.contentDocument) == null ? void 0 : _d.querySelector(selector)) == null ? void 0 : _e.getBoundingClientRect();
|
|
5354
5410
|
}
|
|
5355
5411
|
};
|
|
5356
|
-
this.layout = ({
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
}) => {
|
|
5361
|
-
this.hookManager.execute(`item.onBeforeLayout`, void 0, {
|
|
5362
|
-
blankPagePosition,
|
|
5363
|
-
item: this.item,
|
|
5364
|
-
minimumWidth
|
|
5365
|
-
});
|
|
5366
|
-
const { height, width } = this.renderer.layout({
|
|
5367
|
-
blankPagePosition,
|
|
5368
|
-
minPageSpread: minimumWidth / this.context.getPageSize().width,
|
|
5369
|
-
spreadPosition
|
|
5370
|
-
}) ?? { width: 0, height: 0 };
|
|
5371
|
-
const minHeight = Math.max(height, this.context.getPageSize().height);
|
|
5372
|
-
const minWidth = Math.max(width, minimumWidth);
|
|
5373
|
-
this.containerElement.style.width = `${minWidth}px`;
|
|
5374
|
-
this.containerElement.style.height = `${minHeight}px`;
|
|
5375
|
-
this.hookManager.execute(`item.onAfterLayout`, void 0, {
|
|
5376
|
-
blankPagePosition,
|
|
5377
|
-
item: this.item,
|
|
5378
|
-
minimumWidth
|
|
5379
|
-
});
|
|
5380
|
-
return { width: minWidth, height: minHeight };
|
|
5412
|
+
this.layout = (params) => {
|
|
5413
|
+
const nextResult = deferNextResult(this.layout$.pipe(operators.first()));
|
|
5414
|
+
this.layoutTriggerSubject.next(params);
|
|
5415
|
+
return nextResult();
|
|
5381
5416
|
};
|
|
5382
5417
|
this.load = () => this.renderer.load();
|
|
5383
5418
|
this.unload = () => {
|
|
@@ -5395,16 +5430,14 @@
|
|
|
5395
5430
|
return normalizedValues;
|
|
5396
5431
|
};
|
|
5397
5432
|
this.destroy = () => {
|
|
5398
|
-
|
|
5433
|
+
super.destroy();
|
|
5399
5434
|
this.containerElement.remove();
|
|
5400
|
-
this.destroySubject$.complete();
|
|
5401
5435
|
this.renderer.destroy();
|
|
5402
5436
|
};
|
|
5403
5437
|
this.isUsingVerticalWriting = () => {
|
|
5404
5438
|
var _a2;
|
|
5405
5439
|
return !!((_a2 = this.renderer.writingMode) == null ? void 0 : _a2.startsWith(`vertical`));
|
|
5406
5440
|
};
|
|
5407
|
-
this.destroySubject$ = new rxjs.Subject();
|
|
5408
5441
|
this.containerElement = createContainerElement(
|
|
5409
5442
|
parentElement,
|
|
5410
5443
|
item,
|
|
@@ -5422,17 +5455,62 @@
|
|
|
5422
5455
|
resourcesHandler: this.resourcesHandler
|
|
5423
5456
|
};
|
|
5424
5457
|
this.renderer = rendererFactory ? rendererFactory(rendererParams) : new DefaultRenderer(rendererParams);
|
|
5425
|
-
const
|
|
5426
|
-
|
|
5427
|
-
|
|
5458
|
+
const layoutProcess$ = this.layoutTriggerSubject.pipe(
|
|
5459
|
+
operators.switchMap(({ blankPagePosition, minimumWidth, spreadPosition }) => {
|
|
5460
|
+
this.hookManager.execute(`item.onBeforeLayout`, void 0, {
|
|
5461
|
+
blankPagePosition,
|
|
5462
|
+
item: this.item,
|
|
5463
|
+
minimumWidth
|
|
5464
|
+
});
|
|
5465
|
+
const layout$ = rxjs.defer(
|
|
5466
|
+
() => this.renderer.onLayout({
|
|
5467
|
+
blankPagePosition,
|
|
5468
|
+
minPageSpread: minimumWidth / this.context.getPageSize().width,
|
|
5469
|
+
minimumWidth,
|
|
5470
|
+
spreadPosition
|
|
5471
|
+
})
|
|
5472
|
+
);
|
|
5473
|
+
return rxjs.merge(
|
|
5474
|
+
rxjs.of({ type: "start" }),
|
|
5475
|
+
layout$.pipe(
|
|
5476
|
+
operators.map((dims) => {
|
|
5477
|
+
const { height, width } = dims ?? { height: 0, width: 0 };
|
|
5478
|
+
const minHeight = Math.max(
|
|
5479
|
+
height,
|
|
5480
|
+
this.context.getPageSize().height
|
|
5481
|
+
);
|
|
5482
|
+
const minWidth = Math.max(width, minimumWidth);
|
|
5483
|
+
this.containerElement.style.width = `${minWidth}px`;
|
|
5484
|
+
this.containerElement.style.height = `${minHeight}px`;
|
|
5485
|
+
this.hookManager.execute(`item.onAfterLayout`, void 0, {
|
|
5486
|
+
blankPagePosition,
|
|
5487
|
+
item: this.item,
|
|
5488
|
+
minimumWidth
|
|
5489
|
+
});
|
|
5490
|
+
return {
|
|
5491
|
+
type: "end",
|
|
5492
|
+
data: { width: minWidth, height: minHeight }
|
|
5493
|
+
};
|
|
5494
|
+
})
|
|
5495
|
+
)
|
|
5496
|
+
);
|
|
5497
|
+
}),
|
|
5498
|
+
operators.share()
|
|
5499
|
+
);
|
|
5500
|
+
this.layout$ = layoutProcess$.pipe(
|
|
5501
|
+
operators.filter((event) => event.type === `end`),
|
|
5502
|
+
operators.map((event) => event.data),
|
|
5503
|
+
operators.share()
|
|
5428
5504
|
);
|
|
5429
|
-
this.
|
|
5430
|
-
operators.withLatestFrom(this.
|
|
5431
|
-
operators.map(([
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
})
|
|
5505
|
+
this.isReady$ = layoutProcess$.pipe(
|
|
5506
|
+
operators.withLatestFrom(this.renderer.isLoaded$),
|
|
5507
|
+
operators.map(([event, loaded]) => !!(event.type === `end` && loaded)),
|
|
5508
|
+
operators.startWith(false),
|
|
5509
|
+
operators.distinctUntilChanged(),
|
|
5510
|
+
operators.shareReplay({ refCount: true })
|
|
5435
5511
|
);
|
|
5512
|
+
this.needsLayout$ = rxjs.merge(this.unloaded$, this.loaded$);
|
|
5513
|
+
rxjs.merge(this.layout$, this.isReady$).pipe(operators.takeUntil(this.destroy$)).subscribe();
|
|
5436
5514
|
}
|
|
5437
5515
|
get element() {
|
|
5438
5516
|
return this.containerElement;
|
|
@@ -5448,15 +5526,6 @@
|
|
|
5448
5526
|
get readingDirection() {
|
|
5449
5527
|
return this.renderer.readingDirection;
|
|
5450
5528
|
}
|
|
5451
|
-
get isReady() {
|
|
5452
|
-
return this.renderer.state$.getValue() === "ready";
|
|
5453
|
-
}
|
|
5454
|
-
get ready$() {
|
|
5455
|
-
return this.renderer.state$.pipe(
|
|
5456
|
-
operators.distinctUntilChanged(),
|
|
5457
|
-
operators.filter((state) => state === "ready")
|
|
5458
|
-
);
|
|
5459
|
-
}
|
|
5460
5529
|
get loaded$() {
|
|
5461
5530
|
return this.renderer.state$.pipe(
|
|
5462
5531
|
operators.distinctUntilChanged(),
|
|
@@ -5475,22 +5544,6 @@
|
|
|
5475
5544
|
)
|
|
5476
5545
|
);
|
|
5477
5546
|
}
|
|
5478
|
-
get isReady$() {
|
|
5479
|
-
return this.renderer.state$.pipe(operators.map((state) => state === "ready"));
|
|
5480
|
-
}
|
|
5481
|
-
/**
|
|
5482
|
-
* Helper that will inject CSS into the document frame.
|
|
5483
|
-
*
|
|
5484
|
-
* @important
|
|
5485
|
-
* The document needs to be detected as a frame.
|
|
5486
|
-
*/
|
|
5487
|
-
upsertCSS(id, style, prepend) {
|
|
5488
|
-
this.renderer.layers.forEach((layer) => {
|
|
5489
|
-
if (layer.element instanceof HTMLIFrameElement) {
|
|
5490
|
-
upsertCSS(layer.element, id, style, prepend);
|
|
5491
|
-
}
|
|
5492
|
-
});
|
|
5493
|
-
}
|
|
5494
5547
|
}
|
|
5495
5548
|
const createContainerElement = (containerElement, item, hookManager) => {
|
|
5496
5549
|
const element = containerElement.ownerDocument.createElement(`div`);
|
|
@@ -6071,6 +6124,103 @@
|
|
|
6071
6124
|
right: position.x + pageSize.width
|
|
6072
6125
|
};
|
|
6073
6126
|
};
|
|
6127
|
+
const layoutItem = ({
|
|
6128
|
+
horizontalOffset,
|
|
6129
|
+
verticalOffset,
|
|
6130
|
+
context,
|
|
6131
|
+
spineItemsManager,
|
|
6132
|
+
isGloballyPrePaginated,
|
|
6133
|
+
settings,
|
|
6134
|
+
index,
|
|
6135
|
+
item,
|
|
6136
|
+
newItemLayoutInformation
|
|
6137
|
+
}) => {
|
|
6138
|
+
let minimumWidth = context.getPageSize().width;
|
|
6139
|
+
let blankPagePosition = `none`;
|
|
6140
|
+
const itemStartOnNewScreen = horizontalOffset % context.state.visibleAreaRect.width === 0;
|
|
6141
|
+
const isLastItem = index === spineItemsManager.items.length - 1;
|
|
6142
|
+
if (context.state.isUsingSpreadMode) {
|
|
6143
|
+
if (!isGloballyPrePaginated && item.item.renditionLayout === `reflowable` && !isLastItem) {
|
|
6144
|
+
minimumWidth = context.getPageSize().width * 2;
|
|
6145
|
+
}
|
|
6146
|
+
if (!isGloballyPrePaginated && item.item.renditionLayout === `reflowable` && isLastItem && itemStartOnNewScreen) {
|
|
6147
|
+
minimumWidth = context.getPageSize().width * 2;
|
|
6148
|
+
}
|
|
6149
|
+
const lastItemStartOnNewScreenInAPrepaginatedBook = itemStartOnNewScreen && isLastItem && isGloballyPrePaginated;
|
|
6150
|
+
if (item.item.pageSpreadRight && itemStartOnNewScreen && !context.isRTL()) {
|
|
6151
|
+
blankPagePosition = `before`;
|
|
6152
|
+
minimumWidth = context.getPageSize().width * 2;
|
|
6153
|
+
} else if (item.item.pageSpreadLeft && itemStartOnNewScreen && context.isRTL()) {
|
|
6154
|
+
blankPagePosition = `before`;
|
|
6155
|
+
minimumWidth = context.getPageSize().width * 2;
|
|
6156
|
+
} else if (lastItemStartOnNewScreenInAPrepaginatedBook) {
|
|
6157
|
+
if (context.isRTL()) {
|
|
6158
|
+
blankPagePosition = `before`;
|
|
6159
|
+
} else {
|
|
6160
|
+
blankPagePosition = `after`;
|
|
6161
|
+
}
|
|
6162
|
+
minimumWidth = context.getPageSize().width * 2;
|
|
6163
|
+
}
|
|
6164
|
+
}
|
|
6165
|
+
const itemLayout$ = item.layout({
|
|
6166
|
+
minimumWidth,
|
|
6167
|
+
blankPagePosition,
|
|
6168
|
+
spreadPosition: context.state.isUsingSpreadMode ? itemStartOnNewScreen ? context.isRTL() ? `right` : `left` : context.isRTL() ? `left` : `right` : `none`
|
|
6169
|
+
});
|
|
6170
|
+
return itemLayout$.pipe(
|
|
6171
|
+
rxjs.map(({ width, height }) => {
|
|
6172
|
+
if (settings.values.computedPageTurnDirection === `vertical`) {
|
|
6173
|
+
const currentValidEdgeYForVerticalPositioning = itemStartOnNewScreen ? verticalOffset : verticalOffset - context.state.visibleAreaRect.height;
|
|
6174
|
+
const currentValidEdgeXForVerticalPositioning = itemStartOnNewScreen ? 0 : horizontalOffset;
|
|
6175
|
+
if (context.isRTL()) {
|
|
6176
|
+
item.adjustPositionOfElement({
|
|
6177
|
+
top: currentValidEdgeYForVerticalPositioning,
|
|
6178
|
+
left: currentValidEdgeXForVerticalPositioning
|
|
6179
|
+
});
|
|
6180
|
+
} else {
|
|
6181
|
+
item.adjustPositionOfElement({
|
|
6182
|
+
top: currentValidEdgeYForVerticalPositioning,
|
|
6183
|
+
left: currentValidEdgeXForVerticalPositioning
|
|
6184
|
+
});
|
|
6185
|
+
}
|
|
6186
|
+
const newEdgeX = width + currentValidEdgeXForVerticalPositioning;
|
|
6187
|
+
const newEdgeY = height + currentValidEdgeYForVerticalPositioning;
|
|
6188
|
+
newItemLayoutInformation.push({
|
|
6189
|
+
left: currentValidEdgeXForVerticalPositioning,
|
|
6190
|
+
right: newEdgeX,
|
|
6191
|
+
top: currentValidEdgeYForVerticalPositioning,
|
|
6192
|
+
bottom: newEdgeY,
|
|
6193
|
+
height,
|
|
6194
|
+
width,
|
|
6195
|
+
x: currentValidEdgeXForVerticalPositioning,
|
|
6196
|
+
y: currentValidEdgeYForVerticalPositioning
|
|
6197
|
+
});
|
|
6198
|
+
return {
|
|
6199
|
+
horizontalOffset: newEdgeX,
|
|
6200
|
+
verticalOffset: newEdgeY
|
|
6201
|
+
};
|
|
6202
|
+
}
|
|
6203
|
+
item.adjustPositionOfElement(
|
|
6204
|
+
context.isRTL() ? { right: horizontalOffset, top: 0 } : { left: horizontalOffset, top: 0 }
|
|
6205
|
+
);
|
|
6206
|
+
const left = context.isRTL() ? context.state.visibleAreaRect.width - horizontalOffset - width : horizontalOffset;
|
|
6207
|
+
newItemLayoutInformation.push({
|
|
6208
|
+
right: context.isRTL() ? context.state.visibleAreaRect.width - horizontalOffset : horizontalOffset + width,
|
|
6209
|
+
left,
|
|
6210
|
+
x: left,
|
|
6211
|
+
top: verticalOffset,
|
|
6212
|
+
bottom: height,
|
|
6213
|
+
height,
|
|
6214
|
+
width,
|
|
6215
|
+
y: verticalOffset
|
|
6216
|
+
});
|
|
6217
|
+
return {
|
|
6218
|
+
horizontalOffset: horizontalOffset + width,
|
|
6219
|
+
verticalOffset: 0
|
|
6220
|
+
};
|
|
6221
|
+
})
|
|
6222
|
+
);
|
|
6223
|
+
};
|
|
6074
6224
|
const NAMESPACE = `SpineLayout`;
|
|
6075
6225
|
class SpineLayout extends DestroyableClass {
|
|
6076
6226
|
constructor(spineItemsManager, context, settings) {
|
|
@@ -6082,8 +6232,8 @@
|
|
|
6082
6232
|
this.layoutSubject = new rxjs.Subject();
|
|
6083
6233
|
spineItemsManager.items$.pipe(
|
|
6084
6234
|
rxjs.switchMap((items) => {
|
|
6085
|
-
const
|
|
6086
|
-
(spineItem) => spineItem.
|
|
6235
|
+
const needsLayouts$ = items.map(
|
|
6236
|
+
(spineItem) => spineItem.needsLayout$.pipe(
|
|
6087
6237
|
rxjs.tap(() => {
|
|
6088
6238
|
this.layout();
|
|
6089
6239
|
})
|
|
@@ -6104,12 +6254,60 @@
|
|
|
6104
6254
|
})
|
|
6105
6255
|
)
|
|
6106
6256
|
);
|
|
6107
|
-
return rxjs.merge(...
|
|
6257
|
+
return rxjs.merge(...needsLayouts$, ...writingModeUpdate$);
|
|
6108
6258
|
})
|
|
6109
6259
|
).pipe(rxjs.takeUntil(this.destroy$)).subscribe();
|
|
6260
|
+
const layoutInProgress = new rxjs.BehaviorSubject(false);
|
|
6110
6261
|
this.layout$ = this.layoutSubject.pipe(
|
|
6111
|
-
rxjs.
|
|
6112
|
-
|
|
6262
|
+
rxjs.debounceTime(50),
|
|
6263
|
+
// queue layout until previous layout is done
|
|
6264
|
+
rxjs.exhaustMap(
|
|
6265
|
+
() => layoutInProgress.pipe(
|
|
6266
|
+
rxjs.filter((value) => !value),
|
|
6267
|
+
rxjs.first()
|
|
6268
|
+
)
|
|
6269
|
+
),
|
|
6270
|
+
rxjs.exhaustMap(() => {
|
|
6271
|
+
layoutInProgress.next(true);
|
|
6272
|
+
const manifest = this.context.manifest;
|
|
6273
|
+
const newItemLayoutInformation = [];
|
|
6274
|
+
const isGloballyPrePaginated = (manifest == null ? void 0 : manifest.renditionLayout) === `pre-paginated`;
|
|
6275
|
+
return rxjs.from(this.spineItemsManager.items).pipe(
|
|
6276
|
+
rxjs.reduce(
|
|
6277
|
+
(acc$, item, index) => acc$.pipe(
|
|
6278
|
+
rxjs.concatMap(
|
|
6279
|
+
({ horizontalOffset, verticalOffset }) => layoutItem({
|
|
6280
|
+
context: this.context,
|
|
6281
|
+
horizontalOffset,
|
|
6282
|
+
index,
|
|
6283
|
+
isGloballyPrePaginated,
|
|
6284
|
+
item,
|
|
6285
|
+
settings: this.settings,
|
|
6286
|
+
spineItemsManager: this.spineItemsManager,
|
|
6287
|
+
verticalOffset,
|
|
6288
|
+
newItemLayoutInformation
|
|
6289
|
+
})
|
|
6290
|
+
)
|
|
6291
|
+
),
|
|
6292
|
+
rxjs.of({ horizontalOffset: 0, verticalOffset: 0 })
|
|
6293
|
+
),
|
|
6294
|
+
rxjs.concatMap((layout$) => layout$),
|
|
6295
|
+
rxjs.map(() => {
|
|
6296
|
+
const hasChanged = this.itemLayoutInformation.length !== newItemLayoutInformation.length || this.itemLayoutInformation.some(
|
|
6297
|
+
(old, index) => !shared.isShallowEqual(old, newItemLayoutInformation[index])
|
|
6298
|
+
);
|
|
6299
|
+
this.itemLayoutInformation = newItemLayoutInformation;
|
|
6300
|
+
Report.log(NAMESPACE, `layout`, {
|
|
6301
|
+
hasChanged,
|
|
6302
|
+
itemLayoutInformation: this.itemLayoutInformation
|
|
6303
|
+
});
|
|
6304
|
+
return { hasChanged };
|
|
6305
|
+
}),
|
|
6306
|
+
rxjs.finalize(() => {
|
|
6307
|
+
layoutInProgress.next(false);
|
|
6308
|
+
})
|
|
6309
|
+
);
|
|
6310
|
+
}),
|
|
6113
6311
|
rxjs.map(({ hasChanged }) => {
|
|
6114
6312
|
const items = spineItemsManager.items;
|
|
6115
6313
|
const spineItemsPagesAbsolutePositions = items.map((item) => {
|
|
@@ -6159,116 +6357,13 @@
|
|
|
6159
6357
|
pages
|
|
6160
6358
|
};
|
|
6161
6359
|
}),
|
|
6162
|
-
rxjs.
|
|
6360
|
+
rxjs.share()
|
|
6163
6361
|
);
|
|
6362
|
+
this.info$ = this.layout$.pipe(rxjs.shareReplay({ refCount: true }));
|
|
6363
|
+
rxjs.merge(this.layout$, this.info$).pipe(rxjs.takeUntil(this.destroy$)).subscribe();
|
|
6164
6364
|
}
|
|
6165
|
-
/**
|
|
6166
|
-
* @todo
|
|
6167
|
-
* move this logic to the spine
|
|
6168
|
-
*
|
|
6169
|
-
* @todo
|
|
6170
|
-
* make sure to check how many times it is being called and try to reduce number of layouts
|
|
6171
|
-
* it is called eery time an item is being unload (which can adds up quickly for big books)
|
|
6172
|
-
*/
|
|
6173
6365
|
layout() {
|
|
6174
|
-
|
|
6175
|
-
const newItemLayoutInformation = [];
|
|
6176
|
-
const isGloballyPrePaginated = (manifest == null ? void 0 : manifest.renditionLayout) === `pre-paginated`;
|
|
6177
|
-
this.spineItemsManager.items.reduce(
|
|
6178
|
-
({ horizontalOffset, verticalOffset }, item, index) => {
|
|
6179
|
-
let minimumWidth = this.context.getPageSize().width;
|
|
6180
|
-
let blankPagePosition = `none`;
|
|
6181
|
-
const itemStartOnNewScreen = horizontalOffset % this.context.state.visibleAreaRect.width === 0;
|
|
6182
|
-
const isLastItem = index === this.spineItemsManager.items.length - 1;
|
|
6183
|
-
if (this.context.state.isUsingSpreadMode) {
|
|
6184
|
-
if (!isGloballyPrePaginated && item.item.renditionLayout === `reflowable` && !isLastItem) {
|
|
6185
|
-
minimumWidth = this.context.getPageSize().width * 2;
|
|
6186
|
-
}
|
|
6187
|
-
if (!isGloballyPrePaginated && item.item.renditionLayout === `reflowable` && isLastItem && itemStartOnNewScreen) {
|
|
6188
|
-
minimumWidth = this.context.getPageSize().width * 2;
|
|
6189
|
-
}
|
|
6190
|
-
const lastItemStartOnNewScreenInAPrepaginatedBook = itemStartOnNewScreen && isLastItem && isGloballyPrePaginated;
|
|
6191
|
-
if (item.item.pageSpreadRight && itemStartOnNewScreen && !this.context.isRTL()) {
|
|
6192
|
-
blankPagePosition = `before`;
|
|
6193
|
-
minimumWidth = this.context.getPageSize().width * 2;
|
|
6194
|
-
} else if (item.item.pageSpreadLeft && itemStartOnNewScreen && this.context.isRTL()) {
|
|
6195
|
-
blankPagePosition = `before`;
|
|
6196
|
-
minimumWidth = this.context.getPageSize().width * 2;
|
|
6197
|
-
} else if (lastItemStartOnNewScreenInAPrepaginatedBook) {
|
|
6198
|
-
if (this.context.isRTL()) {
|
|
6199
|
-
blankPagePosition = `before`;
|
|
6200
|
-
} else {
|
|
6201
|
-
blankPagePosition = `after`;
|
|
6202
|
-
}
|
|
6203
|
-
minimumWidth = this.context.getPageSize().width * 2;
|
|
6204
|
-
}
|
|
6205
|
-
}
|
|
6206
|
-
const { width, height } = item.layout({
|
|
6207
|
-
minimumWidth,
|
|
6208
|
-
blankPagePosition,
|
|
6209
|
-
spreadPosition: this.context.state.isUsingSpreadMode ? itemStartOnNewScreen ? this.context.isRTL() ? `right` : `left` : this.context.isRTL() ? `left` : `right` : `none`
|
|
6210
|
-
});
|
|
6211
|
-
if (this.settings.values.computedPageTurnDirection === `vertical`) {
|
|
6212
|
-
const currentValidEdgeYForVerticalPositioning = itemStartOnNewScreen ? verticalOffset : verticalOffset - this.context.state.visibleAreaRect.height;
|
|
6213
|
-
const currentValidEdgeXForVerticalPositioning = itemStartOnNewScreen ? 0 : horizontalOffset;
|
|
6214
|
-
if (this.context.isRTL()) {
|
|
6215
|
-
item.adjustPositionOfElement({
|
|
6216
|
-
top: currentValidEdgeYForVerticalPositioning,
|
|
6217
|
-
left: currentValidEdgeXForVerticalPositioning
|
|
6218
|
-
});
|
|
6219
|
-
} else {
|
|
6220
|
-
item.adjustPositionOfElement({
|
|
6221
|
-
top: currentValidEdgeYForVerticalPositioning,
|
|
6222
|
-
left: currentValidEdgeXForVerticalPositioning
|
|
6223
|
-
});
|
|
6224
|
-
}
|
|
6225
|
-
const newEdgeX = width + currentValidEdgeXForVerticalPositioning;
|
|
6226
|
-
const newEdgeY = height + currentValidEdgeYForVerticalPositioning;
|
|
6227
|
-
newItemLayoutInformation.push({
|
|
6228
|
-
left: currentValidEdgeXForVerticalPositioning,
|
|
6229
|
-
right: newEdgeX,
|
|
6230
|
-
top: currentValidEdgeYForVerticalPositioning,
|
|
6231
|
-
bottom: newEdgeY,
|
|
6232
|
-
height,
|
|
6233
|
-
width,
|
|
6234
|
-
x: currentValidEdgeXForVerticalPositioning,
|
|
6235
|
-
y: currentValidEdgeYForVerticalPositioning
|
|
6236
|
-
});
|
|
6237
|
-
return {
|
|
6238
|
-
horizontalOffset: newEdgeX,
|
|
6239
|
-
verticalOffset: newEdgeY
|
|
6240
|
-
};
|
|
6241
|
-
}
|
|
6242
|
-
item.adjustPositionOfElement(
|
|
6243
|
-
this.context.isRTL() ? { right: horizontalOffset, top: 0 } : { left: horizontalOffset, top: 0 }
|
|
6244
|
-
);
|
|
6245
|
-
const left = this.context.isRTL() ? this.context.state.visibleAreaRect.width - horizontalOffset - width : horizontalOffset;
|
|
6246
|
-
newItemLayoutInformation.push({
|
|
6247
|
-
right: this.context.isRTL() ? this.context.state.visibleAreaRect.width - horizontalOffset : horizontalOffset + width,
|
|
6248
|
-
left,
|
|
6249
|
-
x: left,
|
|
6250
|
-
top: verticalOffset,
|
|
6251
|
-
bottom: height,
|
|
6252
|
-
height,
|
|
6253
|
-
width,
|
|
6254
|
-
y: verticalOffset
|
|
6255
|
-
});
|
|
6256
|
-
return {
|
|
6257
|
-
horizontalOffset: horizontalOffset + width,
|
|
6258
|
-
verticalOffset: 0
|
|
6259
|
-
};
|
|
6260
|
-
},
|
|
6261
|
-
{ horizontalOffset: 0, verticalOffset: 0 }
|
|
6262
|
-
);
|
|
6263
|
-
const hasLayoutChanges = this.itemLayoutInformation.length !== newItemLayoutInformation.length || this.itemLayoutInformation.some(
|
|
6264
|
-
(old, index) => !shared.isShallowEqual(old, newItemLayoutInformation[index])
|
|
6265
|
-
);
|
|
6266
|
-
this.itemLayoutInformation = newItemLayoutInformation;
|
|
6267
|
-
Report.log(NAMESPACE, `layout`, {
|
|
6268
|
-
hasLayoutChanges,
|
|
6269
|
-
itemLayoutInformation: this.itemLayoutInformation
|
|
6270
|
-
});
|
|
6271
|
-
this.layoutSubject.next(hasLayoutChanges);
|
|
6366
|
+
this.layoutSubject.next(void 0);
|
|
6272
6367
|
}
|
|
6273
6368
|
/**
|
|
6274
6369
|
* It's important to not use x,y since we need the absolute position of each element. Otherwise x,y would be relative to
|
|
@@ -6851,7 +6946,7 @@
|
|
|
6851
6946
|
this.layers = [];
|
|
6852
6947
|
return rxjs.EMPTY;
|
|
6853
6948
|
}
|
|
6854
|
-
|
|
6949
|
+
onLayout({
|
|
6855
6950
|
spreadPosition
|
|
6856
6951
|
}) {
|
|
6857
6952
|
var _a, _b;
|
|
@@ -6871,10 +6966,10 @@
|
|
|
6871
6966
|
element.style.width = `${width}px`;
|
|
6872
6967
|
element.style.objectPosition = spreadPosition === "left" ? `right` : spreadPosition === `right` ? `left` : `center`;
|
|
6873
6968
|
}
|
|
6874
|
-
return {
|
|
6969
|
+
return rxjs.of({
|
|
6875
6970
|
width,
|
|
6876
6971
|
height
|
|
6877
|
-
};
|
|
6972
|
+
});
|
|
6878
6973
|
}
|
|
6879
6974
|
}
|
|
6880
6975
|
const mediaEnhancer = (next) => (options) => {
|
|
@@ -6970,36 +7065,41 @@
|
|
|
6970
7065
|
const progressionEnhancer = (next) => (options) => {
|
|
6971
7066
|
const reader = next(options);
|
|
6972
7067
|
const getPercentageEstimate = (context, currentSpineIndex, numberOfPages, pageIndex, currentPosition, currentItem) => {
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
|
|
6986
|
-
|
|
6987
|
-
|
|
6988
|
-
|
|
6989
|
-
|
|
6990
|
-
|
|
6991
|
-
|
|
6992
|
-
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
7068
|
+
return currentItem.isReady$.pipe(
|
|
7069
|
+
rxjs.first(),
|
|
7070
|
+
rxjs.map((itemIsReady) => {
|
|
7071
|
+
var _a, _b, _c, _d, _e, _f;
|
|
7072
|
+
const isGloballyPrePaginated = ((_a = context.manifest) == null ? void 0 : _a.renditionLayout) === `pre-paginated`;
|
|
7073
|
+
const readingOrderLength = ((_b = context.manifest) == null ? void 0 : _b.spineItems.length) || 0;
|
|
7074
|
+
const estimateBeforeThisItem = ((_c = context.manifest) == null ? void 0 : _c.spineItems.slice(0, currentSpineIndex).reduce((acc, item) => acc + (item.progressionWeight ?? 0), 0)) || 0;
|
|
7075
|
+
const currentItemWeight = ((_e = (_d = context.manifest) == null ? void 0 : _d.spineItems[currentSpineIndex]) == null ? void 0 : _e.progressionWeight) || 0;
|
|
7076
|
+
let progressWithinThisItem = (pageIndex + 1) * (currentItemWeight / numberOfPages);
|
|
7077
|
+
if (!isGloballyPrePaginated && currentItem.item.renditionLayout === `reflowable` && !itemIsReady) {
|
|
7078
|
+
progressWithinThisItem = 0;
|
|
7079
|
+
}
|
|
7080
|
+
let totalProgress = estimateBeforeThisItem + progressWithinThisItem;
|
|
7081
|
+
if (((_f = context.manifest) == null ? void 0 : _f.renditionFlow) === `scrolled-continuous`) {
|
|
7082
|
+
if (itemIsReady) {
|
|
7083
|
+
progressWithinThisItem = getScrollPercentageWithinItem(
|
|
7084
|
+
context,
|
|
7085
|
+
currentPosition,
|
|
7086
|
+
currentItem
|
|
7087
|
+
);
|
|
7088
|
+
} else {
|
|
7089
|
+
progressWithinThisItem = 0;
|
|
7090
|
+
}
|
|
7091
|
+
totalProgress = getTotalProgressFromPercentages(
|
|
7092
|
+
estimateBeforeThisItem,
|
|
7093
|
+
currentItemWeight,
|
|
7094
|
+
progressWithinThisItem
|
|
7095
|
+
);
|
|
7096
|
+
}
|
|
7097
|
+
if (currentSpineIndex === readingOrderLength - 1 && pageIndex === numberOfPages - 1 && totalProgress > 0.99) {
|
|
7098
|
+
return 1;
|
|
7099
|
+
}
|
|
7100
|
+
return totalProgress;
|
|
7101
|
+
})
|
|
7102
|
+
);
|
|
7003
7103
|
};
|
|
7004
7104
|
const getTotalProgressFromPercentages = (estimateBeforeThisItem, currentItemWeight, progressWithinThisItem) => {
|
|
7005
7105
|
return estimateBeforeThisItem + currentItemWeight * progressWithinThisItem;
|
|
@@ -7052,19 +7152,24 @@
|
|
|
7052
7152
|
if (!(frame instanceof HTMLIFrameElement)) return;
|
|
7053
7153
|
const item = reader.spineItemsManager.get(itemId);
|
|
7054
7154
|
if (!item) return;
|
|
7055
|
-
item.
|
|
7056
|
-
|
|
7057
|
-
|
|
7058
|
-
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
7063
|
-
|
|
7064
|
-
|
|
7065
|
-
|
|
7066
|
-
|
|
7067
|
-
|
|
7155
|
+
item.renderer.layers.forEach((layer) => {
|
|
7156
|
+
if (layer.element instanceof HTMLIFrameElement) {
|
|
7157
|
+
upsertCSS(
|
|
7158
|
+
layer.element,
|
|
7159
|
+
`prose-reader-accessibility`,
|
|
7160
|
+
`
|
|
7161
|
+
:focus-visible {
|
|
7162
|
+
${/*
|
|
7163
|
+
Some epubs remove the outline, this is not good practice since it reduce accessibility.
|
|
7164
|
+
We will try to restore it by force.
|
|
7165
|
+
*/
|
|
7166
|
+
``}
|
|
7167
|
+
outline: -webkit-focus-ring-color auto 1px;
|
|
7168
|
+
}
|
|
7169
|
+
`
|
|
7170
|
+
);
|
|
7171
|
+
}
|
|
7172
|
+
});
|
|
7068
7173
|
const links = (_b = frame.contentDocument) == null ? void 0 : _b.body.querySelectorAll(`a`);
|
|
7069
7174
|
links == null ? void 0 : links.forEach((link) => {
|
|
7070
7175
|
observer.observe(link);
|
|
@@ -8028,7 +8133,7 @@
|
|
|
8028
8133
|
this.layers = [];
|
|
8029
8134
|
return rxjs.EMPTY;
|
|
8030
8135
|
}
|
|
8031
|
-
|
|
8136
|
+
onLayout({
|
|
8032
8137
|
minPageSpread,
|
|
8033
8138
|
blankPagePosition,
|
|
8034
8139
|
spreadPosition
|
|
@@ -8036,10 +8141,10 @@
|
|
|
8036
8141
|
var _a;
|
|
8037
8142
|
const { width: pageWidth, height: pageHeight } = this.context.getPageSize();
|
|
8038
8143
|
const frameElement = this.getFrameElement();
|
|
8039
|
-
if (!frameElement) return { width: pageWidth, height: pageHeight };
|
|
8144
|
+
if (!frameElement) return rxjs.of({ width: pageWidth, height: pageHeight });
|
|
8040
8145
|
const isUsingVerticalWriting = !!((_a = this.writingMode) == null ? void 0 : _a.startsWith(`vertical`));
|
|
8041
8146
|
if (this.item.renditionLayout === `pre-paginated`) {
|
|
8042
|
-
|
|
8147
|
+
const dims = renderPrePaginated({
|
|
8043
8148
|
blankPagePosition,
|
|
8044
8149
|
enableTouch: this.settings.values.computedPageTurnMode !== `scrollable`,
|
|
8045
8150
|
frameElement,
|
|
@@ -8049,6 +8154,7 @@
|
|
|
8049
8154
|
pageWidth,
|
|
8050
8155
|
spreadPosition
|
|
8051
8156
|
});
|
|
8157
|
+
return rxjs.of(dims);
|
|
8052
8158
|
}
|
|
8053
8159
|
const { latestContentHeightWhenLoaded, ...rest } = renderReflowable({
|
|
8054
8160
|
pageHeight,
|
|
@@ -8064,7 +8170,7 @@
|
|
|
8064
8170
|
enableTouch: this.settings.values.computedPageTurnMode !== `scrollable`
|
|
8065
8171
|
});
|
|
8066
8172
|
this.latestContentHeightWhenLoaded = latestContentHeightWhenLoaded;
|
|
8067
|
-
return rest;
|
|
8173
|
+
return rxjs.of(rest);
|
|
8068
8174
|
}
|
|
8069
8175
|
getFrameElement() {
|
|
8070
8176
|
var _a;
|
|
@@ -8146,7 +8252,6 @@
|
|
|
8146
8252
|
selection,
|
|
8147
8253
|
spineItem
|
|
8148
8254
|
}) => {
|
|
8149
|
-
if (!spineItem.isReady) return void 0;
|
|
8150
8255
|
const { anchorNode, anchorOffset, focusNode, focusOffset } = selection;
|
|
8151
8256
|
if (!anchorNode || !focusNode) {
|
|
8152
8257
|
return void 0;
|