postext 1.40.0 → 1.41.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/__tests__/composed/crossChapterJumps.test.d.ts +2 -0
- package/dist/__tests__/composed/crossChapterJumps.test.d.ts.map +1 -0
- package/dist/__tests__/composed/crossChapterJumps.test.js +299 -0
- package/dist/__tests__/composed/crossChapterJumps.test.js.map +1 -0
- package/dist/__tests__/exports.test.js +3 -0
- package/dist/__tests__/exports.test.js.map +1 -1
- package/dist/bundle/book.d.ts +5 -0
- package/dist/bundle/book.d.ts.map +1 -1
- package/dist/bundle/book.js +53 -7
- package/dist/bundle/book.js.map +1 -1
- package/dist/bundle/layoutCache.d.ts +5 -0
- package/dist/bundle/layoutCache.d.ts.map +1 -1
- package/dist/bundle/layoutCache.js.map +1 -1
- package/dist/composed/carry.d.ts +53 -0
- package/dist/composed/carry.d.ts.map +1 -0
- package/dist/composed/carry.js +114 -0
- package/dist/composed/carry.js.map +1 -0
- package/dist/composed/carryTypes.d.ts +76 -0
- package/dist/composed/carryTypes.d.ts.map +1 -0
- package/dist/composed/carryTypes.js +2 -0
- package/dist/composed/carryTypes.js.map +1 -0
- package/dist/composed/continuation.d.ts +8 -0
- package/dist/composed/continuation.d.ts.map +1 -1
- package/dist/composed/continuation.js.map +1 -1
- package/dist/composed/sourceMap.d.ts +16 -0
- package/dist/composed/sourceMap.d.ts.map +1 -1
- package/dist/composed/sourceMap.js +36 -8
- package/dist/composed/sourceMap.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/pipeline/build.d.ts +12 -0
- package/dist/pipeline/build.d.ts.map +1 -1
- package/dist/pipeline/build.js +237 -15
- package/dist/pipeline/build.js.map +1 -1
- package/dist/pipeline/calloutLayout.d.ts +2 -17
- package/dist/pipeline/calloutLayout.d.ts.map +1 -1
- package/dist/pipeline/calloutLayout.js.map +1 -1
- package/dist/pipeline/composedLayout.d.ts +12 -0
- package/dist/pipeline/composedLayout.d.ts.map +1 -1
- package/dist/pipeline/composedLayout.js +76 -1
- package/dist/pipeline/composedLayout.js.map +1 -1
- package/dist/pipeline/contentWarnings.d.ts.map +1 -1
- package/dist/pipeline/contentWarnings.js +5 -3
- package/dist/pipeline/contentWarnings.js.map +1 -1
- package/dist/pipeline/continuation.d.ts +11 -0
- package/dist/pipeline/continuation.d.ts.map +1 -1
- package/dist/pipeline/continuation.js +36 -0
- package/dist/pipeline/continuation.js.map +1 -1
- package/dist/pipeline/cutTypes.d.ts +42 -0
- package/dist/pipeline/cutTypes.d.ts.map +1 -0
- package/dist/pipeline/cutTypes.js +6 -0
- package/dist/pipeline/cutTypes.js.map +1 -0
- package/dist/pipeline/frameLayout.d.ts +3 -21
- package/dist/pipeline/frameLayout.d.ts.map +1 -1
- package/dist/pipeline/frameLayout.js.map +1 -1
- package/dist/pipeline/index.d.ts +2 -1
- package/dist/pipeline/index.d.ts.map +1 -1
- package/dist/pipeline/index.js +2 -1
- package/dist/pipeline/index.js.map +1 -1
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/vdt.d.ts +36 -0
- package/dist/vdt.d.ts.map +1 -1
- package/dist/vdt.js.map +1 -1
- package/package.json +1 -1
package/dist/pipeline/build.js
CHANGED
|
@@ -44,7 +44,8 @@ import { layoutComposedSpread } from '../composed/spread';
|
|
|
44
44
|
import { assignJumpReceivers, assignReceivers, continuationTarget, MAX_CONTINUATION_PAGES } from '../composed/continuation';
|
|
45
45
|
import { frameElementId } from '../composed/ids';
|
|
46
46
|
import { nextFrameOf } from '../composed/geometry';
|
|
47
|
-
import { composedPageAt, frameStyleOf, layoutComposedPage, planComposedPages } from './composedLayout';
|
|
47
|
+
import { carriedPass, composedPageAt, frameStyleOf, layoutComposedPage, planComposedPages } from './composedLayout';
|
|
48
|
+
import { importJumps } from '../composed/carry';
|
|
48
49
|
import { configKeyOf, layoutComposedPageMemo } from '../composed/pageMemo';
|
|
49
50
|
import { anchorOutline, computeOutline, hasIndexDirective, hasTocDirective, headingNumberingOptions, headingTemplatesOf, outlineFromDoc, sameOutline } from './outline';
|
|
50
51
|
import { expandTocDirectives } from './toc';
|
|
@@ -485,7 +486,9 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
485
486
|
const anchorRefs = hasAnchorRefs(parsedBlocks, resourceIds);
|
|
486
487
|
const outline = content.outline
|
|
487
488
|
?? (hasTocDirective(parsedBlocks) || hasIndexDirective(parsedBlocks) || anchorRefs ? computeOutline(parsedBlocks, resolved, headingStart, continuation?.statementCounters) : undefined);
|
|
488
|
-
|
|
489
|
+
// A story carried in from another chapter (#943) may refer to anchors too.
|
|
490
|
+
const carriedRefs = continuation?.jumps?.some((j) => j.outline) === true;
|
|
491
|
+
const anchorRefContext = anchorRefs || carriedRefs
|
|
489
492
|
? { targets: anchorTargetsOf(outline), strings: resolved.crossRefs }
|
|
490
493
|
: undefined;
|
|
491
494
|
const indexExpanded = expandIndexDirectives(expandTocDirectives(parsedBlocks, outline, resolved), outline, resolved);
|
|
@@ -518,6 +521,15 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
518
521
|
// callout machinery places and splits.
|
|
519
522
|
const codeBoxes = wrapCodeBlocks(spanEmbeds.blocks, resolved);
|
|
520
523
|
const contentBlocks = codeBoxes.blocks;
|
|
524
|
+
// Stories of earlier chapters that jump into a page of this one (#943):
|
|
525
|
+
// appended past the chapter's blocks by the composed pages' layout, with
|
|
526
|
+
// the notes they cite numbered as their chapter numbered them.
|
|
527
|
+
const carried = continuation?.jumps && continuation.jumps.length > 0 ? importJumps(continuation.jumps, contentBlocks.length, bodyOffset) : undefined;
|
|
528
|
+
for (const note of carried?.footnotes ?? []) {
|
|
529
|
+
footnoteNumbering.numbers.set(note.id, note.number);
|
|
530
|
+
if (note.def)
|
|
531
|
+
footnoteDefs.set(note.id, note.def);
|
|
532
|
+
}
|
|
521
533
|
if (indexExpanded.warnings.length > 0)
|
|
522
534
|
indexWarnings.set(doc, indexExpanded.warnings);
|
|
523
535
|
const isNumbered = (b) => headingIsNumbered(b, resolved);
|
|
@@ -5997,6 +6009,93 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
5997
6009
|
}
|
|
5998
6010
|
/** Stories waiting for the later page fence they jump to, by its id. */
|
|
5999
6011
|
const jumps = new Map();
|
|
6012
|
+
/** The closing marker of the fence each composed page was set from. */
|
|
6013
|
+
const fenceEnd = new Map();
|
|
6014
|
+
/** The carried stories are laid through a pass that answers for them;
|
|
6015
|
+
* they wait for their fence with the others. */
|
|
6016
|
+
const composedPass = carried ? carriedPass(framePass, carried) : framePass;
|
|
6017
|
+
/** Stories of this chapter that jump into a page of a later one (#943). */
|
|
6018
|
+
const pendingJumps = [];
|
|
6019
|
+
/** The rest of the story `c` cut, as the chapter it goes to needs it
|
|
6020
|
+
* (#943): its box and children as this chapter has them ready to lay,
|
|
6021
|
+
* the cut, and the numbers the lookups by position would give. */
|
|
6022
|
+
const exportJump = (c, page) => {
|
|
6023
|
+
const startIdx = c.story.startIdx;
|
|
6024
|
+
const again = carried?.stories.get(startIdx);
|
|
6025
|
+
const all = composedPass.contentBlocks;
|
|
6026
|
+
const blocks = all.slice(startIdx, c.story.plan.endIdx + 1);
|
|
6027
|
+
const numbers = again ? [...(again.jump.numbers ?? [])] : [];
|
|
6028
|
+
if (!again) {
|
|
6029
|
+
for (let i = startIdx; i <= c.story.plan.endIdx; i++) {
|
|
6030
|
+
if (headingPrefixes[i] === undefined && headingNumbers[i] === undefined)
|
|
6031
|
+
continue;
|
|
6032
|
+
numbers.push({
|
|
6033
|
+
at: i - startIdx,
|
|
6034
|
+
...(headingPrefixes[i] !== undefined ? { prefix: headingPrefixes[i] } : {}),
|
|
6035
|
+
...(headingNumbers[i] !== undefined ? { value: headingNumbers[i] } : {}),
|
|
6036
|
+
...(chapterNumberByBlock[i] ? { chapterNumber: chapterNumberByBlock[i] } : {}),
|
|
6037
|
+
});
|
|
6038
|
+
}
|
|
6039
|
+
}
|
|
6040
|
+
const notes = [];
|
|
6041
|
+
const seen = new Set();
|
|
6042
|
+
for (const b of blocks) {
|
|
6043
|
+
for (const span of b.spans) {
|
|
6044
|
+
const id = span.footnote?.id;
|
|
6045
|
+
if (id === undefined || seen.has(id))
|
|
6046
|
+
continue;
|
|
6047
|
+
seen.add(id);
|
|
6048
|
+
const number = footnoteNumbering.numbers.get(id);
|
|
6049
|
+
if (number === undefined)
|
|
6050
|
+
continue;
|
|
6051
|
+
const def = footnoteDefs.get(id);
|
|
6052
|
+
notes.push({ id, number, ...(def ? { def } : {}) });
|
|
6053
|
+
}
|
|
6054
|
+
}
|
|
6055
|
+
const rule = c.rule;
|
|
6056
|
+
const frame = continueInPage(rule)?.frame;
|
|
6057
|
+
return {
|
|
6058
|
+
...(again ? { chapter: again.chapter } : {}),
|
|
6059
|
+
target: page,
|
|
6060
|
+
...(frame !== undefined ? { targetFrame: frame } : {}),
|
|
6061
|
+
rule,
|
|
6062
|
+
frame: c.frame,
|
|
6063
|
+
fromFrameId: c.fromFrameId,
|
|
6064
|
+
head: c.head,
|
|
6065
|
+
template: c.template,
|
|
6066
|
+
collapsed: c.collapsed,
|
|
6067
|
+
slot: c.slot,
|
|
6068
|
+
pieces: c.pieces,
|
|
6069
|
+
headBlockId: c.headBlockId,
|
|
6070
|
+
...(c.trailing ? { trailing: c.trailing } : {}),
|
|
6071
|
+
...(c.fromMark !== undefined ? { fromMark: c.fromMark } : {}),
|
|
6072
|
+
cut: c.cut,
|
|
6073
|
+
blocks: blocks,
|
|
6074
|
+
bodyOffset,
|
|
6075
|
+
...(numbers.length > 0 ? { numbers } : {}),
|
|
6076
|
+
orderedLevelIndentsPx: again?.jump.orderedLevelIndentsPx ?? orderedLevelIndentsPx,
|
|
6077
|
+
...(notes.length > 0 ? { footnotes: notes } : {}),
|
|
6078
|
+
...(hasAnchorRefs(blocks, new Set((content.resources ?? []).map((r) => r.id))) ? { outline: true } : {}),
|
|
6079
|
+
};
|
|
6080
|
+
};
|
|
6081
|
+
for (const [id, list] of carried?.byTarget ?? []) {
|
|
6082
|
+
if (fenceById.has(id)) {
|
|
6083
|
+
jumps.set(id, [...(jumps.get(id) ?? []), ...list]);
|
|
6084
|
+
continue;
|
|
6085
|
+
}
|
|
6086
|
+
// The host named this chapter for a page it does not have.
|
|
6087
|
+
for (const c of list) {
|
|
6088
|
+
composedNotes.push({
|
|
6089
|
+
kind: 'continueTargetMissing',
|
|
6090
|
+
template: c.template,
|
|
6091
|
+
frame: c.frame,
|
|
6092
|
+
fenceIndex: -1,
|
|
6093
|
+
target: id,
|
|
6094
|
+
fromChapter: c.foreign?.chapter ?? -1,
|
|
6095
|
+
configPath: '',
|
|
6096
|
+
});
|
|
6097
|
+
}
|
|
6098
|
+
}
|
|
6000
6099
|
/** Set the composed page `planned` on a fresh page (#855), or a spread
|
|
6001
6100
|
* template on the two facing pages from the next verso (#861). */
|
|
6002
6101
|
const placeComposedPage = (planned, fence) => {
|
|
@@ -6010,7 +6109,7 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
6010
6109
|
* other templates of the same kind (single pages for this side, or
|
|
6011
6110
|
* spreads). */
|
|
6012
6111
|
const common = (page, current) => ({
|
|
6013
|
-
pass:
|
|
6112
|
+
pass: composedPass,
|
|
6014
6113
|
fence,
|
|
6015
6114
|
startIdx: planned.startIdx,
|
|
6016
6115
|
endIdx: planned.endIdx,
|
|
@@ -6143,6 +6242,7 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
6143
6242
|
const commit = (list) => {
|
|
6144
6243
|
for (const { page, composed, blocks } of list) {
|
|
6145
6244
|
page.composed = composed;
|
|
6245
|
+
fenceEnd.set(composed, planned.endIdx);
|
|
6146
6246
|
const floats = (page.floats ??= []);
|
|
6147
6247
|
for (const b of blocks) {
|
|
6148
6248
|
floats.push(b);
|
|
@@ -6164,12 +6264,7 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
6164
6264
|
indexFrames(placed);
|
|
6165
6265
|
/** The sending frame of `c` points to the frame `to` that took it, and
|
|
6166
6266
|
* its page's log says where it went. */
|
|
6167
|
-
const
|
|
6168
|
-
const src = frameAt.get(c.fromFrameId);
|
|
6169
|
-
const dst = frameAt.get(to);
|
|
6170
|
-
if (!src || !dst)
|
|
6171
|
-
return;
|
|
6172
|
-
src.frame.continuesTo = to;
|
|
6267
|
+
const logContinued = (src, c, event) => {
|
|
6173
6268
|
const log = src.page.composed.log;
|
|
6174
6269
|
let at = log.length;
|
|
6175
6270
|
for (let i = log.length - 1; i >= 0; i--) {
|
|
@@ -6178,7 +6273,19 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
6178
6273
|
break;
|
|
6179
6274
|
}
|
|
6180
6275
|
}
|
|
6181
|
-
log.splice(at, 0, { frame: c.frame, kind: 'continued',
|
|
6276
|
+
log.splice(at, 0, { frame: c.frame, kind: 'continued', ...event });
|
|
6277
|
+
};
|
|
6278
|
+
const link = (c, to) => {
|
|
6279
|
+
// The sending frame is on a page of another chapter: the host links
|
|
6280
|
+
// the two (`resolveJumpMarks`).
|
|
6281
|
+
if (c.foreign)
|
|
6282
|
+
return;
|
|
6283
|
+
const src = frameAt.get(c.fromFrameId);
|
|
6284
|
+
const dst = frameAt.get(to);
|
|
6285
|
+
if (!src || !dst)
|
|
6286
|
+
return;
|
|
6287
|
+
src.frame.continuesTo = to;
|
|
6288
|
+
logContinued(src, c, { toPage: dst.page.index, toFrame: to });
|
|
6182
6289
|
};
|
|
6183
6290
|
for (const [name, c] of jumpReceivers)
|
|
6184
6291
|
link(c, frameElementId(fence.fenceIndex, name));
|
|
@@ -6201,6 +6308,16 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
6201
6308
|
continue;
|
|
6202
6309
|
}
|
|
6203
6310
|
const from = frameAt.get(c.fromFrameId);
|
|
6311
|
+
// A page of a later chapter (#943): the host hands the rest over.
|
|
6312
|
+
const later = !to && content.laterPageIds && Object.prototype.hasOwnProperty.call(content.laterPageIds, target.page) ? content.laterPageIds[target.page] : undefined;
|
|
6313
|
+
if (later !== undefined) {
|
|
6314
|
+
pendingJumps.push(exportJump(c, target.page));
|
|
6315
|
+
if (from) {
|
|
6316
|
+
from.frame.continuesToChapter = later;
|
|
6317
|
+
logContinued(from, c, { toChapter: later });
|
|
6318
|
+
}
|
|
6319
|
+
continue;
|
|
6320
|
+
}
|
|
6204
6321
|
composedNotes.push({
|
|
6205
6322
|
kind: 'continueTargetMissing',
|
|
6206
6323
|
template: c.template,
|
|
@@ -8699,6 +8816,10 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
8699
8816
|
// Composed pages (#855): frames whose content does not fit.
|
|
8700
8817
|
if (composedNotes.length > 0)
|
|
8701
8818
|
composedWarningsByDoc.set(doc, composedNotes);
|
|
8819
|
+
if (pendingJumps.length > 0)
|
|
8820
|
+
doc.pendingJumps = pendingJumps;
|
|
8821
|
+
if (carried)
|
|
8822
|
+
stampCarriedSource(doc, carried, fenceEnd);
|
|
8702
8823
|
// The composition rules (#749): short lists cut, floats on opener pages.
|
|
8703
8824
|
const ruleNotes = [...shortListWarnings(), ...openerFloatNotes, ...tocGroupWarnings()];
|
|
8704
8825
|
if (ruleNotes.length > 0)
|
|
@@ -8867,6 +8988,39 @@ function afterTextWarnings(doc) {
|
|
|
8867
8988
|
}
|
|
8868
8989
|
return out;
|
|
8869
8990
|
}
|
|
8991
|
+
/**
|
|
8992
|
+
* Mark the blocks laid from stories that came in from other chapters
|
|
8993
|
+
* (#943): `VDTBlock.sourceChapter` says whose file their source offsets
|
|
8994
|
+
* are offsets in.
|
|
8995
|
+
*/
|
|
8996
|
+
function stampCarriedSource(doc, carried, fenceEnd) {
|
|
8997
|
+
const stories = [...carried.stories.values()];
|
|
8998
|
+
const noteChapter = new Map(carried.footnotes.map((n) => [n.id, n.chapter]));
|
|
8999
|
+
for (const block of doc.blocks) {
|
|
9000
|
+
const note = block.footnoteNote !== undefined ? noteChapter.get(block.footnoteNote) : undefined;
|
|
9001
|
+
if (note !== undefined)
|
|
9002
|
+
block.sourceChapter = note;
|
|
9003
|
+
const at = block.contentIndex;
|
|
9004
|
+
if (at === undefined)
|
|
9005
|
+
continue;
|
|
9006
|
+
const story = stories.find((st) => at >= st.startIdx && at <= st.endIdx);
|
|
9007
|
+
if (story)
|
|
9008
|
+
block.sourceChapter = story.chapter;
|
|
9009
|
+
}
|
|
9010
|
+
// The frames that set a carried story's text: the box (a block of the
|
|
9011
|
+
// frame) says whose it is.
|
|
9012
|
+
for (const page of doc.pages) {
|
|
9013
|
+
for (const frame of page.composed?.frames ?? []) {
|
|
9014
|
+
const box = frame.blockIds.length > 0 ? page.floats?.find((b) => b.id === frame.blockIds[0]) : undefined;
|
|
9015
|
+
if (box?.sourceChapter === undefined)
|
|
9016
|
+
continue;
|
|
9017
|
+
frame.sourceChapter = box.sourceChapter;
|
|
9018
|
+
const end = fenceEnd.get(page.composed);
|
|
9019
|
+
if (end !== undefined)
|
|
9020
|
+
frame.readIndex = end + 0.5;
|
|
9021
|
+
}
|
|
9022
|
+
}
|
|
9023
|
+
}
|
|
8870
9024
|
/**
|
|
8871
9025
|
* Write the page numbers into the continuation marks of composed pages'
|
|
8872
9026
|
* frames (#917, `VDTDesignTextBlock.pageMark`): `{page}` becomes the label
|
|
@@ -8880,6 +9034,22 @@ function fillPageMarks(pages) {
|
|
|
8880
9034
|
for (const f of p.composed?.frames ?? [])
|
|
8881
9035
|
if (!f.facingBlocks)
|
|
8882
9036
|
frames.set(f.id, p);
|
|
9037
|
+
forEachPageMark(pages, (f, d) => {
|
|
9038
|
+
// A page of another chapter is `resolveJumpMarks`'s (its frame ids are
|
|
9039
|
+
// another chapter's).
|
|
9040
|
+
if ((d.pageMark.page === 'to' ? f.continuesToChapter : f.continuedFromChapter) !== undefined)
|
|
9041
|
+
return undefined;
|
|
9042
|
+
const other = d.pageMark.page === 'to' ? f.continuesTo : f.continuedFrom;
|
|
9043
|
+
const at = other !== undefined ? frames.get(other) : undefined;
|
|
9044
|
+
return at ? pageLabelOf(at) : undefined;
|
|
9045
|
+
});
|
|
9046
|
+
}
|
|
9047
|
+
/** The label a page prints. */
|
|
9048
|
+
const pageLabelOf = (page) => page.pageLabel ?? String(page.pageNumberValue ?? page.index + 1);
|
|
9049
|
+
/** Each continuation mark with a page number of `pages`' composed frames,
|
|
9050
|
+
* with `label` answering for the page it names: the mark's text is laid
|
|
9051
|
+
* out again with the number when it answers. */
|
|
9052
|
+
function forEachPageMark(pages, label) {
|
|
8883
9053
|
for (const p of pages) {
|
|
8884
9054
|
for (const f of p.composed?.frames ?? []) {
|
|
8885
9055
|
for (const id of f.blockIds) {
|
|
@@ -8887,12 +9057,10 @@ function fillPageMarks(pages) {
|
|
|
8887
9057
|
for (const d of box?.designOverlay?.blocks ?? []) {
|
|
8888
9058
|
if (d.kind !== 'text' || !d.pageMark)
|
|
8889
9059
|
continue;
|
|
8890
|
-
const
|
|
8891
|
-
|
|
8892
|
-
if (!at)
|
|
9060
|
+
const shown = label(f, d);
|
|
9061
|
+
if (shown === undefined)
|
|
8893
9062
|
continue;
|
|
8894
|
-
const
|
|
8895
|
-
const text = d.pageMark.text.split('{page}').join(label);
|
|
9063
|
+
const text = d.pageMark.text.split('{page}').join(shown);
|
|
8896
9064
|
const lh = d.lines.length > 0 ? d.bbox.height / d.lines.length : d.bbox.height;
|
|
8897
9065
|
const first = d.lines[0];
|
|
8898
9066
|
const slack0 = first ? d.bbox.width - first.width : 0;
|
|
@@ -8910,6 +9078,60 @@ function fillPageMarks(pages) {
|
|
|
8910
9078
|
}
|
|
8911
9079
|
}
|
|
8912
9080
|
}
|
|
9081
|
+
/**
|
|
9082
|
+
* Link the stories that jump from one chapter to a page of another (#943)
|
|
9083
|
+
* and write the page numbers into their continuation marks. `docs` is the
|
|
9084
|
+
* book laid out, one document per chapter, in the order of the book (a
|
|
9085
|
+
* story's `chapter` is its position in it): the sending frame gets the
|
|
9086
|
+
* frame that took the rest (`continuesTo`, its `continued` event the page
|
|
9087
|
+
* and frame there), and every mark naming a page of another chapter
|
|
9088
|
+
* prints that page's label as its chapter numbered it. Marks within a
|
|
9089
|
+
* chapter were filled by its own build. Safe to run again on the same
|
|
9090
|
+
* documents.
|
|
9091
|
+
*/
|
|
9092
|
+
export function resolveJumpMarks(docs) {
|
|
9093
|
+
const byId = docs.map((doc) => {
|
|
9094
|
+
const out = new Map();
|
|
9095
|
+
for (const p of doc.pages)
|
|
9096
|
+
for (const f of p.composed?.frames ?? [])
|
|
9097
|
+
if (!f.facingBlocks)
|
|
9098
|
+
out.set(f.id, p);
|
|
9099
|
+
return out;
|
|
9100
|
+
});
|
|
9101
|
+
const frameOf = (chapter, id) => {
|
|
9102
|
+
const page = byId[chapter]?.get(id);
|
|
9103
|
+
const frame = page?.composed?.frames.find((f) => f.id === id);
|
|
9104
|
+
return page && frame ? { page, frame } : undefined;
|
|
9105
|
+
};
|
|
9106
|
+
// The receiving frames name where their story came from; give the
|
|
9107
|
+
// sending frame the way on.
|
|
9108
|
+
docs.forEach((doc) => {
|
|
9109
|
+
for (const p of doc.pages) {
|
|
9110
|
+
for (const f of p.composed?.frames ?? []) {
|
|
9111
|
+
if (f.continuedFromChapter === undefined || f.continuedFrom === undefined)
|
|
9112
|
+
continue;
|
|
9113
|
+
const from = frameOf(f.continuedFromChapter, f.continuedFrom);
|
|
9114
|
+
if (!from)
|
|
9115
|
+
continue;
|
|
9116
|
+
from.frame.continuesTo = f.id;
|
|
9117
|
+
const event = from.page.composed.log.find((e) => e.kind === 'continued' && e.frame === from.frame.name && e.toChapter !== undefined);
|
|
9118
|
+
if (event) {
|
|
9119
|
+
event.toPage = p.index;
|
|
9120
|
+
event.toFrame = f.id;
|
|
9121
|
+
}
|
|
9122
|
+
}
|
|
9123
|
+
}
|
|
9124
|
+
});
|
|
9125
|
+
docs.forEach((doc) => {
|
|
9126
|
+
forEachPageMark(doc.pages, (f, d) => {
|
|
9127
|
+
const [chapter, id] = d.pageMark.page === 'to' ? [f.continuesToChapter, f.continuesTo] : [f.continuedFromChapter, f.continuedFrom];
|
|
9128
|
+
if (chapter === undefined || id === undefined)
|
|
9129
|
+
return undefined;
|
|
9130
|
+
const at = byId[chapter]?.get(id);
|
|
9131
|
+
return at ? pageLabelOf(at) : undefined;
|
|
9132
|
+
});
|
|
9133
|
+
});
|
|
9134
|
+
}
|
|
8913
9135
|
/** `doc` with the page of each of its index marks (`doc.indexMarks`). */
|
|
8914
9136
|
function withIndexMarks(doc, content) {
|
|
8915
9137
|
const { content: body, contentOffset } = extractFrontmatter(content.markdown);
|