postext 1.52.0 → 1.53.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__/breakOpportunities.test.js +12 -7
- package/dist/__tests__/breakOpportunities.test.js.map +1 -1
- package/dist/__tests__/bundle/balloonPlacementPin.test.js +11 -9
- package/dist/__tests__/bundle/balloonPlacementPin.test.js.map +1 -1
- package/dist/__tests__/bundle/cjkRulesPin.test.js +12 -12
- package/dist/__tests__/bundle/cjkRulesPin.test.js.map +1 -1
- package/dist/__tests__/bundle/designOverflowPin.test.js +3 -3
- package/dist/__tests__/bundle/designOverflowPin.test.js.map +1 -1
- package/dist/__tests__/bundle/flowColumnsPin.test.js +4 -4
- package/dist/__tests__/bundle/flowColumnsPin.test.js.map +1 -1
- package/dist/__tests__/bundle/gridBalancingPin.test.js +11 -9
- package/dist/__tests__/bundle/gridBalancingPin.test.js.map +1 -1
- package/dist/__tests__/bundle/gridBreakRulesPin.test.js +26 -24
- package/dist/__tests__/bundle/gridBreakRulesPin.test.js.map +1 -1
- package/dist/__tests__/bundle/indexGroupSplitPin.test.js +4 -4
- package/dist/__tests__/bundle/indexGroupSplitPin.test.js.map +1 -1
- package/dist/__tests__/bundle/looseOrderPin.test.js +11 -9
- package/dist/__tests__/bundle/looseOrderPin.test.js.map +1 -1
- package/dist/__tests__/bundle/markRadiusPin.test.js +3 -3
- package/dist/__tests__/bundle/markRadiusPin.test.js.map +1 -1
- package/dist/__tests__/bundle/refLabelBreaksPin.test.js +11 -9
- package/dist/__tests__/bundle/refLabelBreaksPin.test.js.map +1 -1
- package/dist/__tests__/bundle/scriptContextPin.test.js +12 -10
- package/dist/__tests__/bundle/scriptContextPin.test.js.map +1 -1
- package/dist/__tests__/bundle/shapingLanguagePin.test.js +20 -18
- package/dist/__tests__/bundle/shapingLanguagePin.test.js.map +1 -1
- package/dist/__tests__/bundle/taskBoxPin.test.js +1 -1
- package/dist/__tests__/bundle/trailingStepPin.test.js +4 -4
- package/dist/__tests__/bundle/trailingStepPin.test.js.map +1 -1
- package/dist/__tests__/bundle/wideFloatStretchPin.test.js +4 -4
- package/dist/__tests__/bundle/wideFloatStretchPin.test.js.map +1 -1
- package/dist/__tests__/bundle.test.js +5 -5
- package/dist/__tests__/bundle.test.js.map +1 -1
- package/dist/__tests__/codeBlocks.test.js +1 -1
- package/dist/__tests__/composed/folioMissing.test.d.ts +2 -0
- package/dist/__tests__/composed/folioMissing.test.d.ts.map +1 -0
- package/dist/__tests__/composed/folioMissing.test.js +90 -0
- package/dist/__tests__/composed/folioMissing.test.js.map +1 -0
- package/dist/__tests__/composedTemplates.test.js +8 -6
- package/dist/__tests__/composedTemplates.test.js.map +1 -1
- package/dist/__tests__/hardBreaks.test.js +1 -1
- package/dist/__tests__/headingInlineMarks.test.js +1 -1
- package/dist/__tests__/mathSizeMigration.test.js +4 -4
- package/dist/__tests__/mathSizeMigration.test.js.map +1 -1
- package/dist/__tests__/pipeline/boxParagraphStyles.test.js +2 -2
- package/dist/__tests__/pipeline/calloutInlineResourceGap.test.js +1 -1
- package/dist/__tests__/pipeline/calloutSplitMinLinesChild.test.js +3 -3
- package/dist/__tests__/pipeline/calloutSplitMinLinesChild.test.js.map +1 -1
- package/dist/__tests__/pipeline/colonListRoom.test.js +3 -3
- package/dist/__tests__/pipeline/colonListRoom.test.js.map +1 -1
- package/dist/__tests__/pipeline/compoundBreaks.test.js +6 -6
- package/dist/__tests__/pipeline/compoundBreaks.test.js.map +1 -1
- package/dist/__tests__/pipeline/dashBreaks.test.js +5 -5
- package/dist/__tests__/pipeline/dashBreaks.test.js.map +1 -1
- package/dist/__tests__/pipeline/headingSplitOrphans.test.js +3 -3
- package/dist/__tests__/pipeline/headingSplitOrphans.test.js.map +1 -1
- package/dist/__tests__/pipeline/inlineFigureSpace.test.js +5 -5
- package/dist/__tests__/pipeline/inlineFigureSpace.test.js.map +1 -1
- package/dist/__tests__/pipeline/openerChips.test.d.ts +2 -0
- package/dist/__tests__/pipeline/openerChips.test.d.ts.map +1 -0
- package/dist/__tests__/pipeline/openerChips.test.js +181 -0
- package/dist/__tests__/pipeline/openerChips.test.js.map +1 -0
- package/dist/__tests__/pipeline/paragraphContainerTail.test.js +7 -7
- package/dist/__tests__/pipeline/paragraphContainerTail.test.js.map +1 -1
- package/dist/__tests__/pipeline/raggedOptimal.test.js +7 -7
- package/dist/__tests__/pipeline/raggedOptimal.test.js.map +1 -1
- package/dist/__tests__/scriptContext.test.js +10 -1
- package/dist/__tests__/scriptContext.test.js.map +1 -1
- package/dist/__tests__/slashBreaks.test.d.ts +2 -0
- package/dist/__tests__/slashBreaks.test.d.ts.map +1 -0
- package/dist/__tests__/slashBreaks.test.js +160 -0
- package/dist/__tests__/slashBreaks.test.js.map +1 -0
- package/dist/__tests__/verseLines.test.js +7 -7
- package/dist/__tests__/verseLines.test.js.map +1 -1
- package/dist/bundle/configVersion.d.ts +28 -7
- package/dist/bundle/configVersion.d.ts.map +1 -1
- package/dist/bundle/configVersion.js +40 -7
- package/dist/bundle/configVersion.js.map +1 -1
- package/dist/bundle/index.d.ts +1 -1
- package/dist/bundle/index.d.ts.map +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/index.js.map +1 -1
- package/dist/canvas-backend/headerFooter.d.ts.map +1 -1
- package/dist/canvas-backend/headerFooter.js +10 -0
- package/dist/canvas-backend/headerFooter.js.map +1 -1
- package/dist/composed/furniture.d.ts +41 -0
- package/dist/composed/furniture.d.ts.map +1 -0
- package/dist/composed/furniture.js +108 -0
- package/dist/composed/furniture.js.map +1 -0
- package/dist/defaults/bodyText.d.ts.map +1 -1
- package/dist/defaults/bodyText.js +7 -0
- package/dist/defaults/bodyText.js.map +1 -1
- package/dist/design/bidiText.d.ts +2 -0
- package/dist/design/bidiText.d.ts.map +1 -1
- package/dist/design/bidiText.js +1 -1
- package/dist/design/bidiText.js.map +1 -1
- package/dist/design/cjkText.d.ts.map +1 -1
- package/dist/design/cjkText.js +6 -1
- package/dist/design/cjkText.js.map +1 -1
- package/dist/design/layout.d.ts +7 -1
- package/dist/design/layout.d.ts.map +1 -1
- package/dist/design/layout.js +49 -15
- package/dist/design/layout.js.map +1 -1
- package/dist/design/placeholders.d.ts +6 -1
- package/dist/design/placeholders.d.ts.map +1 -1
- package/dist/design/placeholders.js.map +1 -1
- package/dist/design/richText.d.ts +28 -4
- package/dist/design/richText.d.ts.map +1 -1
- package/dist/design/richText.js +105 -6
- package/dist/design/richText.js.map +1 -1
- package/dist/html-backend.d.ts.map +1 -1
- package/dist/html-backend.js +28 -5
- package/dist/html-backend.js.map +1 -1
- package/dist/measure/breakRules.d.ts +33 -0
- package/dist/measure/breakRules.d.ts.map +1 -1
- package/dist/measure/breakRules.js +82 -0
- package/dist/measure/breakRules.js.map +1 -1
- package/dist/measure/cache.d.ts.map +1 -1
- package/dist/measure/cache.js +4 -2
- package/dist/measure/cache.js.map +1 -1
- package/dist/measure/rich.d.ts +6 -2
- package/dist/measure/rich.d.ts.map +1 -1
- package/dist/measure/rich.js +69 -6
- package/dist/measure/rich.js.map +1 -1
- package/dist/pipeline/build.d.ts.map +1 -1
- package/dist/pipeline/build.js +16 -7
- package/dist/pipeline/build.js.map +1 -1
- package/dist/pipeline/contentWarnings.d.ts.map +1 -1
- package/dist/pipeline/contentWarnings.js +3 -0
- package/dist/pipeline/contentWarnings.js.map +1 -1
- package/dist/pipeline/headerFooter.d.ts +17 -3
- package/dist/pipeline/headerFooter.d.ts.map +1 -1
- package/dist/pipeline/headerFooter.js +199 -45
- package/dist/pipeline/headerFooter.js.map +1 -1
- package/dist/types.d.ts +17 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/vdt.d.ts +26 -0
- package/dist/vdt.d.ts.map +1 -1
- package/dist/vdt.js.map +1 -1
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@ import { resolvedComics } from '../defaults/comics.js';
|
|
|
2
2
|
import { fontFamilyOf, getMeasureRegion, getMeasureUprightDigits, getMeasureWritingMode, measureCentralBaseline, setMeasureWritingMode, withMeasureWritingMode } from '../measure/vertical.js';
|
|
3
3
|
import { applyPartPalettesToFlow } from './partPalette.js';
|
|
4
4
|
import { recolorLineNumbers } from './lineNumbers.js';
|
|
5
|
-
import { CHIP_PLACEHOLDER, applyTitleBreaks, parseInlineFormatting, replaceTitleBreaks } from '../parse/inlineFormatting.js';
|
|
5
|
+
import { CHIP_PLACEHOLDER, applyTitleBreaks, extractInlineChips, injectChipSpans, parseInlineFormatting, replaceTitleBreaks, withoutChips } from '../parse/inlineFormatting.js';
|
|
6
6
|
import { createBoundingBox, flowRectToPage, pageIsMirrored, pageIsVertical, } from '../vdt.js';
|
|
7
7
|
import { computeChapterTitles, computeChapterTitlesAtTop, computeChapterNumbers, computeChapterNumbersAtTop, computeChapterNumbersByBlock, computeChapterAttrs, computePageMarks, computePartValues, lineJoin, markSourceOf } from './placeholders.js';
|
|
8
8
|
import { parsePartNumber, parsePartPalette, partMarkPages } from './parts.js';
|
|
@@ -17,6 +17,7 @@ import { splitSpreadDecoration } from '../composed/spread.js';
|
|
|
17
17
|
import { pathInkBox } from '../design/pathBlock.js';
|
|
18
18
|
import { frameOfBlock, framePageRect } from '../composed/paint.js';
|
|
19
19
|
import { figureAnchorPointOnPage } from '../composed/labels.js';
|
|
20
|
+
import { expectedFurniture, folioMissingWarnings } from '../composed/furniture.js';
|
|
20
21
|
import { layoutDesignSlot, textVerticalOffset, trailingTracking, } from '../design/layout.js';
|
|
21
22
|
import { resolveDesignText } from '../design/placeholders.js';
|
|
22
23
|
import { plainDesignText } from '../design/richText.js';
|
|
@@ -678,14 +679,40 @@ const PLAIN_RUN = { bold: false, italic: false };
|
|
|
678
679
|
const TITLE_ESCAPE_RE = /[*_^~`]/g;
|
|
679
680
|
const escapeTitleRun = (text) => text.replace(TITLE_ESCAPE_RE, (c) => `\\${c}`);
|
|
680
681
|
const sameEmphasis = (a, b) => a.bold === b.bold && a.italic === b.italic;
|
|
681
|
-
/** The
|
|
682
|
-
*
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
/**
|
|
687
|
-
*
|
|
688
|
-
|
|
682
|
+
/** The characters a chip's label escapes: the inline markers and the
|
|
683
|
+
* brackets (`\]`, see `extractInlineChips`). */
|
|
684
|
+
const CHIP_LABEL_ESCAPE_RE = /[*_^~`[\]]/g;
|
|
685
|
+
/** A chip style id that can be written back as `{style="…"}`. */
|
|
686
|
+
const CHIP_STYLE_ID_RE = /^[^"{}\n]*$/;
|
|
687
|
+
/** A laid-out chip written back as `:chip[…]{style="…"}` (#1162): its
|
|
688
|
+
* runs in logical order, each with its own bold, italic and script, so a
|
|
689
|
+
* design text that reads inline marks sets the same words. Undefined when
|
|
690
|
+
* the style id cannot be written in an attribute. */
|
|
691
|
+
function chipMarkdown(chip) {
|
|
692
|
+
if (!CHIP_STYLE_ID_RE.test(chip.styleId))
|
|
693
|
+
return undefined;
|
|
694
|
+
let label = '';
|
|
695
|
+
for (const run of chip.runs) {
|
|
696
|
+
if (run.text.length === 0)
|
|
697
|
+
continue;
|
|
698
|
+
let t = run.text.replace(CHIP_LABEL_ESCAPE_RE, (c) => `\\${c}`);
|
|
699
|
+
if (run.baselineShift !== undefined && run.baselineShift !== 0)
|
|
700
|
+
t = run.baselineShift < 0 ? `^${t}^` : `~${t}~`;
|
|
701
|
+
const marker = run.bold && run.italic ? '***' : run.bold ? '**' : run.italic ? '*' : '';
|
|
702
|
+
// Markers go round the words, their edge spaces outside them.
|
|
703
|
+
const core = t.trim();
|
|
704
|
+
label += marker && core ? t.replace(core, `${marker}${core}${marker}`) : t;
|
|
705
|
+
}
|
|
706
|
+
if (label.trim() === '')
|
|
707
|
+
label = ' ';
|
|
708
|
+
return `:chip[${label}]${chip.styleId ? `{style="${chip.styleId}"}` : ''}`;
|
|
709
|
+
}
|
|
710
|
+
/** The characters of a heading's lines read back as the title, with the
|
|
711
|
+
* run flags of each (see {@link defaultOpenerTitle}). With `keepChips`
|
|
712
|
+
* each chip stays one {@link CHIP_PLACEHOLDER} carrying its box; else it
|
|
713
|
+
* is left out with the space beside it (#1100), recorded in `removedAt`.
|
|
714
|
+
* Undefined when a chip is to be kept and its segment carries no box. */
|
|
715
|
+
function readTitleChars(lines, keepChips) {
|
|
689
716
|
const chars = [];
|
|
690
717
|
const flags = [];
|
|
691
718
|
/** Where a line break was read back as a space or a no-break space. */
|
|
@@ -696,6 +723,7 @@ numberSeparator = ' ') {
|
|
|
696
723
|
* before it: a chip is a box of the page, not words of the title. */
|
|
697
724
|
const removedAt = [];
|
|
698
725
|
let afterChip = false;
|
|
726
|
+
let missing = false;
|
|
699
727
|
lines.forEach((ln, i) => {
|
|
700
728
|
const start = chars.length;
|
|
701
729
|
// The hyphen repeated from the line before (`repeatHyphen`) is not part
|
|
@@ -709,6 +737,14 @@ numberSeparator = ' ') {
|
|
|
709
737
|
skipRepeated = false;
|
|
710
738
|
}
|
|
711
739
|
if (s.text === CHIP_PLACEHOLDER) {
|
|
740
|
+
if (keepChips) {
|
|
741
|
+
// The chip, one character with its box (#1162).
|
|
742
|
+
if (!s.chip)
|
|
743
|
+
missing = true;
|
|
744
|
+
chars.push(CHIP_PLACEHOLDER);
|
|
745
|
+
flags.push({ bold: false, italic: false, ...(s.chip ? { chip: s.chip } : {}) });
|
|
746
|
+
continue;
|
|
747
|
+
}
|
|
712
748
|
removedAt.push(chars.length);
|
|
713
749
|
afterChip = true;
|
|
714
750
|
continue;
|
|
@@ -749,6 +785,8 @@ numberSeparator = ' ') {
|
|
|
749
785
|
flags.push(PLAIN_RUN);
|
|
750
786
|
}
|
|
751
787
|
});
|
|
788
|
+
if (missing)
|
|
789
|
+
return undefined;
|
|
752
790
|
// The space two lines were broken at takes the emphasis of the words on
|
|
753
791
|
// both sides of it, when they share one.
|
|
754
792
|
for (let i = 1; i < chars.length - 1; i++) {
|
|
@@ -758,25 +796,14 @@ numberSeparator = ' ') {
|
|
|
758
796
|
flags[i] = { bold: f.bold, italic: f.italic };
|
|
759
797
|
}
|
|
760
798
|
}
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
chars.pop();
|
|
770
|
-
flags.pop();
|
|
771
|
-
titleLength--;
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
const title = chars.join('').slice(drop);
|
|
775
|
-
const titleText = applyTitleBreaks(title, titleBreaks, titleLength);
|
|
776
|
-
if (!hasMarks)
|
|
777
|
-
return { titleText };
|
|
778
|
-
let tChars = chars.slice(drop);
|
|
779
|
-
let tFlags = flags.slice(drop);
|
|
799
|
+
return { chars, flags, hasMarks, removedAt };
|
|
800
|
+
}
|
|
801
|
+
/** The title written as inline Markdown from its characters and their run
|
|
802
|
+
* flags (the number prefix dropped), when it reads back as `expected`
|
|
803
|
+
* with the same runs; a chip is written as `:chip[…]` (#1162). */
|
|
804
|
+
function markedTitle(chars, flags, titleBreaks, titleLength, title, expected) {
|
|
805
|
+
let tChars = chars.slice();
|
|
806
|
+
let tFlags = flags.slice();
|
|
780
807
|
// The forced breaks, as `applyTitleBreaks` sets them: a newline at each
|
|
781
808
|
// recorded index, the spaces and tabs around it dropped.
|
|
782
809
|
if (titleBreaks && titleBreaks.length > 0 && title.length === titleLength) {
|
|
@@ -797,15 +824,26 @@ numberSeparator = ' ') {
|
|
|
797
824
|
tFlags = tFlags.filter((_, i) => keep[i]);
|
|
798
825
|
tChars = tChars.filter((_, i) => keep[i]);
|
|
799
826
|
}
|
|
800
|
-
if (tChars.join('') !==
|
|
801
|
-
return
|
|
827
|
+
if (tChars.join('') !== expected)
|
|
828
|
+
return undefined;
|
|
829
|
+
const chips = tFlags.some((f) => f.chip);
|
|
830
|
+
let failed = false;
|
|
802
831
|
const scripted = (a, b) => {
|
|
803
832
|
let out = '';
|
|
804
833
|
let i = a;
|
|
805
834
|
while (i < b) {
|
|
835
|
+
const chip = tFlags[i].chip;
|
|
836
|
+
if (chip) {
|
|
837
|
+
const md = chipMarkdown(chip);
|
|
838
|
+
if (md === undefined)
|
|
839
|
+
failed = true;
|
|
840
|
+
out += md ?? '';
|
|
841
|
+
i++;
|
|
842
|
+
continue;
|
|
843
|
+
}
|
|
806
844
|
const script = tFlags[i].script;
|
|
807
845
|
let j = i + 1;
|
|
808
|
-
while (j < b && tFlags[j].script === script)
|
|
846
|
+
while (j < b && tFlags[j].script === script && !tFlags[j].chip)
|
|
809
847
|
j++;
|
|
810
848
|
const text = escapeTitleRun(tChars.slice(i, j).join(''));
|
|
811
849
|
out += script === 'sup' ? `^${text}^` : script === 'sub' ? `~${text}~` : text;
|
|
@@ -844,23 +882,109 @@ numberSeparator = ' ') {
|
|
|
844
882
|
}
|
|
845
883
|
i = j;
|
|
846
884
|
}
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
885
|
+
if (failed)
|
|
886
|
+
return undefined;
|
|
887
|
+
// Kept only when it reads back as the same text with the same runs (a
|
|
888
|
+
// chip as a chip).
|
|
889
|
+
let spans;
|
|
890
|
+
if (chips) {
|
|
891
|
+
const { cleaned, chips: metas } = extractInlineChips(marked, 0);
|
|
892
|
+
spans = injectChipSpans(parseInlineFormatting(cleaned), metas);
|
|
893
|
+
}
|
|
894
|
+
else
|
|
895
|
+
spans = parseInlineFormatting(marked);
|
|
896
|
+
if (spans.map((s) => s.text).join('') !== expected)
|
|
897
|
+
return undefined;
|
|
851
898
|
let at = 0;
|
|
852
899
|
for (const s of spans) {
|
|
853
900
|
if (s.smallCaps || s.links || s.math)
|
|
854
|
-
return
|
|
901
|
+
return undefined;
|
|
855
902
|
for (let k = 0; k < s.text.length; k++, at++) {
|
|
856
|
-
if (/\s/.test(s.text[k]))
|
|
857
|
-
continue;
|
|
858
903
|
const f = tFlags[at];
|
|
904
|
+
if ((s.chip !== undefined) !== (f.chip !== undefined))
|
|
905
|
+
return undefined;
|
|
906
|
+
if (s.chip || /\s/.test(s.text[k]))
|
|
907
|
+
continue;
|
|
859
908
|
if (f.bold !== !!s.bold || f.italic !== !!s.italic || f.script !== s.script)
|
|
860
|
-
return
|
|
909
|
+
return undefined;
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
return marked;
|
|
913
|
+
}
|
|
914
|
+
/** The title a page-span heading's default opener prints, from the lines the
|
|
915
|
+
* heading was measured into (see {@link DefaultOpenerTitle}). The same
|
|
916
|
+
* reading serves the band's measure (`build.ts`) and its paint, so the
|
|
917
|
+
* two lay out one text. */
|
|
918
|
+
export function defaultOpenerTitle(lines, numberPrefix, titleBreaks, titleLength,
|
|
919
|
+
/** What joins the number to the title in the lines
|
|
920
|
+
* (`HeadingLevelConfig.numberSeparator`). */
|
|
921
|
+
numberSeparator = ' ') {
|
|
922
|
+
const { chars, flags, hasMarks, removedAt } = readTitleChars(lines, false);
|
|
923
|
+
const keptBreaks = titleBreaks;
|
|
924
|
+
const keptLength = titleLength;
|
|
925
|
+
const full = chars.join('');
|
|
926
|
+
const drop = numberPrefix && full.startsWith(`${numberPrefix}${numberSeparator}`) ? numberPrefix.length + numberSeparator.length : 0;
|
|
927
|
+
if (removedAt.length > 0) {
|
|
928
|
+
// The forced breaks and the length of the title without what was left
|
|
929
|
+
// out; a space a closing chip stood after goes too.
|
|
930
|
+
titleBreaks = titleBreaks?.map((i) => i - removedAt.filter((c, k) => c - drop + k < i).length);
|
|
931
|
+
titleLength -= removedAt.length;
|
|
932
|
+
while (chars.length > drop && chars[chars.length - 1] === ' ') {
|
|
933
|
+
chars.pop();
|
|
934
|
+
flags.pop();
|
|
935
|
+
titleLength--;
|
|
861
936
|
}
|
|
937
|
+
// A chip alone on the first line leaves the space its line was
|
|
938
|
+
// broken at (#1162).
|
|
939
|
+
while (chars.length > drop && chars[drop] === ' ') {
|
|
940
|
+
chars.splice(drop, 1);
|
|
941
|
+
flags.splice(drop, 1);
|
|
942
|
+
titleLength--;
|
|
943
|
+
titleBreaks = titleBreaks?.map((i) => Math.max(0, i - 1));
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
const title = chars.join('').slice(drop);
|
|
947
|
+
const titleText = applyTitleBreaks(title, titleBreaks, titleLength);
|
|
948
|
+
// The heading's chips (#1162): the title with them, written as Markdown
|
|
949
|
+
// a design text that reads inline marks sets them from. The plain title
|
|
950
|
+
// leaves them out.
|
|
951
|
+
if (removedAt.length > 0) {
|
|
952
|
+
const marked = markedTitleWithChips(lines, numberPrefix, numberSeparator, keptBreaks, keptLength, titleText);
|
|
953
|
+
if (marked !== undefined)
|
|
954
|
+
return { titleText, marked, chips: true };
|
|
862
955
|
}
|
|
863
|
-
|
|
956
|
+
if (!hasMarks)
|
|
957
|
+
return { titleText };
|
|
958
|
+
const marked = markedTitle(chars.slice(drop), flags.slice(drop), titleBreaks, titleLength, title, titleText);
|
|
959
|
+
return marked === undefined ? { titleText } : { titleText, marked };
|
|
960
|
+
}
|
|
961
|
+
/** {@link DefaultOpenerTitle.marked} of a heading with chips (#1162): its
|
|
962
|
+
* lines read back with each chip kept, the title written with them, when
|
|
963
|
+
* it reads as `titleText` once its chips are left out again. */
|
|
964
|
+
function markedTitleWithChips(lines, numberPrefix, numberSeparator, titleBreaks, titleLength, titleText) {
|
|
965
|
+
const kept = readTitleChars(lines, true);
|
|
966
|
+
if (!kept)
|
|
967
|
+
return undefined;
|
|
968
|
+
const full = kept.chars.join('');
|
|
969
|
+
const drop = numberPrefix && full.startsWith(`${numberPrefix}${numberSeparator}`) ? numberPrefix.length + numberSeparator.length : 0;
|
|
970
|
+
const title = full.slice(drop);
|
|
971
|
+
const withChips = applyTitleBreaks(title, titleBreaks, titleLength);
|
|
972
|
+
if (withoutChips(withChips) !== titleText)
|
|
973
|
+
return undefined;
|
|
974
|
+
// Text written as `:chip[…]` in a code span would read as a chip.
|
|
975
|
+
if (titleText.includes(':chip['))
|
|
976
|
+
return undefined;
|
|
977
|
+
return markedTitle(kept.chars.slice(drop), kept.flags.slice(drop), titleBreaks, titleLength, title, withChips);
|
|
978
|
+
}
|
|
979
|
+
/** The marked title of a heading placeholder (`titleMarked`), with the
|
|
980
|
+
* document's chip styles when it holds the heading's chips (#1162). A
|
|
981
|
+
* title with chips and no styles to set them in is left plain. */
|
|
982
|
+
export function markedTitleFields(title, chipStyles) {
|
|
983
|
+
if (title.marked === undefined)
|
|
984
|
+
return {};
|
|
985
|
+
if (!title.chips)
|
|
986
|
+
return { titleMarked: title.marked };
|
|
987
|
+
return chipStyles ? { titleMarked: title.marked, chipStyles } : {};
|
|
864
988
|
}
|
|
865
989
|
/** The height of the title a page-span heading's default opener paints
|
|
866
990
|
* across `width`, with the opener's own painter (a greedy wrap at natural
|
|
@@ -869,9 +993,11 @@ numberSeparator = ' ') {
|
|
|
869
993
|
* even where the heading's own measure fits more on a line: a justified
|
|
870
994
|
* line whose spaces shrink, a forced break, a run the opener sets plain
|
|
871
995
|
* (EF-100). */
|
|
872
|
-
export function measureDefaultOpenerHeight(level, textAlign, title, numberPrefix, width, dpi, metadata, pageIndex
|
|
996
|
+
export function measureDefaultOpenerHeight(level, textAlign, title, numberPrefix, width, dpi, metadata, pageIndex,
|
|
997
|
+
/** The document's chip styles, for a title with chips (#1162). */
|
|
998
|
+
chipStyles) {
|
|
873
999
|
const slot = synthesiseDefaultOpenerSlot(level, numberPrefix.length > 0, textAlign, title.marked !== undefined);
|
|
874
|
-
const placeholders = headingPlaceholders({ titleText: title.titleText, ...(title
|
|
1000
|
+
const placeholders = headingPlaceholders({ titleText: title.titleText, ...markedTitleFields(title, chipStyles), formattedNumber: numberPrefix }, metadata, pageIndex);
|
|
875
1001
|
const result = layoutDesignSlot(slot, { container: { x: 0, y: 0, width, height: MEASURE_CONTAINER_HEIGHT }, dpi, placeholders }, pageIndex);
|
|
876
1002
|
let bottom = 0;
|
|
877
1003
|
for (const prim of result.primitives) {
|
|
@@ -1033,6 +1159,15 @@ export function framesInFrame(frames, frame) {
|
|
|
1033
1159
|
* (#1057), per document, as `labelAnchorUnknown` warnings with the
|
|
1034
1160
|
* connector's id (read by {@link connectorAnchorUnknownWarnings}). */
|
|
1035
1161
|
const connectorAnchorWarnings = new WeakMap();
|
|
1162
|
+
/** Per document, the furniture each composed page's running heads and
|
|
1163
|
+
* decoration meant to draw (#1163), read by {@link pageFurnitureWarnings}. */
|
|
1164
|
+
const pageFurnitureByDoc = new WeakMap();
|
|
1165
|
+
/** The `folioMissing` warnings of `doc` (#1163): a composed page that draws
|
|
1166
|
+
* no folio or running head most pages of its template and side draw. */
|
|
1167
|
+
export function pageFurnitureWarnings(doc) {
|
|
1168
|
+
const records = pageFurnitureByDoc.get(doc);
|
|
1169
|
+
return records && records.length > 0 ? folioMissingWarnings(doc.pages, records) : [];
|
|
1170
|
+
}
|
|
1036
1171
|
/** The `labelAnchorUnknown` warnings of the connectors of `doc`'s composed
|
|
1037
1172
|
* pages (#1057): an end set at an anchor no picture of its frame has. */
|
|
1038
1173
|
export function connectorAnchorUnknownWarnings(doc) {
|
|
@@ -1100,6 +1235,9 @@ function layoutHeadersAndFooters(doc, resourceById, inputs) {
|
|
|
1100
1235
|
// Parity (odd/even elements) counts the pages before a continued document.
|
|
1101
1236
|
const pageIndexOffset = doc.pageIndexOffset ?? 0;
|
|
1102
1237
|
const chapterAttrsByPageIndex = computeChapterAttrs(doc.blocks, doc.pages.length, doc.pages);
|
|
1238
|
+
/** Per composed page, the furniture its slots mean to draw (#1163). */
|
|
1239
|
+
const furnitureRecords = [];
|
|
1240
|
+
pageFurnitureByDoc.set(doc, furnitureRecords);
|
|
1103
1241
|
// `{bookTotalPages}`: the host's count of the whole book, else the pages
|
|
1104
1242
|
// up to the end of this document.
|
|
1105
1243
|
const bookTotalPages = doc.bookPageCount ?? pageIndexOffset + doc.pages.length;
|
|
@@ -1350,7 +1488,7 @@ function layoutHeadersAndFooters(doc, resourceById, inputs) {
|
|
|
1350
1488
|
partPaletteByPageIndex,
|
|
1351
1489
|
heading: {
|
|
1352
1490
|
titleText: opener.title.titleText,
|
|
1353
|
-
...(
|
|
1491
|
+
...markedTitleFields(opener.title, resolved.chipStyles),
|
|
1354
1492
|
formattedNumber: opener.numberPrefix,
|
|
1355
1493
|
numericValue: opener.block.headingNumber,
|
|
1356
1494
|
locale,
|
|
@@ -1406,9 +1544,10 @@ function layoutHeadersAndFooters(doc, resourceById, inputs) {
|
|
|
1406
1544
|
// The lines joined back into the title (EF-162), with a forced break
|
|
1407
1545
|
// (`\\`) as a newline, as the block's height was measured
|
|
1408
1546
|
// (`build.ts`) and as an opener prints it (EF-152).
|
|
1409
|
-
const
|
|
1547
|
+
const read = own
|
|
1410
1548
|
? defaultOpenerTitle(block.lines, pref, own.titleBreaks, own.titleLength ?? -1, block.numberSeparator)
|
|
1411
1549
|
: defaultOpenerTitle(block.lines, pref, block.titleBreaks, block.titleLength ?? -1, block.numberSeparator);
|
|
1550
|
+
const { titleText: title, marked } = read;
|
|
1412
1551
|
const placeholders = {
|
|
1413
1552
|
kind: 'heading',
|
|
1414
1553
|
page,
|
|
@@ -1425,7 +1564,7 @@ function layoutHeadersAndFooters(doc, resourceById, inputs) {
|
|
|
1425
1564
|
partPaletteByPageIndex,
|
|
1426
1565
|
heading: {
|
|
1427
1566
|
titleText: title,
|
|
1428
|
-
...(
|
|
1567
|
+
...markedTitleFields(read, resolved.chipStyles),
|
|
1429
1568
|
formattedNumber: pref,
|
|
1430
1569
|
numericValue: block.headingNumber,
|
|
1431
1570
|
locale,
|
|
@@ -1545,6 +1684,21 @@ function layoutHeadersAndFooters(doc, resourceById, inputs) {
|
|
|
1545
1684
|
};
|
|
1546
1685
|
page.footer = asFurniture(withMeasureWritingMode('horizontal-tb', () => layoutSlotToVdt(footerSlot, footerContainerBbox(sheetArea, pageMetrics.physical.trimBox), page.index + pageIndexOffset, placeholders, dpi, { ...headExtras, slot: 'footer', ...withPath(slotPath('footer')) })));
|
|
1547
1686
|
}
|
|
1687
|
+
// What the page's running heads and decoration mean to draw on it, for
|
|
1688
|
+
// `folioMissing` (#1163). A spread's decoration is laid on its sheet of
|
|
1689
|
+
// two pages, so only its running heads are compared.
|
|
1690
|
+
if (page.composed && template) {
|
|
1691
|
+
const role = page.composed.role ?? page.role;
|
|
1692
|
+
const at = page.index + pageIndexOffset;
|
|
1693
|
+
const expected = [
|
|
1694
|
+
...(furniture ? expectedFurniture(headerSlot.elements, 'header', at, role, pageAttrs) : []),
|
|
1695
|
+
...(furniture ? expectedFurniture(footerSlot.elements, 'footer', at, role, pageAttrs) : []),
|
|
1696
|
+
...(page.composed.spread === undefined && template.decoration.elements.some((el) => el.kind === 'text')
|
|
1697
|
+
? expectedFurniture(resolveDesignSlot(template.decoration, 'header').elements, 'decoration', at, role, pageAttrs)
|
|
1698
|
+
: []),
|
|
1699
|
+
];
|
|
1700
|
+
furnitureRecords.push({ pageIndex: page.index, template: page.composed.template, side: recto ? 'recto' : 'verso', expected });
|
|
1701
|
+
}
|
|
1548
1702
|
// The template's decoration, laid with the frames' final boxes (its
|
|
1549
1703
|
// elements may anchor to `'#frame'`), on the sheet like the running
|
|
1550
1704
|
// heads; painted under the frames of layer 1 and up. A spread's (#861)
|