postext 1.9.2 → 1.11.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__/pipeline/calloutOverflow.test.js +25 -0
- package/dist/__tests__/pipeline/calloutOverflow.test.js.map +1 -1
- package/dist/__tests__/pipeline/footnotesCjk.test.d.ts +2 -0
- package/dist/__tests__/pipeline/footnotesCjk.test.d.ts.map +1 -0
- package/dist/__tests__/pipeline/footnotesCjk.test.js +206 -0
- package/dist/__tests__/pipeline/footnotesCjk.test.js.map +1 -0
- package/dist/defaults/footnotes.d.ts +2 -1
- package/dist/defaults/footnotes.d.ts.map +1 -1
- package/dist/defaults/footnotes.js +22 -2
- package/dist/defaults/footnotes.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/knuthPlass/richAdapter.d.ts +2 -0
- package/dist/knuthPlass/richAdapter.d.ts.map +1 -1
- package/dist/knuthPlass/richAdapter.js +1 -0
- package/dist/knuthPlass/richAdapter.js.map +1 -1
- package/dist/measure/cache.js +1 -1
- package/dist/measure/cache.js.map +1 -1
- package/dist/measure/rich.d.ts +6 -0
- package/dist/measure/rich.d.ts.map +1 -1
- package/dist/measure/rich.js +12 -1
- package/dist/measure/rich.js.map +1 -1
- package/dist/parse/types.d.ts +4 -1
- package/dist/parse/types.d.ts.map +1 -1
- package/dist/pipeline/build.d.ts +3 -0
- package/dist/pipeline/build.d.ts.map +1 -1
- package/dist/pipeline/build.js +84 -9
- package/dist/pipeline/build.js.map +1 -1
- package/dist/pipeline/config.js +1 -1
- package/dist/pipeline/config.js.map +1 -1
- package/dist/pipeline/footnotes.d.ts +34 -7
- package/dist/pipeline/footnotes.d.ts.map +1 -1
- package/dist/pipeline/footnotes.js +62 -14
- package/dist/pipeline/footnotes.js.map +1 -1
- package/dist/pipeline/measureContentBlock.d.ts.map +1 -1
- package/dist/pipeline/measureContentBlock.js +20 -4
- package/dist/pipeline/measureContentBlock.js.map +1 -1
- package/dist/types.d.ts +30 -4
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/pipeline/build.js
CHANGED
|
@@ -23,7 +23,7 @@ import { chooseParagraphSplit } from './orphanWidow';
|
|
|
23
23
|
import { applyStyleAttrs, computePageMetrics, pageMirrored, sheetRectToFlow, isMarkerBlock, nextNonMarkerBlock, spaceLinesAfter, prevNonMarkerBlock, rollbackTrailingBlocks, } from './buildHelpers';
|
|
24
24
|
import { measureContentBlock } from './measureContentBlock';
|
|
25
25
|
import { planParagraphContainers } from './paragraphContainers';
|
|
26
|
-
import { appendChapterEndNotes, footnoteIdsOfLines, footnoteParagraphStyle, noteContentBlock, numberFootnotes, splitFootnoteDefinitions, withFootnoteStyle, } from './footnotes';
|
|
26
|
+
import { appendChapterEndNotes, footnoteIdsOfLines, footnoteParagraphStyle, noteContentBlock, numberFootnotes, numberFootnotesByPlacement, sameFootnoteNumbers, splitFootnoteDefinitions, withFootnoteStyle, } from './footnotes';
|
|
27
27
|
import { planParts, derivePartMeasureContext } from './parts';
|
|
28
28
|
import { layoutCallout, offsetCalloutToAbsolute, pickCalloutStyle, planCallouts, resolveCalloutAttrs, } from './calloutLayout';
|
|
29
29
|
import { layoutResourceBlock, planTableSlice } from './resourceLayout';
|
|
@@ -273,10 +273,19 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
273
273
|
// come back as paragraphs after each chapter's last block.
|
|
274
274
|
const footnoteSplit = splitFootnoteDefinitions(headingMarksFor(parseMarkdownMemo(markdownBody), resolved));
|
|
275
275
|
const footnoteDefs = footnoteSplit.defs;
|
|
276
|
-
|
|
276
|
+
// Numbered by page or column (`numbering: 'page'`), a note takes the
|
|
277
|
+
// number the previous build gave it where it landed; the first build
|
|
278
|
+
// numbers by chapter (see `buildDocumentNumbered`).
|
|
279
|
+
const footnoteNumbering = numberFootnotes(footnoteSplit.blocks, resolved.footnotes.numbering, resolved.footnotes.numbering === 'document' ? Math.max(0, Math.floor(continuation?.footnoteNumber ?? 0)) : 0, resolved.footnotes.numberFormat);
|
|
280
|
+
if (hints.footnoteNumbers) {
|
|
281
|
+
for (const [id, number] of hints.footnoteNumbers) {
|
|
282
|
+
if (footnoteNumbering.numbers.has(id))
|
|
283
|
+
footnoteNumbering.numbers.set(id, number);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
277
286
|
const chapterEndNotes = resolved.footnotes.placement === 'chapterEnd' && footnoteNumbering.numbers.size > 0;
|
|
278
287
|
const parsedBlocks = chapterEndNotes
|
|
279
|
-
? appendChapterEndNotes(footnoteSplit.blocks, footnoteNumbering, footnoteDefs)
|
|
288
|
+
? appendChapterEndNotes(footnoteSplit.blocks, footnoteNumbering, footnoteDefs, resolved.footnotes.markerPosition)
|
|
280
289
|
: footnoteSplit.blocks;
|
|
281
290
|
const headingStart = continuation?.headings;
|
|
282
291
|
// `:::toc` expands into the entries of the book's outline — the one the
|
|
@@ -1591,7 +1600,7 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
1591
1600
|
let m = noteMeasures.get(key);
|
|
1592
1601
|
if (m === undefined) {
|
|
1593
1602
|
const number = footnoteNumbering.numbers.get(id) ?? '?';
|
|
1594
|
-
m = measureContentBlock(noteContentBlock(footnoteDefs.get(id), id, number), 0, width, measureCtx, { styleOverride: noteStyle });
|
|
1603
|
+
m = measureContentBlock(noteContentBlock(footnoteDefs.get(id), id, number, resolved.footnotes.markerPosition), 0, width, measureCtx, { styleOverride: noteStyle });
|
|
1595
1604
|
noteMeasures.set(key, m);
|
|
1596
1605
|
}
|
|
1597
1606
|
return m;
|
|
@@ -2819,6 +2828,9 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
2819
2828
|
/** The box already moved to a fresh page (or sits on an empty one):
|
|
2820
2829
|
* whatever does not fit there is force-placed and overflows. */
|
|
2821
2830
|
let forceHere = false;
|
|
2831
|
+
/** Times the box left a fresh page whose room the floats flushed onto
|
|
2832
|
+
* it had taken — bounded. */
|
|
2833
|
+
let floatPageMoves = 0;
|
|
2822
2834
|
for (;;) {
|
|
2823
2835
|
let page = doc.pages[cursor.pageIndex];
|
|
2824
2836
|
const continuation = part > 0;
|
|
@@ -2942,6 +2954,22 @@ function placeDocumentPass(content, config, cache, options, hints) {
|
|
|
2942
2954
|
}
|
|
2943
2955
|
}
|
|
2944
2956
|
}
|
|
2957
|
+
// A fresh page whose room went to the floats flushed onto it (a
|
|
2958
|
+
// figure page, a page-span figure standing upright across a vertical
|
|
2959
|
+
// page) holds no text to cut: a box a page would hold moves on to the
|
|
2960
|
+
// next page rather than overflow this one.
|
|
2961
|
+
if (!action && forceHere && fit && floatPageMoves < 2
|
|
2962
|
+
&& fit.spacing + result.totalHeight > fit.roomPx + 0.5
|
|
2963
|
+
&& result.totalHeight <= contentArea.height + 0.01
|
|
2964
|
+
&& !pageHasContent(page) && (page.floats?.length ?? 0) > 0) {
|
|
2965
|
+
floatPageMoves++;
|
|
2966
|
+
pendingSpacing = 0;
|
|
2967
|
+
const startPageIndex = cursor.pageIndex;
|
|
2968
|
+
do {
|
|
2969
|
+
advanceToNextColumn(doc, cursor, geomResolved, contentArea, pageWidthPx, pageHeightPx, onNewPage);
|
|
2970
|
+
} while (cursor.pageIndex === startPageIndex);
|
|
2971
|
+
continue;
|
|
2972
|
+
}
|
|
2945
2973
|
if (!action && forceHere && fit) {
|
|
2946
2974
|
action = { kind: 'whole', fit, need: fit.need, result };
|
|
2947
2975
|
// A box that fills its band to the last grid line is not an overflow.
|
|
@@ -5309,21 +5337,68 @@ function* buildDocumentRounds(content, config, cache, options) {
|
|
|
5309
5337
|
const parsed = parseMarkdownMemo(extractFrontmatter(content.markdown).content);
|
|
5310
5338
|
if (hasTocDirective(parsed) || hasIndexDirective(parsed)) {
|
|
5311
5339
|
let outline = computeOutline(parsed, resolveAllConfig(config), content.continuation?.headings);
|
|
5312
|
-
let doc = withIndexMarks(yield*
|
|
5340
|
+
let doc = withIndexMarks(yield* buildDocumentNumbered({ ...content, outline }, config, cache, options, 0), content);
|
|
5313
5341
|
for (let round = 0; round < MAX_TOC_ROUNDS; round++) {
|
|
5314
5342
|
const after = outlineFromDoc(doc, outline);
|
|
5315
5343
|
if (sameOutline(after, outline))
|
|
5316
5344
|
break;
|
|
5317
5345
|
outline = after;
|
|
5318
|
-
doc = withIndexMarks(yield*
|
|
5346
|
+
doc = withIndexMarks(yield* buildDocumentNumbered({ ...content, outline }, config, cache, options, round + 1), content);
|
|
5319
5347
|
}
|
|
5320
5348
|
return doc;
|
|
5321
5349
|
}
|
|
5322
5350
|
}
|
|
5323
|
-
return withIndexMarks(yield*
|
|
5351
|
+
return withIndexMarks(yield* buildDocumentNumbered(content, config, cache, options), content);
|
|
5352
|
+
}
|
|
5353
|
+
/** The number each note's marker prints in `doc` (its first marker). */
|
|
5354
|
+
function printedFootnoteNumbers(doc) {
|
|
5355
|
+
const out = new Map();
|
|
5356
|
+
for (const block of doc.blocks) {
|
|
5357
|
+
if (block.footnoteNote !== undefined)
|
|
5358
|
+
continue;
|
|
5359
|
+
for (const line of block.lines) {
|
|
5360
|
+
for (const seg of line.segments ?? []) {
|
|
5361
|
+
if (seg.footnoteId !== undefined && !out.has(seg.footnoteId))
|
|
5362
|
+
out.set(seg.footnoteId, seg.text);
|
|
5363
|
+
}
|
|
5364
|
+
}
|
|
5365
|
+
}
|
|
5366
|
+
return out;
|
|
5367
|
+
}
|
|
5368
|
+
/** Builds a document numbering its notes by page (or column) gets at most,
|
|
5369
|
+
* beyond the first, for the numbers to settle. */
|
|
5370
|
+
const MAX_FOOTNOTE_ROUNDS = 3;
|
|
5371
|
+
/**
|
|
5372
|
+
* {@link buildDocumentBalanced}, with `footnotes.numbering: 'page'` /
|
|
5373
|
+
* `'column'`: a note's number depends on the page the layout sets it on,
|
|
5374
|
+
* so the document is numbered by chapter, laid out, numbered again where
|
|
5375
|
+
* its notes landed, and laid out with those numbers until they no longer
|
|
5376
|
+
* change (as the contents' page labels are). A circled marker is the same
|
|
5377
|
+
* width whatever its number, so the second build reflows nothing and the
|
|
5378
|
+
* numbers hold; a decimal one may move a line (9 → 10), hence the bound.
|
|
5379
|
+
*/
|
|
5380
|
+
function* buildDocumentNumbered(content, config, cache, options, tocRound = 0) {
|
|
5381
|
+
let doc = yield* buildDocumentBalanced(content, config, cache, options, tocRound);
|
|
5382
|
+
const f = doc.config.footnotes;
|
|
5383
|
+
if (f.placement !== 'column' || (f.numbering !== 'page' && f.numbering !== 'column'))
|
|
5384
|
+
return doc;
|
|
5385
|
+
for (let round = 0; round < MAX_FOOTNOTE_ROUNDS; round++) {
|
|
5386
|
+
const used = printedFootnoteNumbers(doc);
|
|
5387
|
+
if (used.size === 0)
|
|
5388
|
+
break;
|
|
5389
|
+
const placed = numberFootnotesByPlacement(doc.pages, f.numbering, f.numberFormat).numbers;
|
|
5390
|
+
// A note the layout set nowhere keeps the number it had.
|
|
5391
|
+
const next = new Map(used);
|
|
5392
|
+
for (const [id, number] of placed)
|
|
5393
|
+
next.set(id, number);
|
|
5394
|
+
if (sameFootnoteNumbers(next, used))
|
|
5395
|
+
break;
|
|
5396
|
+
doc = yield* buildDocumentBalanced(content, config, cache, options, tocRound, next);
|
|
5397
|
+
}
|
|
5398
|
+
return doc;
|
|
5324
5399
|
}
|
|
5325
5400
|
const now = () => (typeof performance !== 'undefined' ? performance.now() : Date.now());
|
|
5326
|
-
function* buildDocumentBalanced(content, config, cache, options, tocRound = 0) {
|
|
5401
|
+
function* buildDocumentBalanced(content, config, cache, options, tocRound = 0, footnoteNumbers) {
|
|
5327
5402
|
// Each pass reports its own progress, numbered in build order.
|
|
5328
5403
|
let passIndex = 0;
|
|
5329
5404
|
const onProgress = options?.onProgress;
|
|
@@ -5337,7 +5412,7 @@ function* buildDocumentBalanced(content, config, cache, options, tocRound = 0) {
|
|
|
5337
5412
|
const runPass = (hints) => {
|
|
5338
5413
|
passIndex++;
|
|
5339
5414
|
const started = onPass ? now() : 0;
|
|
5340
|
-
const result = buildDocumentPass(content, config, cache, passOptions, { ...hints, captionUnder });
|
|
5415
|
+
const result = buildDocumentPass(content, config, cache, passOptions, { ...hints, captionUnder, ...(footnoteNumbers ? { footnoteNumbers } : {}) });
|
|
5341
5416
|
for (const id of result.captionUnderProposals)
|
|
5342
5417
|
captionUnder.add(id);
|
|
5343
5418
|
onPass?.({ pass: passIndex, tocRound, ms: now() - started, pages: result.doc.pages.length });
|