postext 1.34.0 → 1.35.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.
Files changed (245) hide show
  1. package/dist/__tests__/bundle.test.js +33 -1
  2. package/dist/__tests__/bundle.test.js.map +1 -1
  3. package/dist/__tests__/codeBlocks.test.js +88 -0
  4. package/dist/__tests__/codeBlocks.test.js.map +1 -1
  5. package/dist/__tests__/composed/fixtures/page8.d.ts +20 -0
  6. package/dist/__tests__/composed/fixtures/page8.d.ts.map +1 -0
  7. package/dist/__tests__/composed/fixtures/page8.js +162 -0
  8. package/dist/__tests__/composed/fixtures/page8.js.map +1 -0
  9. package/dist/__tests__/composed/fixtures/timeline.d.ts +26 -0
  10. package/dist/__tests__/composed/fixtures/timeline.d.ts.map +1 -0
  11. package/dist/__tests__/composed/fixtures/timeline.js +153 -0
  12. package/dist/__tests__/composed/fixtures/timeline.js.map +1 -0
  13. package/dist/__tests__/composed/groups.test.d.ts +2 -0
  14. package/dist/__tests__/composed/groups.test.d.ts.map +1 -0
  15. package/dist/__tests__/composed/groups.test.js +361 -0
  16. package/dist/__tests__/composed/groups.test.js.map +1 -0
  17. package/dist/__tests__/composed/layout.test.d.ts +2 -0
  18. package/dist/__tests__/composed/layout.test.d.ts.map +1 -0
  19. package/dist/__tests__/composed/layout.test.js +387 -0
  20. package/dist/__tests__/composed/layout.test.js.map +1 -0
  21. package/dist/__tests__/composed/outsidePrint.test.d.ts +2 -0
  22. package/dist/__tests__/composed/outsidePrint.test.d.ts.map +1 -0
  23. package/dist/__tests__/composed/outsidePrint.test.js +116 -0
  24. package/dist/__tests__/composed/outsidePrint.test.js.map +1 -0
  25. package/dist/__tests__/composed/slotChecks.test.js +6 -3
  26. package/dist/__tests__/composed/slotChecks.test.js.map +1 -1
  27. package/dist/__tests__/composed/spread.test.d.ts +2 -0
  28. package/dist/__tests__/composed/spread.test.d.ts.map +1 -0
  29. package/dist/__tests__/composed/spread.test.js +475 -0
  30. package/dist/__tests__/composed/spread.test.js.map +1 -0
  31. package/dist/__tests__/composedPaint.test.d.ts +2 -0
  32. package/dist/__tests__/composedPaint.test.d.ts.map +1 -0
  33. package/dist/__tests__/composedPaint.test.js +199 -0
  34. package/dist/__tests__/composedPaint.test.js.map +1 -0
  35. package/dist/__tests__/defaults/stripRoundTrip.test.js +3 -2
  36. package/dist/__tests__/defaults/stripRoundTrip.test.js.map +1 -1
  37. package/dist/__tests__/exports.test.js +25 -0
  38. package/dist/__tests__/exports.test.js.map +1 -1
  39. package/dist/__tests__/highlightMarks.test.d.ts +2 -0
  40. package/dist/__tests__/highlightMarks.test.d.ts.map +1 -0
  41. package/dist/__tests__/highlightMarks.test.js +169 -0
  42. package/dist/__tests__/highlightMarks.test.js.map +1 -0
  43. package/dist/__tests__/tocPartLeader.test.d.ts +2 -0
  44. package/dist/__tests__/tocPartLeader.test.d.ts.map +1 -0
  45. package/dist/__tests__/tocPartLeader.test.js +133 -0
  46. package/dist/__tests__/tocPartLeader.test.js.map +1 -0
  47. package/dist/bundle/api.d.ts +8 -0
  48. package/dist/bundle/api.d.ts.map +1 -1
  49. package/dist/bundle/api.js +6 -3
  50. package/dist/bundle/api.js.map +1 -1
  51. package/dist/bundle/codec.d.ts +5 -0
  52. package/dist/bundle/codec.d.ts.map +1 -1
  53. package/dist/bundle/codec.js +4 -0
  54. package/dist/bundle/codec.js.map +1 -1
  55. package/dist/bundle/index.d.ts +2 -2
  56. package/dist/bundle/index.d.ts.map +1 -1
  57. package/dist/bundle/index.js +1 -1
  58. package/dist/bundle/index.js.map +1 -1
  59. package/dist/bundle/manifest.d.ts +14 -0
  60. package/dist/bundle/manifest.d.ts.map +1 -1
  61. package/dist/bundle/manifest.js +13 -0
  62. package/dist/bundle/manifest.js.map +1 -1
  63. package/dist/bundle/types.d.ts +7 -0
  64. package/dist/bundle/types.d.ts.map +1 -1
  65. package/dist/canvas-backend/annotations.d.ts +6 -0
  66. package/dist/canvas-backend/annotations.d.ts.map +1 -1
  67. package/dist/canvas-backend/annotations.js +39 -0
  68. package/dist/canvas-backend/annotations.js.map +1 -1
  69. package/dist/canvas-backend/blockRender.d.ts.map +1 -1
  70. package/dist/canvas-backend/blockRender.js +6 -1
  71. package/dist/canvas-backend/blockRender.js.map +1 -1
  72. package/dist/canvas-backend/composed.d.ts +19 -0
  73. package/dist/canvas-backend/composed.d.ts.map +1 -0
  74. package/dist/canvas-backend/composed.js +68 -0
  75. package/dist/canvas-backend/composed.js.map +1 -0
  76. package/dist/canvas-backend/index.d.ts.map +1 -1
  77. package/dist/canvas-backend/index.js +15 -1
  78. package/dist/canvas-backend/index.js.map +1 -1
  79. package/dist/canvas-backend/renderResourceBlock.d.ts.map +1 -1
  80. package/dist/canvas-backend/renderResourceBlock.js +4 -1
  81. package/dist/canvas-backend/renderResourceBlock.js.map +1 -1
  82. package/dist/composed/geometry.d.ts +108 -0
  83. package/dist/composed/geometry.d.ts.map +1 -0
  84. package/dist/composed/geometry.js +241 -0
  85. package/dist/composed/geometry.js.map +1 -0
  86. package/dist/composed/groups.d.ts +95 -0
  87. package/dist/composed/groups.d.ts.map +1 -0
  88. package/dist/composed/groups.js +359 -0
  89. package/dist/composed/groups.js.map +1 -0
  90. package/dist/composed/labelText.d.ts +15 -0
  91. package/dist/composed/labelText.d.ts.map +1 -0
  92. package/dist/composed/labelText.js +16 -0
  93. package/dist/composed/labelText.js.map +1 -0
  94. package/dist/composed/paint.d.ts +64 -0
  95. package/dist/composed/paint.d.ts.map +1 -0
  96. package/dist/composed/paint.js +128 -0
  97. package/dist/composed/paint.js.map +1 -0
  98. package/dist/composed/reflowLog.d.ts +39 -0
  99. package/dist/composed/reflowLog.d.ts.map +1 -0
  100. package/dist/composed/reflowLog.js +123 -0
  101. package/dist/composed/reflowLog.js.map +1 -0
  102. package/dist/composed/slotChecks.d.ts +7 -2
  103. package/dist/composed/slotChecks.d.ts.map +1 -1
  104. package/dist/composed/slotChecks.js +21 -0
  105. package/dist/composed/slotChecks.js.map +1 -1
  106. package/dist/composed/spread.d.ts +106 -0
  107. package/dist/composed/spread.d.ts.map +1 -0
  108. package/dist/composed/spread.js +178 -0
  109. package/dist/composed/spread.js.map +1 -0
  110. package/dist/composed/types.d.ts +1 -44
  111. package/dist/composed/types.d.ts.map +1 -1
  112. package/dist/composed/wrap.d.ts +52 -0
  113. package/dist/composed/wrap.d.ts.map +1 -0
  114. package/dist/composed/wrap.js +234 -0
  115. package/dist/composed/wrap.js.map +1 -0
  116. package/dist/configWarnings.js +1 -1
  117. package/dist/configWarnings.js.map +1 -1
  118. package/dist/defaults/codeStyle.d.ts.map +1 -1
  119. package/dist/defaults/codeStyle.js +1 -0
  120. package/dist/defaults/codeStyle.js.map +1 -1
  121. package/dist/defaults/headerFooter.d.ts.map +1 -1
  122. package/dist/defaults/headerFooter.js +4 -0
  123. package/dist/defaults/headerFooter.js.map +1 -1
  124. package/dist/defaults/index.d.ts +1 -0
  125. package/dist/defaults/index.d.ts.map +1 -1
  126. package/dist/defaults/index.js +9 -0
  127. package/dist/defaults/index.js.map +1 -1
  128. package/dist/defaults/markStyles.d.ts +23 -0
  129. package/dist/defaults/markStyles.d.ts.map +1 -0
  130. package/dist/defaults/markStyles.js +80 -0
  131. package/dist/defaults/markStyles.js.map +1 -0
  132. package/dist/defaults/shared.d.ts.map +1 -1
  133. package/dist/defaults/shared.js +12 -0
  134. package/dist/defaults/shared.js.map +1 -1
  135. package/dist/design/bidiText.d.ts +4 -1
  136. package/dist/design/bidiText.d.ts.map +1 -1
  137. package/dist/design/bidiText.js +5 -2
  138. package/dist/design/bidiText.js.map +1 -1
  139. package/dist/design/layout.d.ts +19 -0
  140. package/dist/design/layout.d.ts.map +1 -1
  141. package/dist/design/layout.js +110 -8
  142. package/dist/design/layout.js.map +1 -1
  143. package/dist/design/placeholders.d.ts +28 -2
  144. package/dist/design/placeholders.d.ts.map +1 -1
  145. package/dist/design/placeholders.js +24 -1
  146. package/dist/design/placeholders.js.map +1 -1
  147. package/dist/design/richText.d.ts +2 -0
  148. package/dist/design/richText.d.ts.map +1 -1
  149. package/dist/design/richText.js.map +1 -1
  150. package/dist/highlightMarks.d.ts +33 -0
  151. package/dist/highlightMarks.d.ts.map +1 -0
  152. package/dist/highlightMarks.js +209 -0
  153. package/dist/highlightMarks.js.map +1 -0
  154. package/dist/html-backend.d.ts.map +1 -1
  155. package/dist/html-backend.js +96 -9
  156. package/dist/html-backend.js.map +1 -1
  157. package/dist/htmlAnnotations.d.ts +5 -0
  158. package/dist/htmlAnnotations.d.ts.map +1 -1
  159. package/dist/htmlAnnotations.js +16 -0
  160. package/dist/htmlAnnotations.js.map +1 -1
  161. package/dist/index.d.ts +13 -4
  162. package/dist/index.d.ts.map +1 -1
  163. package/dist/index.js +12 -2
  164. package/dist/index.js.map +1 -1
  165. package/dist/knuthPlass/richAdapter.d.ts +3 -0
  166. package/dist/knuthPlass/richAdapter.d.ts.map +1 -1
  167. package/dist/knuthPlass/richAdapter.js +3 -2
  168. package/dist/knuthPlass/richAdapter.js.map +1 -1
  169. package/dist/measure/cache.js +3 -3
  170. package/dist/measure/cache.js.map +1 -1
  171. package/dist/measure/chipEdges.d.ts +13 -1
  172. package/dist/measure/chipEdges.d.ts.map +1 -1
  173. package/dist/measure/chipEdges.js +59 -1
  174. package/dist/measure/chipEdges.js.map +1 -1
  175. package/dist/measure/links.d.ts.map +1 -1
  176. package/dist/measure/links.js +78 -5
  177. package/dist/measure/links.js.map +1 -1
  178. package/dist/measure/rich.d.ts +3 -0
  179. package/dist/measure/rich.d.ts.map +1 -1
  180. package/dist/measure/rich.js +19 -4
  181. package/dist/measure/rich.js.map +1 -1
  182. package/dist/parse/inlineFormatting.d.ts +14 -0
  183. package/dist/parse/inlineFormatting.d.ts.map +1 -1
  184. package/dist/parse/inlineFormatting.js +104 -5
  185. package/dist/parse/inlineFormatting.js.map +1 -1
  186. package/dist/parse/links.js +1 -1
  187. package/dist/parse/links.js.map +1 -1
  188. package/dist/parse/softBreaks.js +1 -1
  189. package/dist/parse/softBreaks.js.map +1 -1
  190. package/dist/parse/sourceMapping.d.ts.map +1 -1
  191. package/dist/parse/sourceMapping.js +19 -3
  192. package/dist/parse/sourceMapping.js.map +1 -1
  193. package/dist/parse/types.d.ts +24 -0
  194. package/dist/parse/types.d.ts.map +1 -1
  195. package/dist/pipeline/build.d.ts.map +1 -1
  196. package/dist/pipeline/build.js +213 -301
  197. package/dist/pipeline/build.js.map +1 -1
  198. package/dist/pipeline/buildMeasurement.d.ts +4 -1
  199. package/dist/pipeline/buildMeasurement.d.ts.map +1 -1
  200. package/dist/pipeline/buildMeasurement.js +19 -1
  201. package/dist/pipeline/buildMeasurement.js.map +1 -1
  202. package/dist/pipeline/calloutLayout.d.ts +36 -1
  203. package/dist/pipeline/calloutLayout.d.ts.map +1 -1
  204. package/dist/pipeline/calloutLayout.js +93 -3
  205. package/dist/pipeline/calloutLayout.js.map +1 -1
  206. package/dist/pipeline/codeInline.d.ts +10 -1
  207. package/dist/pipeline/codeInline.d.ts.map +1 -1
  208. package/dist/pipeline/codeInline.js +96 -15
  209. package/dist/pipeline/codeInline.js.map +1 -1
  210. package/dist/pipeline/composedLayout.d.ts +93 -0
  211. package/dist/pipeline/composedLayout.d.ts.map +1 -0
  212. package/dist/pipeline/composedLayout.js +520 -0
  213. package/dist/pipeline/composedLayout.js.map +1 -0
  214. package/dist/pipeline/config.d.ts.map +1 -1
  215. package/dist/pipeline/config.js +2 -1
  216. package/dist/pipeline/config.js.map +1 -1
  217. package/dist/pipeline/contentWarnings.d.ts.map +1 -1
  218. package/dist/pipeline/contentWarnings.js +39 -2
  219. package/dist/pipeline/contentWarnings.js.map +1 -1
  220. package/dist/pipeline/floatSlots.js +1 -1
  221. package/dist/pipeline/floatSlots.js.map +1 -1
  222. package/dist/pipeline/frameLayout.d.ts +120 -0
  223. package/dist/pipeline/frameLayout.d.ts.map +1 -0
  224. package/dist/pipeline/frameLayout.js +279 -0
  225. package/dist/pipeline/frameLayout.js.map +1 -0
  226. package/dist/pipeline/headerFooter.d.ts.map +1 -1
  227. package/dist/pipeline/headerFooter.js +96 -3
  228. package/dist/pipeline/headerFooter.js.map +1 -1
  229. package/dist/pipeline/pageRoles.d.ts +1 -0
  230. package/dist/pipeline/pageRoles.d.ts.map +1 -1
  231. package/dist/pipeline/pageRoles.js +3 -0
  232. package/dist/pipeline/pageRoles.js.map +1 -1
  233. package/dist/pipeline/placement.js +1 -1
  234. package/dist/pipeline/placement.js.map +1 -1
  235. package/dist/pipeline/resourceLayout.d.ts.map +1 -1
  236. package/dist/pipeline/resourceLayout.js +5 -3
  237. package/dist/pipeline/resourceLayout.js.map +1 -1
  238. package/dist/pipeline/tabs.js +1 -1
  239. package/dist/pipeline/tabs.js.map +1 -1
  240. package/dist/types.d.ts +89 -3
  241. package/dist/types.d.ts.map +1 -1
  242. package/dist/vdt.d.ts +247 -1
  243. package/dist/vdt.d.ts.map +1 -1
  244. package/dist/vdt.js.map +1 -1
  245. package/package.json +1 -1
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Lay out one composed page (#855, DESIGN §5.1–5.2): place the frames of
3
+ * its template, pour each story (`composed/wrap.ts`) into its frames with
4
+ * the box typesetter (`frameLayout.ts`), and hand back the blocks for the
5
+ * page's floats with the page's `VDTComposedPage`.
6
+ *
7
+ * Per frame, in {@link frameOrder}: its box ({@link placeBox}, an `'auto'`
8
+ * height measured with the content the frame will hold), then its content:
9
+ * the story from where the frame before it in the chain stopped, cut at the
10
+ * frame's foot when a `next` frame takes the rest, else laid whole and
11
+ * clipped at the foot (`frameOverflow`). Text runs round the frames that
12
+ * push it (`exclude: 'push'`) already placed. The groups' negotiation
13
+ * (#856), the reflow ladder (#858) and continuation on other pages (#859)
14
+ * build on this.
15
+ */
16
+ import type { ComposedPageFence, ContentBlock } from '../parse/types';
17
+ import type { ResolvedCalloutStyleConfig } from '../types';
18
+ import type { ContentWarning, VDTBlock, VDTComposedPage, VDTPage } from '../vdt';
19
+ import { dimensionToPx } from '../units';
20
+ import { type FrameAreas, type Rect } from '../composed/geometry';
21
+ import type { ResolvedFrame, ResolvedPageTemplate } from '../composed/types';
22
+ import { type PageTemplateSource } from '../composed/templates';
23
+ import { type PlannedCallout } from './calloutLayout';
24
+ import { type FrameLayoutPass } from './frameLayout';
25
+ /** A story of the page: the box `composed/wrap.ts` made of a chain's
26
+ * content, by the name of the chain's first frame. */
27
+ export interface ComposedStory {
28
+ startIdx: number;
29
+ plan: PlannedCallout;
30
+ }
31
+ export interface ComposedPageInput {
32
+ pass: FrameLayoutPass;
33
+ page: VDTPage;
34
+ template: ResolvedPageTemplate;
35
+ fence: ComposedPageFence;
36
+ /** Content index of the page's opening and closing markers. */
37
+ startIdx: number;
38
+ endIdx: number;
39
+ /** The page's stories by head frame name. */
40
+ stories: ReadonlyMap<string, ComposedStory>;
41
+ /** The style a frame is drawn with: its `style`, or frameless. */
42
+ styleOf(frame: ResolvedFrame): ResolvedCalloutStyleConfig;
43
+ areas: FrameAreas;
44
+ dpi: number;
45
+ emPx: number;
46
+ /** Source offset of the body in the chapter file. */
47
+ bodyOffset: number;
48
+ /** The page swaps its mirrored margins (an `'outer'` corner icon). */
49
+ mirrored: boolean;
50
+ /** The gap text keeps from a frame that pushes it. */
51
+ pushGapPx: number;
52
+ /** The box a frame takes given the one its placement gives: on a spread
53
+ * (#861, `composed/spread.ts`), off the spine band unless the frame
54
+ * crosses the gutter. An `'auto'` height is measured at the width it
55
+ * returns. */
56
+ fitBox?: (frame: ResolvedFrame, rect: Rect) => Rect;
57
+ }
58
+ export interface ComposedPageLayout {
59
+ composed: VDTComposedPage;
60
+ /** Frame boxes and their content, in paint-independent page order (each
61
+ * frame's box first): for `page.floats` and `doc.blocks`. */
62
+ blocks: VDTBlock[];
63
+ warnings: ContentWarning[];
64
+ /** Story heads laid in a frame of this page. A story left out (its frame
65
+ * is missing on this side) is set in the flow after the page. */
66
+ laid: Set<string>;
67
+ }
68
+ export declare function layoutComposedPage(input: ComposedPageInput): ComposedPageLayout;
69
+ /** The callout style a frame is drawn with: `base` (its `style`, or the
70
+ * frameless frame style) with what a frame sets of its own: its padding
71
+ * (side by side) and a measure that is the frame's. A style's placement,
72
+ * span, width and margins do not apply to a frame. */
73
+ export declare function frameStyleOf(base: ResolvedCalloutStyleConfig, frame: ResolvedFrame): ResolvedCalloutStyleConfig;
74
+ /** The story heads of a composed page's stories, by the head frame's
75
+ * name, read from the boxes `wrapComposedPages` made (`FRAME_ATTR`). */
76
+ export declare function composedStories(startIdx: number, endIdx: number, plans: ReadonlyMap<number, PlannedCallout>): Map<string, ComposedStory>;
77
+ /** `d` in px, 0 when unset. */
78
+ export declare function lengthPx(d: Parameters<typeof dimensionToPx>[0] | undefined, dpi: number, emPx: number): number;
79
+ /** A composed page of the pass whose template is known: its markers and
80
+ * its stories. */
81
+ export interface PlannedComposedPage {
82
+ startIdx: number;
83
+ endIdx: number;
84
+ stories: Map<string, ComposedStory>;
85
+ /** The story box holding block `idx`, if any. */
86
+ storyAt(idx: number): ComposedStory | undefined;
87
+ }
88
+ /** The composed pages of `blocks` whose template `source` has, by their
89
+ * opening marker's index. */
90
+ export declare function planComposedPages(blocks: readonly ContentBlock[], plans: ReadonlyMap<number, PlannedCallout>, source: PageTemplateSource): Map<number, PlannedComposedPage>;
91
+ /** The planned composed page whose markers enclose block `idx`. */
92
+ export declare function composedPageAt(pages: ReadonlyMap<number, PlannedComposedPage>, idx: number): PlannedComposedPage | undefined;
93
+ //# sourceMappingURL=composedLayout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composedLayout.d.ts","sourceRoot":"","sources":["../../src/pipeline/composedLayout.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,520 @@
1
+ import { dimensionToPx } from '../units';
2
+ import { frameBounds } from '../composed/paint';
3
+ import { FRAME_ATTR } from '../composed/wrap';
4
+ import { framePlaceable, nextFrameOf, groupPlaceable, placeBox, unionRect } from '../composed/geometry';
5
+ import { composedOrder, groupOfFrames, layoutGroup } from '../composed/groups';
6
+ import { reflowEvents } from '../composed/reflowLog';
7
+ import { anchorTarget } from '../composed/templates';
8
+ import { resolvePageTemplate } from '../composed/templates';
9
+ import { offsetCalloutToAbsolute } from './calloutLayout';
10
+ import { CUT_START, fragmentRange, makeCalloutLayouter, splitCalloutFragment } from './frameLayout';
11
+ const MM_PER_IN = 25.4;
12
+ export function layoutComposedPage(input) {
13
+ const { pass, page, template, fence, dpi } = input;
14
+ const fi = fence.fenceIndex;
15
+ const frameIdOf = (name) => `cp${fi}:${name}`;
16
+ const byName = new Map(template.frames.map((f) => [f.name, f]));
17
+ const prev = new Map();
18
+ for (const f of template.frames) {
19
+ const n = nextFrameOf(f);
20
+ if (n && byName.has(n) && !prev.has(n))
21
+ prev.set(n, f.name);
22
+ }
23
+ /** The head of the chain a frame belongs to. */
24
+ const headOf = (name) => {
25
+ let at = name;
26
+ const seen = new Set([at]);
27
+ for (let p = prev.get(at); p !== undefined && !seen.has(p); p = prev.get(at)) {
28
+ seen.add(p);
29
+ at = p;
30
+ }
31
+ return at;
32
+ };
33
+ /** Place and fill every frame. `seed`: the boxes of the frames that push
34
+ * text, from a first run, so a frame placed before one that pushes it
35
+ * (the photo anchored to its box) still runs round it. */
36
+ const run = (seed) => {
37
+ const pushRects = new Map();
38
+ const states = new Map();
39
+ const stateOf = (frame) => {
40
+ const head = headOf(frame.name);
41
+ const known = states.get(head);
42
+ if (known)
43
+ return known;
44
+ const story = input.stories.get(head);
45
+ const headFrame = byName.get(head);
46
+ if (!story || !headFrame)
47
+ return undefined;
48
+ const st = {
49
+ story,
50
+ L: makeCalloutLayouter(pass, story.startIdx, story.plan, input.styleOf(frame)),
51
+ cut: CUT_START,
52
+ pieces: 0,
53
+ headBlockId: frameIdOf(head),
54
+ headFrameId: frameIdOf(head),
55
+ };
56
+ states.set(head, st);
57
+ return st;
58
+ };
59
+ const atEnd = (st) => st.cut.child >= st.L.end.child && st.cut.line === 0 && !st.cut.group;
60
+ /** The frames' boxes as laid, and as the template declares them. */
61
+ const rects = new Map();
62
+ const declared = new Map();
63
+ /** Groups' boxes once their step is laid. */
64
+ const groupRects = new Map();
65
+ const groupDeclared = new Map();
66
+ const groupRect = (name, boxes, solved, refs) => {
67
+ const done = solved.get(name);
68
+ if (done)
69
+ return done;
70
+ const g = template.groups.find((gr) => gr.name === name);
71
+ if (!g)
72
+ return undefined;
73
+ const own = groupPlaceable(g);
74
+ if (own)
75
+ return placeBox(own, template, input, refs, () => 0);
76
+ return unionRect(g.frames.flatMap((m) => (boxes.has(m) ? [boxes.get(m)] : [])));
77
+ };
78
+ const refOf = (name) => rects.get(name) ?? groupRect(name, rects, groupRects, refOf);
79
+ const declaredRefOf = (name) => declared.get(name) ?? groupRect(name, declared, groupDeclared, declaredRefOf);
80
+ /** Pinned frames laid so far: a group's frames flow round them. */
81
+ const pinned = [];
82
+ const frames = [];
83
+ const vdtByName = new Map();
84
+ const blocks = [];
85
+ const warnings = [];
86
+ const overflowLog = [];
87
+ const laid = new Set();
88
+ const pushed = seed ? [...seed].map(([name, box]) => ({ name, box })) : [];
89
+ /** The rectangles of the pushing frames placed so far that `rect`
90
+ * meets, in the frame block's coordinates. */
91
+ const exclusionsFor = (frame, rect, open) => {
92
+ const out = [];
93
+ const g = input.pushGapPx;
94
+ for (const p of pushed) {
95
+ if (p.name === frame.name)
96
+ continue;
97
+ const b = p.box;
98
+ const below = open ? true : b.y < rect.y + rect.height;
99
+ if (b.x - g >= rect.x + rect.width || b.x + b.width + g <= rect.x || !below || b.y + b.height + g <= rect.y)
100
+ continue;
101
+ out.push({ x: b.x - g - rect.x, y: b.y - g - rect.y, width: b.width + 2 * g, height: b.height + 2 * g });
102
+ }
103
+ return out.length > 0 ? out : undefined;
104
+ };
105
+ const prepare = (frame) => {
106
+ const st = stateOf(frame);
107
+ // Each frame of a chain sets the story in its own style: the cuts are
108
+ // positions in the story's blocks, the same in any.
109
+ if (st)
110
+ st.L = makeCalloutLayouter(pass, st.story.startIdx, st.story.plan, input.styleOf(frame));
111
+ // A frame continues its story only once the frame before it in the
112
+ // chain was filled (a frame placed before it, through an anchor, starts
113
+ // empty).
114
+ const before = prev.get(frame.name);
115
+ const reached = st !== undefined && (before === undefined || vdtByName.has(before));
116
+ const holds = reached && !atEnd(st);
117
+ const continuation = st !== undefined && st.pieces > 0;
118
+ const blockId = st && st.pieces > 0 ? `${st.headBlockId}-cont-${st.pieces}` : frameIdOf(frame.name);
119
+ return { frame, st, before, holds, continuation, blockId };
120
+ };
121
+ /** The content's height at `width`, running round the pushing frames
122
+ * below the top of `at` (the frame's box as first placed). */
123
+ const naturalOf = (p, at) => {
124
+ const memo = new Map();
125
+ return (width) => {
126
+ if (!p.holds)
127
+ return 0;
128
+ const key = Math.round(width * 1000);
129
+ const known = memo.get(key);
130
+ if (known !== undefined)
131
+ return known;
132
+ const exclusions = at ? exclusionsFor(p.frame, { ...at, width }, true) : undefined;
133
+ const r = p.st.L.layoutRange(p.st.cut, p.st.L.end, width, p.blockId, p.continuation, input.mirrored, exclusions ? { exclusions } : undefined);
134
+ memo.set(key, r.totalHeight);
135
+ return r.totalHeight;
136
+ };
137
+ };
138
+ /** `placeBox`, then the box the page lets the frame take (`fitBox`:
139
+ * off a spread's spine band, #861), its `'auto'` height measured at the
140
+ * width it is left with. Declared and final boxes alike: the band is
141
+ * the template's, not a reflow. */
142
+ const placeFitted = (frame, placeable, ctx, refs, nat) => {
143
+ const r = placeBox(placeable, template, ctx, refs, nat);
144
+ if (!input.fitBox)
145
+ return r;
146
+ const fitted = input.fitBox(frame, r);
147
+ if (Math.abs(fitted.width - r.width) < 0.01)
148
+ return fitted;
149
+ return input.fitBox(frame, placeBox(placeable, template, ctx, refs, () => nat(fitted.width)));
150
+ };
151
+ /** A frame's height as its template declares it: its `minHeight` where
152
+ * the height follows the content, else the content's (`natural`). */
153
+ const declaredNatural = (frame, natural) => (width) => (frame.minHeight ? 0 : natural(width));
154
+ /** Place a frame outside any group: its box, placed with the content's
155
+ * own height, then again with the height it takes running round the
156
+ * frames that push it there; a pinned frame where the template puts
157
+ * it. */
158
+ const placeFrame = (p) => {
159
+ const frame = p.frame;
160
+ const placeable = framePlaceable(frame);
161
+ const natural = naturalOf(p);
162
+ const at = (refs) => {
163
+ const r0 = placeFitted(frame, placeable, input, refs, natural);
164
+ if (!p.holds || !exclusionsFor(frame, r0, true))
165
+ return { rect: r0, natural };
166
+ const round = naturalOf(p, r0);
167
+ return { rect: placeFitted(frame, placeable, input, refs, round), natural: round };
168
+ };
169
+ const decl = frame.pin ? at(declaredRefOf) : undefined;
170
+ const fin = decl ?? at(refOf);
171
+ const declRect = placeFitted(frame, placeable, input, declaredRefOf, declaredNatural(frame, fin.natural));
172
+ const rect = frame.pin ? declRect : fin.rect;
173
+ declared.set(frame.name, declRect);
174
+ rects.set(frame.name, rect);
175
+ if (frame.pin)
176
+ pinned.push({ name: frame.name, rect });
177
+ return rect;
178
+ };
179
+ /** Lay a group: its frames' boxes as the template declares them and as
180
+ * their content needs (`composed/groups.ts`). */
181
+ const placeGroup = (group, members) => {
182
+ const own = groupPlaceable(group);
183
+ const mmPx = dpi / MM_PER_IN;
184
+ const preps = members.map(prepare);
185
+ const solve = (mode, naturals) => {
186
+ const refs = mode === 'final' ? refOf : declaredRefOf;
187
+ const ownBox = own ? placeBox(own, template, input, refs, () => 0) : undefined;
188
+ const ownRects = new Map();
189
+ const memberRefs = (n) => ownRects.get(n) ?? (n === group.name ? ownBox : refs(n));
190
+ const items = members.map((f, k) => {
191
+ // A frame placed nowhere stands in its group's box.
192
+ const ctx = ownBox && !f.placement && !f.grid ? { ...input, areas: { ...input.areas, area: ownBox } } : input;
193
+ const natural = naturals[k];
194
+ const placeable = framePlaceable(f);
195
+ // On a spread the member's own box keeps off the spine band, and
196
+ // the negotiation starts from it (#861).
197
+ const box = placeFitted(f, placeable, ctx, memberRefs, declaredNatural(f, natural));
198
+ ownRects.set(f.name, box);
199
+ const auto = f.height === 'auto' && !(f.grid && !placeable.heightSet);
200
+ const fill = f.height === 'fill';
201
+ const minH = f.minHeight ? dimensionToPx(f.minHeight, dpi, input.emPx) : 0;
202
+ const want = fill ? minH : auto ? (mode === 'final' ? natural(box.width) : declaredNatural(f, natural)(box.width)) : box.height;
203
+ return {
204
+ name: f.name,
205
+ own: box,
206
+ want,
207
+ min: minH,
208
+ max: f.maxHeight ? dimensionToPx(f.maxHeight, dpi, input.emPx) : Infinity,
209
+ minWidth: f.minWidth ? dimensionToPx(f.minWidth, dpi, input.emPx) : 0,
210
+ maxWidth: f.maxWidth ? dimensionToPx(f.maxWidth, dpi, input.emPx) : Infinity,
211
+ grow: fill ? Math.max(1, f.grow) : f.grow,
212
+ shrink: f.shrink,
213
+ priority: f.priority,
214
+ pin: f.pin,
215
+ fixedHeight: !auto && !fill,
216
+ need: natural,
217
+ };
218
+ });
219
+ const firstFree = items.find((it) => !it.pin) ?? items[0];
220
+ const start = firstFree?.own ?? input.areas.area;
221
+ const box = ownBox ?? { x: start.x, y: start.y, width: 0, height: 0 };
222
+ const out = layoutGroup({
223
+ kind: group.kind,
224
+ box,
225
+ elastic: !ownBox,
226
+ limit: input.areas.area,
227
+ gap: dimensionToPx(group.gap, dpi, input.emPx),
228
+ align: group.align,
229
+ items,
230
+ obstacles: pinned.filter((q) => !members.some((m) => m.name === q.name)).map((q) => q.rect),
231
+ mmPx,
232
+ negotiate: mode === 'final',
233
+ });
234
+ // A pinned frame of the group stands where the template puts it.
235
+ for (const it of items)
236
+ if (it.pin)
237
+ out.set(it.name, it.own);
238
+ return { rects: out, box: ownBox ?? unionRect([...out.values()]) ?? box };
239
+ };
240
+ let naturals = preps.map((p) => naturalOf(p));
241
+ let fin = solve('final', naturals);
242
+ // Text that runs round a pushing frame is taller: measured at the box
243
+ // first found, then laid again.
244
+ const round = preps.map((p) => (p.holds && exclusionsFor(p.frame, fin.rects.get(p.frame.name), true) ? naturalOf(p, fin.rects.get(p.frame.name)) : undefined));
245
+ if (round.some((r) => r !== undefined)) {
246
+ naturals = naturals.map((n, k) => round[k] ?? n);
247
+ fin = solve('final', naturals);
248
+ }
249
+ const decl = solve('declared', naturals);
250
+ for (const m of members) {
251
+ rects.set(m.name, fin.rects.get(m.name));
252
+ declared.set(m.name, decl.rects.get(m.name));
253
+ if (m.pin)
254
+ pinned.push({ name: m.name, rect: fin.rects.get(m.name) });
255
+ }
256
+ groupRects.set(group.name, fin.box);
257
+ groupDeclared.set(group.name, decl.box);
258
+ return fin.rects;
259
+ };
260
+ /** Pour a frame's content into its box and record the frame. */
261
+ const fill = (p, rect) => {
262
+ const { frame, st, holds, continuation, blockId, before } = p;
263
+ const style = input.styleOf(frame);
264
+ let result;
265
+ let overflowPx = 0;
266
+ const from = st?.cut ?? CUT_START;
267
+ if (holds) {
268
+ const opts = {
269
+ boxHeight: rect.height,
270
+ verticalAlign: frame.verticalAlign,
271
+ ...(exclusionsFor(frame, rect, false) ? { exclusions: exclusionsFor(frame, rect, false) } : {}),
272
+ };
273
+ const whole = st.L.layoutRange(from, st.L.end, rect.width, blockId, continuation, input.mirrored, opts);
274
+ const nextName = nextFrameOf(frame);
275
+ const nextFrame = nextName !== undefined ? byName.get(nextName) : undefined;
276
+ if ((whole.overflowPx ?? 0) > 0.5 && nextFrame && !vdtByName.has(nextFrame.name)) {
277
+ // The rest goes on in the next frame of the chain.
278
+ const minLines = Math.max(1, style.splitMinLines);
279
+ const frag = splitCalloutFragment(pass, st.L, from, rect.width, rect.height, blockId, continuation, minLines, input.mirrored, opts.exclusions ? { exclusions: opts.exclusions } : undefined);
280
+ const to = frag?.to ?? from;
281
+ result = frag
282
+ ? st.L.layoutRange(from, to, rect.width, blockId, continuation, input.mirrored, opts)
283
+ : undefined;
284
+ st.cut = to;
285
+ }
286
+ else {
287
+ result = whole;
288
+ overflowPx = whole.overflowPx ?? 0;
289
+ st.cut = st.L.end;
290
+ }
291
+ }
292
+ else if (st && frame.style) {
293
+ // A styled frame with nothing (left) to hold still draws its box.
294
+ result = st.L.layoutRange(st.L.end, st.L.end, rect.width, blockId, true, input.mirrored, { boxHeight: rect.height });
295
+ }
296
+ const vdt = {
297
+ id: frameIdOf(frame.name),
298
+ name: frame.name,
299
+ rect: { ...rect },
300
+ rotate: frame.rotate,
301
+ layer: frame.layer,
302
+ ...(frame.style ? { styleId: frame.style } : {}),
303
+ scale: 1,
304
+ overflowPx,
305
+ blockIds: [],
306
+ configPath: frame.configPath,
307
+ ...(frame.exclude === 'push' ? { push: true } : {}),
308
+ };
309
+ const decl = declared.get(frame.name);
310
+ if (decl && !sameRect(decl, rect))
311
+ vdt.declaredRect = { ...decl };
312
+ if (before && vdtByName.has(before) && st && st.lastFrameId) {
313
+ vdt.continuedFrom = st.lastFrameId;
314
+ const q = frames.find((f) => f.id === st.lastFrameId);
315
+ if (q)
316
+ q.continuesTo = vdt.id;
317
+ }
318
+ if (result && st) {
319
+ const range = fragmentRange(st.L, from, st.cut);
320
+ commitFrame(result, rect, st.story, range, input, vdt, blocks);
321
+ st.pieces++;
322
+ st.lastFrameId = vdt.id;
323
+ laid.add(headOf(frame.name));
324
+ }
325
+ if (overflowPx > 0.5) {
326
+ const overflowMm = Math.round((overflowPx / dpi) * MM_PER_IN * 10) / 10;
327
+ overflowLog.push({ frame: frame.name, kind: 'overflow', toMm: overflowMm });
328
+ warnings.push({
329
+ kind: 'frameOverflow',
330
+ template: template.id,
331
+ frame: frame.name,
332
+ fenceIndex: fi,
333
+ overflowMm,
334
+ configPath: frame.configPath,
335
+ ...(vdt.sourceStart !== undefined ? { sourceStart: vdt.sourceStart, sourceEnd: vdt.sourceEnd } : {}),
336
+ pageIndex: page.index,
337
+ });
338
+ }
339
+ if (frame.exclude === 'push') {
340
+ const box = frameBounds({ rect, rotate: frame.rotate });
341
+ pushRects.set(frame.name, box);
342
+ if (!seed)
343
+ pushed.push({ name: frame.name, box });
344
+ }
345
+ frames.push(vdt);
346
+ vdtByName.set(frame.name, vdt);
347
+ };
348
+ for (const step of composedOrder(template)) {
349
+ if (step.kind === 'frame') {
350
+ const p = prepare(step.frame);
351
+ fill(p, placeFrame(p));
352
+ continue;
353
+ }
354
+ const solved = placeGroup(step.group, step.frames);
355
+ // A frame of a chain inside the group is reached once the frame
356
+ // before it was filled: each is prepared again as it is filled.
357
+ for (const f of step.frames)
358
+ fill(prepare(f), solved.get(f.name));
359
+ }
360
+ const log = mergeLog(reflowEvents(motionsOf(template, rects, declared), dpi / MM_PER_IN), overflowLog, template);
361
+ return { frames, blocks, warnings, log, laid, pushRects };
362
+ };
363
+ const first = run();
364
+ const { frames, blocks, warnings, log, laid } = first.pushRects.size > 0 ? run(first.pushRects) : first;
365
+ // Template order on the page record.
366
+ const order = new Map(template.frames.map((f, i) => [f.name, i]));
367
+ frames.sort((a, b) => order.get(a.name) - order.get(b.name));
368
+ const contentBlocks = pass.contentBlocks;
369
+ const composed = {
370
+ template: template.id,
371
+ ...(template.variant ? { variant: template.variant } : {}),
372
+ fenceIndex: fi,
373
+ role: template.role,
374
+ attrs: { ...fence.attrs },
375
+ attrSources: Object.fromEntries(Object.entries(fence.attrSources).map(([k, v]) => [k, { sourceStart: v.sourceStart + input.bodyOffset, sourceEnd: v.sourceEnd + input.bodyOffset }])),
376
+ frames,
377
+ log,
378
+ configPath: template.configPath,
379
+ sourceStart: contentBlocks[input.startIdx].sourceStart + input.bodyOffset,
380
+ sourceEnd: contentBlocks[input.endIdx].sourceEnd + input.bodyOffset,
381
+ };
382
+ return { composed, blocks, warnings, laid };
383
+ }
384
+ const sameRect = (a, b) => Math.abs(a.x - b.x) < 0.01 && Math.abs(a.y - b.y) < 0.01 && Math.abs(a.width - b.width) < 0.01 && Math.abs(a.height - b.height) < 0.01;
385
+ /** Each laid frame's declared and final boxes, in template order, with
386
+ * what moves it: what it anchors to (a group: its frames, last first),
387
+ * then, in a group, the frames before it (nearest first), what the group
388
+ * anchors to, and the frames after it. */
389
+ function motionsOf(template, rects, declared) {
390
+ const groupOf = groupOfFrames(template);
391
+ const groups = new Map(template.groups.map((g) => [g.name, g]));
392
+ const expand = (target) => {
393
+ if (!target)
394
+ return [];
395
+ const g = groups.get(target);
396
+ return g && !rects.has(target) ? [...g.frames].reverse() : [target];
397
+ };
398
+ const out = [];
399
+ for (const f of template.frames) {
400
+ const fin = rects.get(f.name);
401
+ const decl = declared.get(f.name);
402
+ if (!fin || !decl)
403
+ continue;
404
+ const deps = f.grid ? [] : expand(anchorTarget(f.placement));
405
+ const g = groupOf.get(f.name);
406
+ if (g) {
407
+ const k = g.frames.indexOf(f.name);
408
+ deps.push(...g.frames.slice(0, k).reverse());
409
+ if (!g.grid)
410
+ deps.push(...expand(anchorTarget(g.placement)));
411
+ deps.push(...g.frames.slice(k + 1));
412
+ }
413
+ out.push({ name: f.name, declared: decl, final: fin, deps });
414
+ }
415
+ return out;
416
+ }
417
+ /** The page's log: each frame's events in template order, what groups and
418
+ * anchors changed first, then its overflow. */
419
+ function mergeLog(reflow, overflow, template) {
420
+ const order = new Map(template.frames.map((f, i) => [f.name, i]));
421
+ const all = [...reflow.map((e, i) => ({ e, i })), ...overflow.map((e, i) => ({ e, i: reflow.length + i }))];
422
+ all.sort((a, b) => (order.get(a.e.frame) ?? 0) - (order.get(b.e.frame) ?? 0) || a.i - b.i);
423
+ return all.map((x) => x.e);
424
+ }
425
+ /** Stamp a frame's laid-out box with its source and page, move it to the
426
+ * frame's place and add it (box first) to `out` and to the frame's ids. */
427
+ function commitFrame(result, rect, story, range, input, vdt, out) {
428
+ const { pass, page, bodyOffset } = input;
429
+ const blocks = pass.contentBlocks;
430
+ const box = result.frame;
431
+ box.contentIndex = story.startIdx;
432
+ const first = blocks[Math.max(story.startIdx + 1, Math.min(range.firstChildIdx, story.plan.endIdx - 1))];
433
+ const last = blocks[Math.max(story.startIdx + 1, Math.min(range.lastChildIdx, story.plan.endIdx - 1))];
434
+ if (first && last && range.lastChildIdx >= range.firstChildIdx) {
435
+ box.sourceStart = first.sourceStart + bodyOffset;
436
+ box.sourceEnd = last.sourceEnd + bodyOffset;
437
+ vdt.sourceStart = box.sourceStart;
438
+ vdt.sourceEnd = box.sourceEnd;
439
+ }
440
+ box.pageIndex = page.index;
441
+ box.columnIndex = 0;
442
+ offsetCalloutToAbsolute(result, rect.x, rect.y);
443
+ out.push(box);
444
+ vdt.blockIds.push(box.id);
445
+ for (const child of result.children) {
446
+ child.pageIndex = page.index;
447
+ child.columnIndex = 0;
448
+ out.push(child);
449
+ vdt.blockIds.push(child.id);
450
+ }
451
+ }
452
+ /** The callout style a frame is drawn with: `base` (its `style`, or the
453
+ * frameless frame style) with what a frame sets of its own: its padding
454
+ * (side by side) and a measure that is the frame's. A style's placement,
455
+ * span, width and margins do not apply to a frame. */
456
+ export function frameStyleOf(base, frame) {
457
+ const padding = frame.padding ? { ...base.padding, ...frame.padding } : base.padding;
458
+ return {
459
+ ...base,
460
+ padding,
461
+ width: 'fill',
462
+ placement: 'here',
463
+ span: 'column',
464
+ marginTop: { value: 0, unit: 'px' },
465
+ marginBottom: { value: 0, unit: 'px' },
466
+ };
467
+ }
468
+ /** The story heads of a composed page's stories, by the head frame's
469
+ * name, read from the boxes `wrapComposedPages` made (`FRAME_ATTR`). */
470
+ export function composedStories(startIdx, endIdx, plans) {
471
+ const out = new Map();
472
+ for (let i = startIdx + 1; i < endIdx; i++) {
473
+ const plan = plans.get(i);
474
+ if (!plan)
475
+ continue;
476
+ const head = plan.attrs[FRAME_ATTR];
477
+ if (head !== undefined && !out.has(head))
478
+ out.set(head, { startIdx: i, plan });
479
+ i = plan.endIdx;
480
+ }
481
+ return out;
482
+ }
483
+ /** `d` in px, 0 when unset. */
484
+ export function lengthPx(d, dpi, emPx) {
485
+ return d ? dimensionToPx(d, dpi, emPx) : 0;
486
+ }
487
+ /** The composed pages of `blocks` whose template `source` has, by their
488
+ * opening marker's index. */
489
+ export function planComposedPages(blocks, plans, source) {
490
+ const out = new Map();
491
+ for (let i = 0; i < blocks.length; i++) {
492
+ const b = blocks[i];
493
+ if (b.type !== 'containerStart' || b.containerName !== 'composedPage' || !b.composedPage)
494
+ continue;
495
+ let end = i + 1;
496
+ while (end < blocks.length && !(blocks[end].type === 'containerEnd' && blocks[end].containerId === b.containerId))
497
+ end++;
498
+ end = Math.min(end, blocks.length - 1);
499
+ if (resolvePageTemplate(source, b.composedPage.template)) {
500
+ const stories = composedStories(i, end, plans);
501
+ const list = [...stories.values()];
502
+ out.set(i, {
503
+ startIdx: i,
504
+ endIdx: end,
505
+ stories,
506
+ storyAt: (idx) => list.find((s) => idx > s.startIdx && idx < s.plan.endIdx),
507
+ });
508
+ }
509
+ i = end;
510
+ }
511
+ return out;
512
+ }
513
+ /** The planned composed page whose markers enclose block `idx`. */
514
+ export function composedPageAt(pages, idx) {
515
+ for (const p of pages.values())
516
+ if (idx > p.startIdx && idx < p.endIdx)
517
+ return p;
518
+ return undefined;
519
+ }
520
+ //# sourceMappingURL=composedLayout.js.map