postext 1.46.4 → 1.48.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__/bundle/designOverflowPin.test.js +1 -1
- package/dist/__tests__/bundle/gridBreakRulesPin.test.js +2 -2
- package/dist/__tests__/bundle/shapingLanguagePin.test.js +3 -3
- package/dist/__tests__/bundle/taskBoxPin.test.js +1 -1
- package/dist/__tests__/bundle.test.js +1 -1
- package/dist/__tests__/codeBlocks.test.js +1 -1
- package/dist/__tests__/comics/config.test.js +20 -0
- package/dist/__tests__/comics/config.test.js.map +1 -1
- package/dist/__tests__/composed/cardShapes.test.d.ts +2 -0
- package/dist/__tests__/composed/cardShapes.test.d.ts.map +1 -0
- package/dist/__tests__/composed/cardShapes.test.js +82 -0
- package/dist/__tests__/composed/cardShapes.test.js.map +1 -0
- package/dist/__tests__/composed/connectors.test.d.ts +2 -0
- package/dist/__tests__/composed/connectors.test.d.ts.map +1 -0
- package/dist/__tests__/composed/connectors.test.js +349 -0
- package/dist/__tests__/composed/connectors.test.js.map +1 -0
- package/dist/__tests__/composed/decorationSidePoints.test.d.ts +2 -0
- package/dist/__tests__/composed/decorationSidePoints.test.d.ts.map +1 -0
- package/dist/__tests__/composed/decorationSidePoints.test.js +164 -0
- package/dist/__tests__/composed/decorationSidePoints.test.js.map +1 -0
- package/dist/__tests__/composed/fit.test.js +2 -1
- package/dist/__tests__/composed/fit.test.js.map +1 -1
- package/dist/__tests__/composed/fixtures/connectors.d.ts +33 -0
- package/dist/__tests__/composed/fixtures/connectors.d.ts.map +1 -0
- package/dist/__tests__/composed/fixtures/connectors.js +142 -0
- package/dist/__tests__/composed/fixtures/connectors.js.map +1 -0
- package/dist/__tests__/composed/fixtures/grid.d.ts +32 -0
- package/dist/__tests__/composed/fixtures/grid.d.ts.map +1 -0
- package/dist/__tests__/composed/fixtures/grid.js +53 -0
- package/dist/__tests__/composed/fixtures/grid.js.map +1 -0
- package/dist/__tests__/composed/fixtures/legendMap.d.ts +24 -0
- package/dist/__tests__/composed/fixtures/legendMap.d.ts.map +1 -0
- package/dist/__tests__/composed/fixtures/legendMap.js +117 -0
- package/dist/__tests__/composed/fixtures/legendMap.js.map +1 -0
- package/dist/__tests__/composed/fixtures/mapParts.d.ts +58 -0
- package/dist/__tests__/composed/fixtures/mapParts.d.ts.map +1 -0
- package/dist/__tests__/composed/fixtures/mapParts.js +192 -0
- package/dist/__tests__/composed/fixtures/mapParts.js.map +1 -0
- package/dist/__tests__/composed/fixtures/modules.d.ts +55 -0
- package/dist/__tests__/composed/fixtures/modules.d.ts.map +1 -0
- package/dist/__tests__/composed/fixtures/modules.js +123 -0
- package/dist/__tests__/composed/fixtures/modules.js.map +1 -0
- package/dist/__tests__/composed/grid.test.d.ts +2 -0
- package/dist/__tests__/composed/grid.test.d.ts.map +1 -0
- package/dist/__tests__/composed/grid.test.js +357 -0
- package/dist/__tests__/composed/grid.test.js.map +1 -0
- package/dist/__tests__/composed/groups.test.js +6 -3
- package/dist/__tests__/composed/groups.test.js.map +1 -1
- package/dist/__tests__/composed/labelLegend.test.d.ts +2 -0
- package/dist/__tests__/composed/labelLegend.test.d.ts.map +1 -0
- package/dist/__tests__/composed/labelLegend.test.js +268 -0
- package/dist/__tests__/composed/labelLegend.test.js.map +1 -0
- package/dist/__tests__/composed/labelsChecks.test.js.map +1 -1
- package/dist/__tests__/composed/leaders.test.d.ts +2 -0
- package/dist/__tests__/composed/leaders.test.d.ts.map +1 -0
- package/dist/__tests__/composed/leaders.test.js +372 -0
- package/dist/__tests__/composed/leaders.test.js.map +1 -0
- package/dist/__tests__/composed/modules.test.d.ts +2 -0
- package/dist/__tests__/composed/modules.test.d.ts.map +1 -0
- package/dist/__tests__/composed/modules.test.js +352 -0
- package/dist/__tests__/composed/modules.test.js.map +1 -0
- package/dist/__tests__/composed/overConnectors.test.d.ts +2 -0
- package/dist/__tests__/composed/overConnectors.test.d.ts.map +1 -0
- package/dist/__tests__/composed/overConnectors.test.js +232 -0
- package/dist/__tests__/composed/overConnectors.test.js.map +1 -0
- package/dist/__tests__/composed/overlap.test.d.ts +2 -0
- package/dist/__tests__/composed/overlap.test.d.ts.map +1 -0
- package/dist/__tests__/composed/overlap.test.js +339 -0
- package/dist/__tests__/composed/overlap.test.js.map +1 -0
- package/dist/__tests__/composed/viewerLeaf.test.d.ts +2 -0
- package/dist/__tests__/composed/viewerLeaf.test.d.ts.map +1 -0
- package/dist/__tests__/composed/viewerLeaf.test.js +106 -0
- package/dist/__tests__/composed/viewerLeaf.test.js.map +1 -0
- package/dist/__tests__/composedTemplates.test.js +1 -1
- package/dist/__tests__/design/boxShape.test.d.ts +2 -0
- package/dist/__tests__/design/boxShape.test.d.ts.map +1 -0
- package/dist/__tests__/design/boxShape.test.js +126 -0
- package/dist/__tests__/design/boxShape.test.js.map +1 -0
- package/dist/__tests__/design/boxShapePaint.test.d.ts +2 -0
- package/dist/__tests__/design/boxShapePaint.test.d.ts.map +1 -0
- package/dist/__tests__/design/boxShapePaint.test.js +130 -0
- package/dist/__tests__/design/boxShapePaint.test.js.map +1 -0
- package/dist/__tests__/design/openerBottomAnchor.test.js.map +1 -1
- package/dist/__tests__/design/pathBlock.test.d.ts +2 -0
- package/dist/__tests__/design/pathBlock.test.d.ts.map +1 -0
- package/dist/__tests__/design/pathBlock.test.js +194 -0
- package/dist/__tests__/design/pathBlock.test.js.map +1 -0
- package/dist/__tests__/design/pathElement.test.d.ts +2 -0
- package/dist/__tests__/design/pathElement.test.d.ts.map +1 -0
- package/dist/__tests__/design/pathElement.test.js +257 -0
- package/dist/__tests__/design/pathElement.test.js.map +1 -0
- package/dist/__tests__/design/svgPath.test.d.ts +2 -0
- package/dist/__tests__/design/svgPath.test.d.ts.map +1 -0
- package/dist/__tests__/design/svgPath.test.js +144 -0
- package/dist/__tests__/design/svgPath.test.js.map +1 -0
- package/dist/__tests__/exports.test.js +53 -0
- package/dist/__tests__/exports.test.js.map +1 -1
- package/dist/__tests__/fontUsage.test.js +46 -0
- package/dist/__tests__/fontUsage.test.js.map +1 -1
- package/dist/__tests__/hardBreaks.test.js +1 -1
- package/dist/__tests__/headingInlineMarks.test.js +1 -1
- package/dist/__tests__/labelGlyphPaint.test.d.ts +2 -0
- package/dist/__tests__/labelGlyphPaint.test.d.ts.map +1 -0
- package/dist/__tests__/labelGlyphPaint.test.js +86 -0
- package/dist/__tests__/labelGlyphPaint.test.js.map +1 -0
- package/dist/__tests__/mathSizeMigration.test.js +2 -2
- package/dist/__tests__/migrate/labelsOnPictures.test.js +1 -1
- package/dist/__tests__/migrate/labelsOnPictures.test.js.map +1 -1
- package/dist/__tests__/parse/containers.test.js +1 -1
- package/dist/__tests__/parse/containers.test.js.map +1 -1
- package/dist/__tests__/pipeline/calloutInlineResourceGap.test.js +1 -1
- package/dist/__tests__/pipeline/calloutLabelGlyph.test.d.ts +2 -0
- package/dist/__tests__/pipeline/calloutLabelGlyph.test.d.ts.map +1 -0
- package/dist/__tests__/pipeline/calloutLabelGlyph.test.js +198 -0
- package/dist/__tests__/pipeline/calloutLabelGlyph.test.js.map +1 -0
- package/dist/__tests__/pipeline/calloutShapes.test.d.ts +2 -0
- package/dist/__tests__/pipeline/calloutShapes.test.d.ts.map +1 -0
- package/dist/__tests__/pipeline/calloutShapes.test.js +159 -0
- package/dist/__tests__/pipeline/calloutShapes.test.js.map +1 -0
- package/dist/__tests__/pipeline/calloutSplitMinLinesChild.test.js +1 -1
- package/dist/__tests__/pipeline/colonListRoom.test.js +1 -1
- package/dist/__tests__/pipeline/compoundBreaks.test.js +1 -1
- package/dist/__tests__/pipeline/dashBreaks.test.js +1 -1
- package/dist/__tests__/pipeline/headingSplitOrphans.test.js +1 -1
- package/dist/__tests__/pipeline/inlineFigureSpace.test.js +1 -1
- package/dist/__tests__/pipeline/paragraphContainerTail.test.js +1 -1
- package/dist/__tests__/pipeline/raggedOptimal.test.js +1 -1
- package/dist/__tests__/prepareFonts.test.js +8 -6
- package/dist/__tests__/prepareFonts.test.js.map +1 -1
- package/dist/__tests__/verseLines.test.js +1 -1
- package/dist/bundle/configVersion.d.ts +12 -3
- package/dist/bundle/configVersion.d.ts.map +1 -1
- package/dist/bundle/configVersion.js +16 -5
- package/dist/bundle/configVersion.js.map +1 -1
- package/dist/canvas-backend/blockRender.js +3 -3
- package/dist/canvas-backend/blockRender.js.map +1 -1
- package/dist/canvas-backend/composed.d.ts +4 -2
- package/dist/canvas-backend/composed.d.ts.map +1 -1
- package/dist/canvas-backend/composed.js +12 -7
- package/dist/canvas-backend/composed.js.map +1 -1
- package/dist/canvas-backend/headerFooter.d.ts +17 -1
- package/dist/canvas-backend/headerFooter.d.ts.map +1 -1
- package/dist/canvas-backend/headerFooter.js +64 -1
- package/dist/canvas-backend/headerFooter.js.map +1 -1
- package/dist/canvas-backend/index.d.ts.map +1 -1
- package/dist/canvas-backend/index.js +7 -1
- package/dist/canvas-backend/index.js.map +1 -1
- package/dist/canvas-backend/renderResourceBlock.d.ts.map +1 -1
- package/dist/canvas-backend/renderResourceBlock.js +17 -6
- package/dist/canvas-backend/renderResourceBlock.js.map +1 -1
- package/dist/canvas-backend/swatch.d.ts +20 -1
- package/dist/canvas-backend/swatch.d.ts.map +1 -1
- package/dist/canvas-backend/swatch.js +51 -1
- package/dist/canvas-backend/swatch.js.map +1 -1
- package/dist/comics/fonts.d.ts +19 -0
- package/dist/comics/fonts.d.ts.map +1 -1
- package/dist/comics/fonts.js +70 -17
- package/dist/comics/fonts.js.map +1 -1
- package/dist/comics/layoutPage.d.ts.map +1 -1
- package/dist/comics/layoutPage.js +6 -1
- package/dist/comics/layoutPage.js.map +1 -1
- package/dist/composed/continuation.d.ts +10 -2
- package/dist/composed/continuation.d.ts.map +1 -1
- package/dist/composed/continuation.js +10 -2
- package/dist/composed/continuation.js.map +1 -1
- package/dist/composed/document.d.ts +45 -1
- package/dist/composed/document.d.ts.map +1 -1
- package/dist/composed/document.js +76 -17
- package/dist/composed/document.js.map +1 -1
- package/dist/composed/labelText.d.ts +9 -1
- package/dist/composed/labelText.d.ts.map +1 -1
- package/dist/composed/labelText.js +23 -1
- package/dist/composed/labelText.js.map +1 -1
- package/dist/composed/labels.d.ts +57 -3
- package/dist/composed/labels.d.ts.map +1 -1
- package/dist/composed/labels.js +261 -12
- package/dist/composed/labels.js.map +1 -1
- package/dist/composed/modules.d.ts +30 -0
- package/dist/composed/modules.d.ts.map +1 -0
- package/dist/composed/modules.js +194 -0
- package/dist/composed/modules.js.map +1 -0
- package/dist/composed/overlap.d.ts +52 -0
- package/dist/composed/overlap.d.ts.map +1 -0
- package/dist/composed/overlap.js +611 -0
- package/dist/composed/overlap.js.map +1 -0
- package/dist/composed/paint.d.ts +28 -5
- package/dist/composed/paint.d.ts.map +1 -1
- package/dist/composed/paint.js +26 -5
- package/dist/composed/paint.js.map +1 -1
- package/dist/composed/reflowLog.d.ts +6 -1
- package/dist/composed/reflowLog.d.ts.map +1 -1
- package/dist/composed/reflowLog.js +43 -0
- package/dist/composed/reflowLog.js.map +1 -1
- package/dist/composed/repeat.d.ts +66 -0
- package/dist/composed/repeat.d.ts.map +1 -0
- package/dist/composed/repeat.js +217 -0
- package/dist/composed/repeat.js.map +1 -0
- package/dist/composed/slotChecks.d.ts +1 -1
- package/dist/composed/slotChecks.d.ts.map +1 -1
- package/dist/composed/slotChecks.js +114 -8
- package/dist/composed/slotChecks.js.map +1 -1
- package/dist/composed/sourceMap.d.ts.map +1 -1
- package/dist/composed/sourceMap.js +16 -4
- package/dist/composed/sourceMap.js.map +1 -1
- package/dist/composed/spread.d.ts.map +1 -1
- package/dist/composed/spread.js +6 -2
- package/dist/composed/spread.js.map +1 -1
- package/dist/composed/templates.d.ts +22 -2
- package/dist/composed/templates.d.ts.map +1 -1
- package/dist/composed/templates.js +159 -9
- package/dist/composed/templates.js.map +1 -1
- package/dist/composed/types.d.ts +140 -7
- package/dist/composed/types.d.ts.map +1 -1
- package/dist/composed/validate.d.ts +1 -1
- package/dist/composed/validate.d.ts.map +1 -1
- package/dist/composed/validate.js +101 -4
- package/dist/composed/validate.js.map +1 -1
- package/dist/composed/wrap.d.ts.map +1 -1
- package/dist/composed/wrap.js +95 -17
- package/dist/composed/wrap.js.map +1 -1
- package/dist/configWarnings.d.ts +7 -1
- package/dist/configWarnings.d.ts.map +1 -1
- package/dist/configWarnings.js +275 -4
- package/dist/configWarnings.js.map +1 -1
- package/dist/contrast.d.ts.map +1 -1
- package/dist/contrast.js +8 -0
- package/dist/contrast.js.map +1 -1
- package/dist/defaults/calloutStyles.d.ts +10 -1
- package/dist/defaults/calloutStyles.d.ts.map +1 -1
- package/dist/defaults/calloutStyles.js +46 -7
- package/dist/defaults/calloutStyles.js.map +1 -1
- package/dist/defaults/comics.d.ts +2 -1
- package/dist/defaults/comics.d.ts.map +1 -1
- package/dist/defaults/comics.js +18 -3
- package/dist/defaults/comics.js.map +1 -1
- package/dist/defaults/headerFooter.d.ts.map +1 -1
- package/dist/defaults/headerFooter.js +38 -0
- package/dist/defaults/headerFooter.js.map +1 -1
- package/dist/design/boxShape.d.ts +101 -0
- package/dist/design/boxShape.d.ts.map +1 -0
- package/dist/design/boxShape.js +398 -0
- package/dist/design/boxShape.js.map +1 -0
- package/dist/design/connector.d.ts +75 -0
- package/dist/design/connector.d.ts.map +1 -0
- package/dist/design/connector.js +325 -0
- package/dist/design/connector.js.map +1 -0
- package/dist/design/layout.d.ts +56 -3
- package/dist/design/layout.d.ts.map +1 -1
- package/dist/design/layout.js +214 -12
- package/dist/design/layout.js.map +1 -1
- package/dist/design/logicalEdges.d.ts +7 -0
- package/dist/design/logicalEdges.d.ts.map +1 -1
- package/dist/design/logicalEdges.js +28 -0
- package/dist/design/logicalEdges.js.map +1 -1
- package/dist/design/pathBlock.d.ts +69 -0
- package/dist/design/pathBlock.d.ts.map +1 -0
- package/dist/design/pathBlock.js +286 -0
- package/dist/design/pathBlock.js.map +1 -0
- package/dist/design/svgPath.d.ts +48 -0
- package/dist/design/svgPath.d.ts.map +1 -0
- package/dist/design/svgPath.js +402 -0
- package/dist/design/svgPath.js.map +1 -0
- package/dist/fonts/usage.d.ts +5 -0
- package/dist/fonts/usage.d.ts.map +1 -1
- package/dist/fonts/usage.js +81 -11
- package/dist/fonts/usage.js.map +1 -1
- package/dist/html-backend.d.ts.map +1 -1
- package/dist/html-backend.js +127 -22
- package/dist/html-backend.js.map +1 -1
- package/dist/index.d.ts +19 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -5
- package/dist/index.js.map +1 -1
- package/dist/measure/cache.js +1 -1
- package/dist/measure/cache.js.map +1 -1
- package/dist/measure/inlineIcon.d.ts +34 -0
- package/dist/measure/inlineIcon.d.ts.map +1 -0
- package/dist/measure/inlineIcon.js +89 -0
- package/dist/measure/inlineIcon.js.map +1 -0
- package/dist/measure/rich.d.ts +2 -1
- package/dist/measure/rich.d.ts.map +1 -1
- package/dist/measure/rich.js +6 -0
- package/dist/measure/rich.js.map +1 -1
- package/dist/migrate/pageDesign.d.ts.map +1 -1
- package/dist/migrate/pageDesign.js +4 -2
- package/dist/migrate/pageDesign.js.map +1 -1
- package/dist/migrate/textToMarkdown.js +2 -0
- package/dist/migrate/textToMarkdown.js.map +1 -1
- package/dist/parse/blockParser.d.ts.map +1 -1
- package/dist/parse/blockParser.js +171 -20
- package/dist/parse/blockParser.js.map +1 -1
- package/dist/parse/index.d.ts +1 -1
- package/dist/parse/index.d.ts.map +1 -1
- package/dist/parse/index.js.map +1 -1
- package/dist/parse/inlineFormatting.d.ts +11 -3
- package/dist/parse/inlineFormatting.d.ts.map +1 -1
- package/dist/parse/inlineFormatting.js +63 -5
- package/dist/parse/inlineFormatting.js.map +1 -1
- package/dist/parse/inlineSnippet.d.ts +2 -1
- package/dist/parse/inlineSnippet.d.ts.map +1 -1
- package/dist/parse/inlineSnippet.js +3 -2
- package/dist/parse/inlineSnippet.js.map +1 -1
- package/dist/parse/sourceMapping.d.ts.map +1 -1
- package/dist/parse/sourceMapping.js +8 -1
- package/dist/parse/sourceMapping.js.map +1 -1
- package/dist/parse/types.d.ts +71 -1
- package/dist/parse/types.d.ts.map +1 -1
- package/dist/pipeline/build.d.ts.map +1 -1
- package/dist/pipeline/build.js +67 -13
- package/dist/pipeline/build.js.map +1 -1
- package/dist/pipeline/buildHelpers.d.ts +10 -0
- package/dist/pipeline/buildHelpers.d.ts.map +1 -1
- package/dist/pipeline/buildHelpers.js +17 -0
- package/dist/pipeline/buildHelpers.js.map +1 -1
- package/dist/pipeline/buildMeasurement.d.ts.map +1 -1
- package/dist/pipeline/buildMeasurement.js +23 -11
- package/dist/pipeline/buildMeasurement.js.map +1 -1
- package/dist/pipeline/calloutLayout.d.ts.map +1 -1
- package/dist/pipeline/calloutLayout.js +142 -32
- package/dist/pipeline/calloutLayout.js.map +1 -1
- package/dist/pipeline/composedLayout.d.ts +1 -33
- package/dist/pipeline/composedLayout.d.ts.map +1 -1
- package/dist/pipeline/composedLayout.js +526 -36
- package/dist/pipeline/composedLayout.js.map +1 -1
- package/dist/pipeline/config.d.ts.map +1 -1
- package/dist/pipeline/config.js +12 -0
- package/dist/pipeline/config.js.map +1 -1
- package/dist/pipeline/contentWarnings.d.ts.map +1 -1
- package/dist/pipeline/contentWarnings.js +46 -1
- package/dist/pipeline/contentWarnings.js.map +1 -1
- package/dist/pipeline/continuation.d.ts.map +1 -1
- package/dist/pipeline/continuation.js +3 -2
- package/dist/pipeline/continuation.js.map +1 -1
- package/dist/pipeline/headerFooter.d.ts +19 -1
- package/dist/pipeline/headerFooter.d.ts.map +1 -1
- package/dist/pipeline/headerFooter.js +169 -17
- package/dist/pipeline/headerFooter.js.map +1 -1
- package/dist/pipeline/partPalette.d.ts.map +1 -1
- package/dist/pipeline/partPalette.js +40 -1
- package/dist/pipeline/partPalette.js.map +1 -1
- package/dist/pipeline/resourceLayout.d.ts +1 -1
- package/dist/pipeline/resourceLayout.d.ts.map +1 -1
- package/dist/pipeline/resourceLayout.js +44 -15
- package/dist/pipeline/resourceLayout.js.map +1 -1
- package/dist/preflight.d.ts.map +1 -1
- package/dist/preflight.js +36 -1
- package/dist/preflight.js.map +1 -1
- package/dist/types.d.ts +319 -22
- package/dist/types.d.ts.map +1 -1
- package/dist/vdt.d.ts +392 -12
- package/dist/vdt.d.ts.map +1 -1
- package/dist/vdt.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,3 +1,36 @@
|
|
|
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. Text runs round the frames that push it (`exclude:
|
|
12
|
+
* 'push'`) already placed; groups negotiate their frames' space (#856).
|
|
13
|
+
*
|
|
14
|
+
* A frame whose content still does not fit climbs the reflow ladder (#858,
|
|
15
|
+
* DESIGN §5.4), frame by frame in template order, each step on top of the
|
|
16
|
+
* ones before it, stopping at the first that makes it fit: free space (a
|
|
17
|
+
* fixed height grows to its `maxHeight`), its group pushing and yielding
|
|
18
|
+
* (already part of every layout), smaller pictures in the frame and its
|
|
19
|
+
* group (`fit.imageMinScale`), the group's other frames down to their
|
|
20
|
+
* minimum or their content, smaller text (`fit.minScale`), continuation on
|
|
21
|
+
* another page (#859). Each step lays the whole page again, so a change
|
|
22
|
+
* stays on the page. What still does not fit is clipped and reported
|
|
23
|
+
* (`frameOverflow`) with the steps tried and proposals worked out on the
|
|
24
|
+
* page.
|
|
25
|
+
*
|
|
26
|
+
* A frame whose `overflow.continueIn` sends content to another page
|
|
27
|
+
* (`'next-page'`, `'template:<id>'`, #859) takes the ladder's last step
|
|
28
|
+
* before the warning: it is cut at its foot, with its mark, its text and
|
|
29
|
+
* pictures back at full size, and the rest is handed back
|
|
30
|
+
* (`ComposedPageLayout.continuations`) for `build.ts` to lay on pages it
|
|
31
|
+
* adds after this one, with this function (`ComposedPageInput.continuing`).
|
|
32
|
+
*/
|
|
33
|
+
import { isCornerRadii } from '../design/boxShape';
|
|
1
34
|
import { pageIsMirrored, pageIsVertical } from '../vdt';
|
|
2
35
|
import { contourBounds, scaleContourAbout, shiftContour } from '../contour';
|
|
3
36
|
import { frameContour } from '../composed/contour';
|
|
@@ -8,11 +41,14 @@ import { chainHead, FRAME_ATTR } from '../composed/wrap';
|
|
|
8
41
|
import { framePlaceable, nextFrameOf, groupPlaceable, placeBox, unionRect } from '../composed/geometry';
|
|
9
42
|
import { composedOrder, groupOfFrames, layoutGroup } from '../composed/groups';
|
|
10
43
|
import { reflowEvents } from '../composed/reflowLog';
|
|
11
|
-
import { anchorTarget, resolveContinueIn } from '../composed/templates';
|
|
44
|
+
import { anchorTarget, repeatInstance, repeatedFrames, resolveContinueIn } from '../composed/templates';
|
|
12
45
|
import { collapsedOnAddedPage, collapseFrames, continuationTemplate, continuesCollapsed, continuesOffPage, trailingFrames } from '../composed/continuation';
|
|
13
|
-
import { resolvePageTemplate } from '../composed/templates';
|
|
46
|
+
import { isModuleTemplate, resolvePageTemplate } from '../composed/templates';
|
|
14
47
|
import { frameElementId } from '../composed/ids';
|
|
48
|
+
import { expandRepeats, instanceOf, repeatItemsOf } from '../composed/repeat';
|
|
49
|
+
import { moduleOfFrame } from '../composed/modules';
|
|
15
50
|
import { frameLinePx, frameRuleBlocks } from '../composed/rules';
|
|
51
|
+
import { overlapChecks } from '../composed/overlap';
|
|
16
52
|
import { offsetCalloutToAbsolute } from './calloutLayout';
|
|
17
53
|
import { isMarkerBlock } from './buildHelpers';
|
|
18
54
|
import { createLayoutMemo, layoutMemoSwitch } from './layoutMemo';
|
|
@@ -21,7 +57,7 @@ import { computeOrderedListRunMetrics } from './lists';
|
|
|
21
57
|
import { planParagraphContainers } from './paragraphContainers';
|
|
22
58
|
import { CUT_START, fragmentRange, frameCutRules, makeCalloutLayouter, partBreakCut, splitCalloutFragment } from './frameLayout';
|
|
23
59
|
const MM_PER_IN = 25.4;
|
|
24
|
-
const NO_FIT = { patches: new Map(), text: new Map(), pictures: new Map(), yieldAll: new Set(), goOn: new Set() };
|
|
60
|
+
const NO_FIT = { patches: new Map(), text: new Map(), pictures: new Map(), yieldAll: new Set(), goOn: new Set(), gridsOn: new Set() };
|
|
25
61
|
/** Step of the text and picture scales the ladder tries (DESIGN §5.4). */
|
|
26
62
|
const FIT_STEP = 0.025;
|
|
27
63
|
/** Lowest text scale an `allowShrink` proposal goes to. */
|
|
@@ -66,7 +102,12 @@ function chainPrev(template, receivers) {
|
|
|
66
102
|
return prev;
|
|
67
103
|
}
|
|
68
104
|
const sameCut = (a, b) => a.child === b.child && a.line === b.line && JSON.stringify(a.group ?? null) === JSON.stringify(b.group ?? null);
|
|
69
|
-
export function layoutComposedPage(
|
|
105
|
+
export function layoutComposedPage(asked) {
|
|
106
|
+
// The grids that repeat a frame set (#1061) are laid with one instance of
|
|
107
|
+
// the set per item the page's stories hold (`<frame>[n]`): from here on
|
|
108
|
+
// they are plain frames.
|
|
109
|
+
const expanded = expandRepeats(asked.template, repeatItemsOf(asked.template, asked.stories.keys()));
|
|
110
|
+
const given = expanded === asked.template ? asked : { ...asked, template: expanded };
|
|
70
111
|
// A page added by continuation (#859) lays its template with the
|
|
71
112
|
// continuation's rules (and, for the template laid again, its other
|
|
72
113
|
// frames collapsed).
|
|
@@ -78,7 +119,9 @@ export function layoutComposedPage(given) {
|
|
|
78
119
|
const fi = fence.fenceIndex;
|
|
79
120
|
const mmPx = dpi / MM_PER_IN;
|
|
80
121
|
const byName = new Map(template.frames.map((f) => [f.name, f]));
|
|
81
|
-
|
|
122
|
+
// (A modules group, #1062, holds its modules' frames to lay them as one
|
|
123
|
+
// step: what a frame shares room with is the group of its own module.)
|
|
124
|
+
const groupOf = groupOfFrames({ ...template, groups: template.groups.filter((g) => !g.modules) });
|
|
82
125
|
const prev = chainPrev(template, input.continuing?.receivers);
|
|
83
126
|
const headOf = (name) => {
|
|
84
127
|
let at = name;
|
|
@@ -89,11 +132,17 @@ export function layoutComposedPage(given) {
|
|
|
89
132
|
}
|
|
90
133
|
return at;
|
|
91
134
|
};
|
|
135
|
+
/** The module a frame belongs to (#1062), when its modules group goes on
|
|
136
|
+
* by whole modules (`overflow.continueIn` off the page). */
|
|
137
|
+
const movingModule = (name) => {
|
|
138
|
+
const m = moduleOfFrame(template, name);
|
|
139
|
+
return m && !input.continuing?.last && continuesOffPage(m.group.overflow?.continueIn) ? m : undefined;
|
|
140
|
+
};
|
|
92
141
|
// Compositions by fit state: the ladder and its proposals ask for some
|
|
93
142
|
// twice.
|
|
94
143
|
const memo = new Map();
|
|
95
144
|
let runs = 0;
|
|
96
|
-
const keyOf = (tpl, fit) => JSON.stringify([tpl.id, [...fit.patches], [...fit.text], [...fit.pictures], [...fit.yieldAll], [...fit.goOn]]);
|
|
145
|
+
const keyOf = (tpl, fit) => JSON.stringify([tpl.id, [...fit.patches], [...fit.text], [...fit.pictures], [...fit.yieldAll], [...fit.goOn], [...fit.gridsOn]]);
|
|
97
146
|
/** Frames a page added by continuation lays with no room (#859). */
|
|
98
147
|
const collapsedHere = input.continuing ? collapsedOnAddedPage(given.template, input.continuing) : new Set();
|
|
99
148
|
const holdsStory = (name) => input.stories.has(headOf(name));
|
|
@@ -234,9 +283,18 @@ export function layoutComposedPage(given) {
|
|
|
234
283
|
};
|
|
235
284
|
/** Story heads of the frame and of its group's frames whose content holds
|
|
236
285
|
* a picture. */
|
|
286
|
+
/** The frames a frame shares its group's room with: its group's, or for
|
|
287
|
+
* an instance of a grid's set (#1061) its own item's. */
|
|
288
|
+
const peersOf = (name) => {
|
|
289
|
+
const inst = instanceOf(template, name);
|
|
290
|
+
if (inst)
|
|
291
|
+
return inst.group.items.find((c) => c.item === inst.item).frames;
|
|
292
|
+
// A module's frame (#1062) outside a group of its own: its module's.
|
|
293
|
+
return groupOf.get(name)?.frames ?? moduleOfFrame(template, name)?.frames;
|
|
294
|
+
};
|
|
237
295
|
const pictureHeads = (frame) => {
|
|
238
|
-
const
|
|
239
|
-
const names =
|
|
296
|
+
const peers = peersOf(frame.name);
|
|
297
|
+
const names = peers ? [frame.name, ...peers.filter((m) => m !== frame.name)] : [frame.name];
|
|
240
298
|
const heads = [];
|
|
241
299
|
for (const n of names) {
|
|
242
300
|
const head = headOf(n);
|
|
@@ -266,8 +324,8 @@ export function layoutComposedPage(given) {
|
|
|
266
324
|
return false;
|
|
267
325
|
};
|
|
268
326
|
const movesOthers = (frame) => {
|
|
269
|
-
const
|
|
270
|
-
if (
|
|
327
|
+
const peers = peersOf(frame.name);
|
|
328
|
+
if (peers && peers.filter((m) => byName.has(m)).length > 1)
|
|
271
329
|
return true;
|
|
272
330
|
return template.frames.some((f) => f.name !== frame.name && !f.grid && anchorTarget(f.placement) === frame.name);
|
|
273
331
|
};
|
|
@@ -309,7 +367,8 @@ export function layoutComposedPage(given) {
|
|
|
309
367
|
// width) back, down to its minimum or its content.
|
|
310
368
|
const redistribute = () => {
|
|
311
369
|
const g = groupOf.get(name);
|
|
312
|
-
|
|
370
|
+
// (A grid's rows are as tall as their tallest cell: nothing to give.)
|
|
371
|
+
if (!g || g.kind === 'grid' || g.frames.filter((m) => byName.has(m)).length <= 1)
|
|
313
372
|
return false;
|
|
314
373
|
steps.push('redistribute');
|
|
315
374
|
return attempt({ ...fit, yieldAll: new Set([...fit.yieldAll, g.name]) }, name);
|
|
@@ -325,15 +384,26 @@ export function layoutComposedPage(given) {
|
|
|
325
384
|
// `'template:<id>'` or `'page:<id>'`, #859). On a page added by
|
|
326
385
|
// continuation, a frame that would take none of what it receives
|
|
327
386
|
// sends nothing on (it would go on for ever): it warns.
|
|
387
|
+
// An instance of a grid's set (#1061) goes on with its whole row, as
|
|
388
|
+
// the grid's main frame says (`overflow.continueIn`, `fit`).
|
|
389
|
+
// A frame of a module (#1062) whose modules group goes on goes on with
|
|
390
|
+
// its whole module, as the group says.
|
|
391
|
+
const moving = movingModule(name);
|
|
392
|
+
const grid = moving ? undefined : instanceOf(template, name)?.group;
|
|
393
|
+
const ruler = moving
|
|
394
|
+
? { ...frame, overflow: { ...frame.overflow, continueIn: moving.group.overflow.continueIn } }
|
|
395
|
+
: grid ? byName.get(grid.items[0].frames[0]) ?? frame : frame;
|
|
328
396
|
const goOn = () => {
|
|
329
|
-
if (!continuesOffPage(
|
|
397
|
+
if (!continuesOffPage(ruler.overflow.continueIn))
|
|
330
398
|
return false;
|
|
331
399
|
steps.push('continue');
|
|
332
400
|
const before = { fit, cur };
|
|
333
401
|
// (Only for a story that came from another page: a page's own story
|
|
334
402
|
// may go on whole.)
|
|
335
403
|
const received = input.continuing?.receivers.has(headOf(name)) ?? false;
|
|
336
|
-
|
|
404
|
+
const wholeIn = moving?.group ?? grid;
|
|
405
|
+
const next = wholeIn ? { ...fit, gridsOn: new Set([...fit.gridsOn, wholeIn.name]) } : goingOn(fit, frame);
|
|
406
|
+
if (attempt(next, name) && (!received || cur.spills.get(name)?.advanced !== false))
|
|
337
407
|
return true;
|
|
338
408
|
({ fit, cur } = before);
|
|
339
409
|
return false;
|
|
@@ -343,7 +413,7 @@ export function layoutComposedPage(given) {
|
|
|
343
413
|
// one size from page to page. The pictures and the text shrink only
|
|
344
414
|
// when it cannot go on (the last page continuation may add, or a
|
|
345
415
|
// receiver that takes none of it).
|
|
346
|
-
const order = continuesOffPage(
|
|
416
|
+
const order = continuesOffPage(ruler.overflow.continueIn) && ruler.fit.preferContinue
|
|
347
417
|
? [redistribute, goOn, scaleImages, shrinkText]
|
|
348
418
|
: [scaleImages, redistribute, shrinkText, goOn];
|
|
349
419
|
for (const step of order)
|
|
@@ -353,10 +423,21 @@ export function layoutComposedPage(given) {
|
|
|
353
423
|
// 7. Warn, with what would make each frame that still overflows fit.
|
|
354
424
|
const warnings = [...(cur.notes ?? [])];
|
|
355
425
|
const templateAttr = fence.attrSources.template;
|
|
426
|
+
// The rows of a grid cut at its foot (#1061) warn once, on the last
|
|
427
|
+
// instance cut.
|
|
428
|
+
// (And so do the modules cut at the foot of their group, #1062.)
|
|
429
|
+
const cutIn = (name) => moduleOfFrame(template, name)?.group.name ?? instanceOf(template, name)?.group.name ?? '';
|
|
430
|
+
const lastCut = new Map();
|
|
431
|
+
for (const frame of template.frames) {
|
|
432
|
+
if (cur.clipped.has(frame.name) && overflows(cur, frame.name))
|
|
433
|
+
lastCut.set(cutIn(frame.name), frame.name);
|
|
434
|
+
}
|
|
356
435
|
for (const frame of template.frames) {
|
|
357
436
|
const vdt = frameIn(cur, frame.name);
|
|
358
437
|
if (!vdt || vdt.overflowPx <= 0.5)
|
|
359
438
|
continue;
|
|
439
|
+
if (cur.clipped.has(frame.name) && lastCut.get(cutIn(frame.name)) !== frame.name)
|
|
440
|
+
continue;
|
|
360
441
|
const overflowMm = Math.round((vdt.overflowPx / mmPx) * 10) / 10;
|
|
361
442
|
const proposals = overflowProposals({
|
|
362
443
|
frame,
|
|
@@ -396,7 +477,23 @@ export function layoutComposedPage(given) {
|
|
|
396
477
|
pageIndex: input.page.index,
|
|
397
478
|
});
|
|
398
479
|
}
|
|
399
|
-
|
|
480
|
+
// 8. What no frame's box says (#1053): ink under a frame painted over it,
|
|
481
|
+
// and ink past the trim, the bleed or the box it is anchored inside.
|
|
482
|
+
const overlaps = overlapChecks({
|
|
483
|
+
template: cur.template,
|
|
484
|
+
frames: cur.frames,
|
|
485
|
+
blocks: cur.blocks,
|
|
486
|
+
groupRects: cur.groupRects,
|
|
487
|
+
areas: input.areas,
|
|
488
|
+
dpi,
|
|
489
|
+
emPx: input.emPx,
|
|
490
|
+
fenceIndex: fi,
|
|
491
|
+
pageIndex: input.page.index,
|
|
492
|
+
...(input.locale ? { locale: input.locale } : {}),
|
|
493
|
+
});
|
|
494
|
+
warnings.push(...overlaps.warnings);
|
|
495
|
+
const { frames, blocks, laid, fitted } = cur;
|
|
496
|
+
const log = overlaps.events.length > 0 ? mergeLog(cur.log, overlaps.events, template) : cur.log;
|
|
400
497
|
// Template order on the page record.
|
|
401
498
|
const order = new Map(template.frames.map((f, i) => [f.name, i]));
|
|
402
499
|
frames.sort((a, b) => order.get(a.name) - order.get(b.name));
|
|
@@ -411,6 +508,10 @@ export function layoutComposedPage(given) {
|
|
|
411
508
|
frames,
|
|
412
509
|
log,
|
|
413
510
|
configPath: template.configPath,
|
|
511
|
+
// The modules laid (#1062), each with its box.
|
|
512
|
+
...(template.modules && template.modules.length > 0
|
|
513
|
+
? { modules: template.modules.map((m) => ({ name: m.name, template: m.template, configPath: m.configPath, ...(cur.moduleRects.has(m.name) ? { rect: { ...cur.moduleRects.get(m.name) } } : {}) })) }
|
|
514
|
+
: {}),
|
|
414
515
|
sourceStart: contentBlocks[input.startIdx].sourceStart + input.bodyOffset,
|
|
415
516
|
sourceEnd: contentBlocks[input.endIdx].sourceEnd + input.bodyOffset,
|
|
416
517
|
};
|
|
@@ -423,12 +524,26 @@ export function layoutComposedPage(given) {
|
|
|
423
524
|
if (!spill || !story)
|
|
424
525
|
continue;
|
|
425
526
|
const came = input.continuing?.receivers.get(spill.head);
|
|
527
|
+
// An item of a grid (#1061) goes on whole, as its main frame says; the
|
|
528
|
+
// instances of its set that hold nothing go with it.
|
|
529
|
+
// A module (#1062) goes on whole as its group says, its frames that
|
|
530
|
+
// hold nothing along with the first of them that goes; any frame of a
|
|
531
|
+
// module goes on in that module on the page it goes to.
|
|
532
|
+
const inModule = moduleOfFrame(template, frame.name);
|
|
533
|
+
const wholeModule = spill.whole && inModule && continuesOffPage(inModule.group.overflow?.continueIn) ? inModule : undefined;
|
|
534
|
+
const cell = spill.whole && !wholeModule ? instanceOf(template, frame.name) : undefined;
|
|
535
|
+
const cellFrames = cell ? cell.group.items.find((c) => c.item === cell.item).frames : [];
|
|
536
|
+
const ruler = cell ? byName.get(cellFrames[0]) ?? frame : frame;
|
|
537
|
+
const firstGoing = wholeModule ? wholeModule.frames.find((n) => cur.spills.has(n)) : undefined;
|
|
538
|
+
const empty = cell?.main
|
|
539
|
+
? cellFrames.filter((n) => n !== frame.name && !cur.spills.has(n))
|
|
540
|
+
: wholeModule && firstGoing === frame.name ? wholeModule.frames.filter((n) => n !== frame.name && !cur.spills.has(n)) : [];
|
|
426
541
|
continuations.push({
|
|
427
542
|
frame: frame.name,
|
|
428
543
|
fromFrameId: spill.frameId,
|
|
429
544
|
head: spill.head,
|
|
430
545
|
// `{attr.x}` read from the fence (#917).
|
|
431
|
-
rule: resolveContinueIn(
|
|
546
|
+
rule: resolveContinueIn(wholeModule ? wholeModule.group.overflow.continueIn : ruler.overflow.continueIn, fence.attrs),
|
|
432
547
|
template: template.id,
|
|
433
548
|
collapsed: input.continuing?.collapse ?? false,
|
|
434
549
|
story,
|
|
@@ -437,8 +552,10 @@ export function layoutComposedPage(given) {
|
|
|
437
552
|
headBlockId: spill.headBlockId,
|
|
438
553
|
// A story that jumped here (#917) goes on named by this page's frame.
|
|
439
554
|
slot: (input.continuing?.jump ? undefined : came?.slot) ?? frame.name,
|
|
440
|
-
...(trailing.has(frame.name) ? { trailing: trailing.get(frame.name) } : {}),
|
|
555
|
+
...(trailing.has(frame.name) ? { trailing: trailing.get(frame.name) } : empty.length > 0 ? { trailing: empty } : {}),
|
|
441
556
|
...(frame.overflow.fromMark !== undefined ? { fromMark: frame.overflow.fromMark } : {}),
|
|
557
|
+
...(spill.whole ? { whole: true } : {}),
|
|
558
|
+
...(inModule ? { module: { name: inModule.module.name, template: inModule.module.template } } : {}),
|
|
442
559
|
});
|
|
443
560
|
}
|
|
444
561
|
return { composed, blocks, warnings, laid, ...(fitted.size > 0 ? { fitted } : {}), ...(continuations.length > 0 ? { continuations } : {}) };
|
|
@@ -575,9 +692,14 @@ function regroupStories(input, alt) {
|
|
|
575
692
|
const flow = alt.frames.find((f) => f.flow);
|
|
576
693
|
const flowHead = flow ? chainHead(alt, flow.name) : undefined;
|
|
577
694
|
const current = input.template.frames;
|
|
695
|
+
const repeatedIn = repeatedFrames(alt);
|
|
578
696
|
const headIn = (head) => {
|
|
579
697
|
if (names.has(head))
|
|
580
698
|
return chainHead(alt, head);
|
|
699
|
+
// An instance of a frame `alt` repeats too (#1061) stays an instance.
|
|
700
|
+
const inst = repeatInstance(head);
|
|
701
|
+
if (inst && repeatedIn.has(inst.frame))
|
|
702
|
+
return head;
|
|
581
703
|
const takes = current.find((f) => f.name === head)?.takes;
|
|
582
704
|
const taker = takes ? alt.frames.find((f) => f.takes === takes) : undefined;
|
|
583
705
|
return taker ? chainHead(alt, taker.name) : flowHead;
|
|
@@ -759,16 +881,27 @@ export function keepChromeAt(style, scale) {
|
|
|
759
881
|
return {
|
|
760
882
|
...style,
|
|
761
883
|
padding: { top: d(p.top), right: d(p.right), bottom: d(p.bottom), left: d(p.left) },
|
|
762
|
-
border: {
|
|
763
|
-
|
|
884
|
+
border: {
|
|
885
|
+
...style.border,
|
|
886
|
+
width: d(style.border.width),
|
|
887
|
+
...(style.border.sides
|
|
888
|
+
? { sides: Object.fromEntries(Object.entries(style.border.sides).map(([k, v]) => [k, { ...v, width: d(v.width) }])) }
|
|
889
|
+
: {}),
|
|
890
|
+
},
|
|
891
|
+
borderRadius: isCornerRadii(style.borderRadius)
|
|
892
|
+
? Object.fromEntries(Object.entries(style.borderRadius).map(([k, v]) => [k, v ? d(v) : v]))
|
|
893
|
+
: d(style.borderRadius),
|
|
764
894
|
stripe: { ...style.stripe, width: d(style.stripe.width) },
|
|
765
895
|
...(style.label
|
|
766
|
-
? { label: { ...style.label, height: d(style.label.height), paddingX: d(style.label.paddingX), offset: d(style.label.offset), inset: d(style.label.inset), rule: { ...style.label.rule, width: d(style.label.rule.width) } } }
|
|
896
|
+
? { label: { ...style.label, height: d(style.label.height), paddingX: d(style.label.paddingX), offset: d(style.label.offset), inset: d(style.label.inset), rule: { ...style.label.rule, width: d(style.label.rule.width) }, ...(style.label.fillet ? { fillet: d(style.label.fillet) } : {}) } }
|
|
767
897
|
: {}),
|
|
768
898
|
};
|
|
769
899
|
}
|
|
770
900
|
/** Lay out every frame of the page once, with the reflow ladder's `fit`. */
|
|
771
|
-
function composePage(
|
|
901
|
+
function composePage(pageInput, template, fit, collapsed) {
|
|
902
|
+
/** What the frames are placed in: the page, or, while a module's frames
|
|
903
|
+
* are placed (#1062), the page with the module's box as its area. */
|
|
904
|
+
let input = pageInput;
|
|
772
905
|
const { pass, fence, dpi } = input;
|
|
773
906
|
const fi = fence.fenceIndex;
|
|
774
907
|
const cont = input.continuing;
|
|
@@ -778,6 +911,8 @@ function composePage(input, template, fit, collapsed) {
|
|
|
778
911
|
* the fence's page that first sent it on. */
|
|
779
912
|
const frameIdOf = (name) => (cont && !cont.jump ? frameElementId(fi, cont.receivers.get(name)?.slot ?? name, cont.generation) : frameElementId(fi, name));
|
|
780
913
|
const byName = new Map(template.frames.map((f) => [f.name, f]));
|
|
914
|
+
/** Frames a grid repeats (#1061): their instances are `<frame>[n]`. */
|
|
915
|
+
const repeated = new Set(template.groups.flatMap((g) => (g.items ? g.repeat?.frames ?? [] : [])));
|
|
781
916
|
const prev = chainPrev(template, cont?.receivers);
|
|
782
917
|
/** The head of the chain a frame belongs to. */
|
|
783
918
|
const headOf = (name) => {
|
|
@@ -926,6 +1061,10 @@ function composePage(input, template, fit, collapsed) {
|
|
|
926
1061
|
const laid = new Set();
|
|
927
1062
|
const spills = new Map();
|
|
928
1063
|
const wantsOn = new Set();
|
|
1064
|
+
const clipped = new Set();
|
|
1065
|
+
const moduleRects = new Map();
|
|
1066
|
+
/** The foot a module cut at its group's foot is clipped to (#1062). */
|
|
1067
|
+
let clipFoot;
|
|
929
1068
|
const pushed = seed
|
|
930
1069
|
? [...seed].map(([name, box]) => ({ name, box, ...(seedShapes?.get(name) ? { contour: seedShapes.get(name) } : {}) }))
|
|
931
1070
|
: [];
|
|
@@ -1207,7 +1346,7 @@ function composePage(input, template, fit, collapsed) {
|
|
|
1207
1346
|
const start = firstFree?.own ?? input.areas.area;
|
|
1208
1347
|
const box = ownBox ?? { x: start.x, y: start.y, width: 0, height: 0 };
|
|
1209
1348
|
const out = layoutGroup({
|
|
1210
|
-
kind: group.kind,
|
|
1349
|
+
kind: group.kind === 'row' ? 'row' : 'stack',
|
|
1211
1350
|
box,
|
|
1212
1351
|
elastic: !ownBox,
|
|
1213
1352
|
limit: input.areas.area,
|
|
@@ -1258,6 +1397,170 @@ function composePage(input, template, fit, collapsed) {
|
|
|
1258
1397
|
groupDeclared.set(group.name, decl.box);
|
|
1259
1398
|
return fin.rects;
|
|
1260
1399
|
};
|
|
1400
|
+
/** Lay a grid (#1061): its cells fill rows from the start side of the
|
|
1401
|
+
* page's lines (the flow frame is mirrored on a right-to-left page, so
|
|
1402
|
+
* its left is the start), `columns` to a row, `columnGap` and `rowGap`
|
|
1403
|
+
* between them. A cell is one item of a repeated frame set (or one
|
|
1404
|
+
* frame of a grid that repeats none): the main frame takes the cell's
|
|
1405
|
+
* width and its own height rule, the set's other frames are placed as
|
|
1406
|
+
* the template draws them, anchored to the main frame or to each
|
|
1407
|
+
* other (one that anchors to nothing in the set moves with the cell).
|
|
1408
|
+
* A row is as tall as its tallest cell, the set's frames counted;
|
|
1409
|
+
* `rowAlign` places the shorter ones (`'stretch'`: their main frame
|
|
1410
|
+
* grows to the row). The grid runs down its own box, or to the foot of
|
|
1411
|
+
* the area from where the template draws its main frame. A row that
|
|
1412
|
+
* does not fit is clipped at the foot, or, when the grid goes on to
|
|
1413
|
+
* another page (`FitState.gridsOn`), it and every row after it are
|
|
1414
|
+
* left for that page, whole (`spilled`). */
|
|
1415
|
+
const placeGrid = (group, members) => {
|
|
1416
|
+
const byMember = new Map(members.map((f) => [f.name, f]));
|
|
1417
|
+
const cells = (group.items ?? (group.repeat ? [] : members.map((f) => ({ item: 0, frames: [f.name] }))))
|
|
1418
|
+
.map((c) => c.frames.filter((n) => byMember.has(n)))
|
|
1419
|
+
.filter((c) => c.length > 0);
|
|
1420
|
+
const laidBoxes = new Map();
|
|
1421
|
+
const spilled = new Set();
|
|
1422
|
+
const cut = [];
|
|
1423
|
+
const own = groupPlaceable(group);
|
|
1424
|
+
const ownBox = own ? placeBox(own, template, input, refOf, () => 0) : undefined;
|
|
1425
|
+
const area = input.areas.area;
|
|
1426
|
+
const first = cells[0] ? byMember.get(cells[0][0]) : undefined;
|
|
1427
|
+
/** Where the template draws a cell's main frame. */
|
|
1428
|
+
const drawnOf = (main) => placeBox(framePlaceable(main), template, input, refOf, () => 0);
|
|
1429
|
+
const drawnFirst = first ? drawnOf(first) : area;
|
|
1430
|
+
const box = ownBox ?? { x: drawnFirst.x, y: drawnFirst.y, width: Math.max(0, area.x + area.width - drawnFirst.x), height: Math.max(0, area.y + area.height - drawnFirst.y) };
|
|
1431
|
+
const foot = box.y + box.height;
|
|
1432
|
+
const columns = Math.max(1, group.columns ?? 1);
|
|
1433
|
+
const colGap = dimensionToPx(group.columnGap ?? group.gap, dpi, input.emPx);
|
|
1434
|
+
const rowGap = dimensionToPx(group.rowGap ?? group.gap, dpi, input.emPx);
|
|
1435
|
+
const colW = Math.max(1, (box.width - colGap * (columns - 1)) / columns);
|
|
1436
|
+
const xOf = (c) => box.x + c * (colW + colGap);
|
|
1437
|
+
const px = (d) => (d ? dimensionToPx(d, dpi, input.emPx) : undefined);
|
|
1438
|
+
/** The main frame's height in a cell `w` wide: its own rule, held
|
|
1439
|
+
* between its minimum and maximum. */
|
|
1440
|
+
const mainHeight = (f, w) => {
|
|
1441
|
+
const h = f.height;
|
|
1442
|
+
let v;
|
|
1443
|
+
if (h === 'auto')
|
|
1444
|
+
v = naturalOf(prepare(f))(w);
|
|
1445
|
+
else if (h === 'fill')
|
|
1446
|
+
v = 0;
|
|
1447
|
+
else if ('percent' in h)
|
|
1448
|
+
v = (area.height * h.percent) / 100;
|
|
1449
|
+
else
|
|
1450
|
+
v = dimensionToPx(h, dpi, input.emPx);
|
|
1451
|
+
const min = px(f.minHeight) ?? 0;
|
|
1452
|
+
const max = px(f.maxHeight) ?? Infinity;
|
|
1453
|
+
return Math.max(min, Math.min(v, max));
|
|
1454
|
+
};
|
|
1455
|
+
/** The boxes of a cell's frames with its main frame at `(x, y)`,
|
|
1456
|
+
* `h` tall; and the frames that count for the cell's extent. */
|
|
1457
|
+
const layCell = (cell, x, y, h) => {
|
|
1458
|
+
const main = byMember.get(cell[0]);
|
|
1459
|
+
const boxes = new Map([[main.name, { x, y, width: colW, height: h }]]);
|
|
1460
|
+
const inCell = [main.name];
|
|
1461
|
+
const set = new Set(cell);
|
|
1462
|
+
const drawn = drawnOf(main);
|
|
1463
|
+
const refs = (n) => boxes.get(n) ?? refOf(n);
|
|
1464
|
+
// A frame anchored in the set fills (and takes its percentages of)
|
|
1465
|
+
// the cell's column, not the whole area.
|
|
1466
|
+
const column = { ...input, areas: { ...input.areas, area: { x, y: area.y, width: colW, height: area.height } } };
|
|
1467
|
+
let todo = cell.slice(1);
|
|
1468
|
+
for (let pass = 0; todo.length > 0 && pass <= cell.length; pass++) {
|
|
1469
|
+
const later = [];
|
|
1470
|
+
for (const name of todo) {
|
|
1471
|
+
const f = byMember.get(name);
|
|
1472
|
+
const target = f.grid ? undefined : anchorTarget(f.placement);
|
|
1473
|
+
// Anchored to a frame of the set not placed yet: next pass.
|
|
1474
|
+
if (target !== undefined && set.has(target) && !boxes.has(target) && pass < cell.length) {
|
|
1475
|
+
later.push(name);
|
|
1476
|
+
continue;
|
|
1477
|
+
}
|
|
1478
|
+
const p = prepare(f);
|
|
1479
|
+
const inSet = target !== undefined && set.has(target);
|
|
1480
|
+
const r = placeFitted(f, framePlaceable(f), inSet ? column : input, refs, naturalOf(p), naturalWidthOf(p));
|
|
1481
|
+
if (target !== undefined && !set.has(target)) {
|
|
1482
|
+
// Anchored to a frame outside the set: where it says.
|
|
1483
|
+
boxes.set(name, r);
|
|
1484
|
+
continue;
|
|
1485
|
+
}
|
|
1486
|
+
// Anchored in the set, or to nothing in it: with the cell.
|
|
1487
|
+
boxes.set(name, target !== undefined ? r : { ...r, x: r.x + x - drawn.x, y: r.y + y - drawn.y });
|
|
1488
|
+
inCell.push(name);
|
|
1489
|
+
}
|
|
1490
|
+
todo = later;
|
|
1491
|
+
}
|
|
1492
|
+
return { boxes, inCell };
|
|
1493
|
+
};
|
|
1494
|
+
const stretchable = (f) => f.height === 'auto' || f.height === 'fill';
|
|
1495
|
+
let cursor = box.y;
|
|
1496
|
+
let laidAny = false;
|
|
1497
|
+
let out = false;
|
|
1498
|
+
for (let r = 0; r * columns < cells.length; r++) {
|
|
1499
|
+
const row = cells.slice(r * columns, (r + 1) * columns);
|
|
1500
|
+
if (out) {
|
|
1501
|
+
for (const c of row)
|
|
1502
|
+
for (const n of c)
|
|
1503
|
+
spilled.add(n);
|
|
1504
|
+
continue;
|
|
1505
|
+
}
|
|
1506
|
+
// Each cell at the row's top, to see how far it reaches above and
|
|
1507
|
+
// below its main frame.
|
|
1508
|
+
const measured = row.map((cell, c) => {
|
|
1509
|
+
const main = byMember.get(cell[0]);
|
|
1510
|
+
const h = mainHeight(main, colW);
|
|
1511
|
+
const { boxes, inCell } = layCell(cell, xOf(c), 0, h);
|
|
1512
|
+
const u = unionRect(inCell.map((n) => boxes.get(n)));
|
|
1513
|
+
return { cell, main, h, above: Math.max(0, -u.y), below: u.y + u.height };
|
|
1514
|
+
});
|
|
1515
|
+
const above = Math.max(0, ...measured.map((m) => m.above));
|
|
1516
|
+
const below = Math.max(0, ...measured.map((m) => m.below));
|
|
1517
|
+
const rowH = above + below;
|
|
1518
|
+
const fits = cursor + rowH <= foot + 0.5;
|
|
1519
|
+
if (!fits && fit.gridsOn.has(group.name)) {
|
|
1520
|
+
// This row and the rest go on, whole.
|
|
1521
|
+
out = true;
|
|
1522
|
+
for (const c of row)
|
|
1523
|
+
for (const n of c)
|
|
1524
|
+
spilled.add(n);
|
|
1525
|
+
continue;
|
|
1526
|
+
}
|
|
1527
|
+
measured.forEach((m, c) => {
|
|
1528
|
+
const spare = below - m.below;
|
|
1529
|
+
let dy = 0;
|
|
1530
|
+
let h = m.h;
|
|
1531
|
+
if (spare > 0.01) {
|
|
1532
|
+
const align = group.rowAlign ?? 'stretch';
|
|
1533
|
+
if (align === 'end')
|
|
1534
|
+
dy = spare;
|
|
1535
|
+
else if (align === 'center')
|
|
1536
|
+
dy = spare / 2;
|
|
1537
|
+
else if (align === 'stretch' && stretchable(m.main))
|
|
1538
|
+
h = Math.min(m.h + spare, px(m.main.maxHeight) ?? Infinity);
|
|
1539
|
+
}
|
|
1540
|
+
const { boxes } = layCell(m.cell, xOf(c), cursor + above + dy, h);
|
|
1541
|
+
if (!fits)
|
|
1542
|
+
cut.push(...m.cell);
|
|
1543
|
+
for (const [n, b] of boxes) {
|
|
1544
|
+
// A row past the grid's foot is cut there: what is cut shows as
|
|
1545
|
+
// the frames' overflow.
|
|
1546
|
+
const y = Math.min(b.y, foot);
|
|
1547
|
+
laidBoxes.set(n, fits ? b : { ...b, y, height: Math.max(0, Math.min(b.y + b.height, foot) - y) });
|
|
1548
|
+
}
|
|
1549
|
+
});
|
|
1550
|
+
laidAny = true;
|
|
1551
|
+
cursor += rowH + rowGap;
|
|
1552
|
+
}
|
|
1553
|
+
for (const [n, b] of laidBoxes) {
|
|
1554
|
+
// A grid's cells are its template's drawing: no reflow events.
|
|
1555
|
+
declared.set(n, b);
|
|
1556
|
+
rects.set(n, b);
|
|
1557
|
+
}
|
|
1558
|
+
const laidRects = [...laidBoxes.values()];
|
|
1559
|
+
const union = ownBox ?? unionRect(laidRects) ?? { ...box, height: 0 };
|
|
1560
|
+
groupRects.set(group.name, union);
|
|
1561
|
+
groupDeclared.set(group.name, union);
|
|
1562
|
+
return { rects: laidBoxes, spilled, laidAny, clipped: cut };
|
|
1563
|
+
};
|
|
1261
1564
|
/** Pour a frame's content into its box and record the frame. A frame
|
|
1262
1565
|
* whose text the ladder scales (#858) is laid out in a box `1 / scale`
|
|
1263
1566
|
* as large, painted at `scale` (`frameMatrix`). */
|
|
@@ -1347,9 +1650,11 @@ function composePage(input, template, fit, collapsed) {
|
|
|
1347
1650
|
emptyRules = turned ? blocks.map((b) => ({ ...b, bbox: turnRectAbout(b.bbox, rect, frameModeTurn({ writingMode: turned })) })) : blocks;
|
|
1348
1651
|
}
|
|
1349
1652
|
}
|
|
1653
|
+
const instance = repeated.has(repeatInstance(frame.name)?.frame ?? '') ? repeatInstance(frame.name) : undefined;
|
|
1350
1654
|
const vdt = {
|
|
1351
1655
|
id: frameIdOf(frame.name),
|
|
1352
1656
|
name: frame.name,
|
|
1657
|
+
...(instance ? { repeat: instance } : {}),
|
|
1353
1658
|
rect: { ...rect },
|
|
1354
1659
|
rotate: frame.rotate + (turned ? frameModeTurn({ writingMode: turned }) : 0),
|
|
1355
1660
|
...(turned ? { writingMode: turned } : {}),
|
|
@@ -1375,8 +1680,9 @@ function composePage(input, template, fit, collapsed) {
|
|
|
1375
1680
|
if (q)
|
|
1376
1681
|
q.continuesTo = vdt.id;
|
|
1377
1682
|
}
|
|
1378
|
-
else if (holds && cont?.receivers.has(frame.name)) {
|
|
1379
|
-
// Content from the page before (#859).
|
|
1683
|
+
else if (holds && cont?.receivers.has(frame.name) && !cont.receivers.get(frame.name).whole) {
|
|
1684
|
+
// Content from the page before (#859). (An item of a grid that
|
|
1685
|
+
// came whole, #1061, starts here.)
|
|
1380
1686
|
const came = cont.receivers.get(frame.name);
|
|
1381
1687
|
vdt.continuedFrom = came.fromFrameId;
|
|
1382
1688
|
// From a page of an earlier chapter (#943).
|
|
@@ -1436,25 +1742,199 @@ function composePage(input, template, fit, collapsed) {
|
|
|
1436
1742
|
frames.push(vdt);
|
|
1437
1743
|
vdtByName.set(frame.name, vdt);
|
|
1438
1744
|
};
|
|
1439
|
-
|
|
1745
|
+
/** A frame's box cut at `clipFoot` (a module cut at its group's foot,
|
|
1746
|
+
* #1062): what is cut shows as the frame's overflow. */
|
|
1747
|
+
const clipAtFoot = (name, r) => {
|
|
1748
|
+
if (clipFoot === undefined || r.y + r.height <= clipFoot + 0.5)
|
|
1749
|
+
return r;
|
|
1750
|
+
clipped.add(name);
|
|
1751
|
+
const y = Math.min(r.y, clipFoot);
|
|
1752
|
+
const out = { ...r, y, height: Math.max(0, Math.min(r.y + r.height, clipFoot) - y) };
|
|
1753
|
+
rects.set(name, out);
|
|
1754
|
+
return out;
|
|
1755
|
+
};
|
|
1756
|
+
/** The frames of `names` whose content goes on whole on another page
|
|
1757
|
+
* (#1061, #1062): none of it is laid here. */
|
|
1758
|
+
const spillWhole = (names, advanced, lastLaid) => {
|
|
1759
|
+
for (const n of names) {
|
|
1760
|
+
const f = byName.get(n);
|
|
1761
|
+
const st = f ? prepare(f).st : undefined;
|
|
1762
|
+
if (!st)
|
|
1763
|
+
continue;
|
|
1764
|
+
laid.add(headOf(n));
|
|
1765
|
+
spills.set(n, { head: headOf(n), cut: st.cut, advanced, pieces: st.pieces, headBlockId: st.headBlockId, frameId: lastLaid ?? frameIdOf(n), whole: true });
|
|
1766
|
+
}
|
|
1767
|
+
};
|
|
1768
|
+
/** Place (and, `filling`, fill) one step of `composedOrder`. */
|
|
1769
|
+
const runStep = (step, filling) => {
|
|
1440
1770
|
if (step.kind === 'frame') {
|
|
1441
1771
|
const p = prepare(step.frame);
|
|
1442
|
-
|
|
1443
|
-
|
|
1772
|
+
const r = clipAtFoot(step.frame.name, placeFrame(p));
|
|
1773
|
+
if (filling)
|
|
1774
|
+
fill(p, r);
|
|
1775
|
+
return;
|
|
1776
|
+
}
|
|
1777
|
+
if (step.group.modules) {
|
|
1778
|
+
// A modules group (#1062): its modules, one under another.
|
|
1779
|
+
placeModules(step.group, step.frames);
|
|
1780
|
+
return;
|
|
1781
|
+
}
|
|
1782
|
+
if (step.group.kind === 'grid') {
|
|
1783
|
+
// A grid (#1061): its cells, and the items of the rows left for
|
|
1784
|
+
// another page, which go on whole.
|
|
1785
|
+
const grid = placeGrid(step.group, step.frames);
|
|
1786
|
+
if (!filling)
|
|
1787
|
+
return;
|
|
1788
|
+
for (const n of grid.clipped)
|
|
1789
|
+
clipped.add(n);
|
|
1790
|
+
let lastLaid;
|
|
1791
|
+
for (const f of step.frames) {
|
|
1792
|
+
if (!grid.spilled.has(f.name)) {
|
|
1793
|
+
fill(prepare(f), clipAtFoot(f.name, grid.rects.get(f.name)));
|
|
1794
|
+
lastLaid = frameIdOf(f.name);
|
|
1795
|
+
continue;
|
|
1796
|
+
}
|
|
1797
|
+
spillWhole([f.name], grid.laidAny, lastLaid);
|
|
1798
|
+
}
|
|
1799
|
+
return;
|
|
1444
1800
|
}
|
|
1445
1801
|
const solved = placeGroup(step.group, step.frames);
|
|
1446
1802
|
// A frame of a chain inside the group is reached once the frame
|
|
1447
1803
|
// before it was filled: each is prepared again as it is filled.
|
|
1448
|
-
for (const f of step.frames)
|
|
1449
|
-
|
|
1450
|
-
|
|
1804
|
+
for (const f of step.frames) {
|
|
1805
|
+
const r = clipAtFoot(f.name, solved.get(f.name));
|
|
1806
|
+
if (filling)
|
|
1807
|
+
fill(prepare(f), r);
|
|
1808
|
+
}
|
|
1809
|
+
};
|
|
1810
|
+
/** Lay a modules group (#1062): each module, in order, in a box as wide
|
|
1811
|
+
* as the group, from where the module before it ends (`gap` between
|
|
1812
|
+
* them), as tall as its frames. A module's frames are placed as its
|
|
1813
|
+
* template draws them in that box (`'container'` is the box) and its
|
|
1814
|
+
* groups laid in it: first in the room left, to find how tall it is
|
|
1815
|
+
* (the frames held by the box's foot or middle, or sized by its
|
|
1816
|
+
* height, left out), then in a box that tall. The group runs down its
|
|
1817
|
+
* own box, else the area. A module that does not fit is cut at the
|
|
1818
|
+
* group's foot (its frames clipped there), or, when the group goes on
|
|
1819
|
+
* to another page (`FitState.gridsOn`), it and every module after it
|
|
1820
|
+
* go on, whole. The modules' declared boxes follow each other at the
|
|
1821
|
+
* heights their frames declare, so the log tells a module moved by
|
|
1822
|
+
* the one before it. */
|
|
1823
|
+
const placeModules = (group, members) => {
|
|
1824
|
+
const byMember = new Map(members.map((f) => [f.name, f]));
|
|
1825
|
+
const own = groupPlaceable(group);
|
|
1826
|
+
const ownBox = own ? placeBox(own, template, pageInput, refOf, () => 0) : undefined;
|
|
1827
|
+
const box = ownBox ?? pageInput.areas.area;
|
|
1828
|
+
const foot = box.y + box.height;
|
|
1829
|
+
const gap = dimensionToPx(group.gap, dpi, pageInput.emPx);
|
|
1830
|
+
let cursor = box.y;
|
|
1831
|
+
let declCursor = box.y;
|
|
1832
|
+
let out = false;
|
|
1833
|
+
let laidAny = false;
|
|
1834
|
+
let lastLaid;
|
|
1835
|
+
const boxes = [];
|
|
1836
|
+
const declBoxes = [];
|
|
1837
|
+
const restore = (to, from) => {
|
|
1838
|
+
to.clear();
|
|
1839
|
+
for (const [k, v] of from)
|
|
1840
|
+
to.set(k, v);
|
|
1841
|
+
};
|
|
1842
|
+
for (const item of group.items ?? []) {
|
|
1843
|
+
const mod = template.modules?.find((m) => m.name === item.module);
|
|
1844
|
+
const names = item.frames.filter((n) => byMember.has(n));
|
|
1845
|
+
if (!mod || names.length === 0)
|
|
1846
|
+
continue;
|
|
1847
|
+
if (out) {
|
|
1848
|
+
spillWhole(names, laidAny, lastLaid);
|
|
1849
|
+
continue;
|
|
1850
|
+
}
|
|
1851
|
+
const sub = { frames: names.map((n) => byMember.get(n)), groups: template.groups.filter((g) => mod.groups.includes(g.name)) };
|
|
1852
|
+
const steps = composedOrder(sub);
|
|
1853
|
+
const lay = (height, filling) => {
|
|
1854
|
+
input = { ...pageInput, areas: { ...pageInput.areas, area: { x: box.x, y: cursor, width: box.width, height: Math.max(0, height) } } };
|
|
1855
|
+
try {
|
|
1856
|
+
for (const step of steps)
|
|
1857
|
+
runStep(step, filling);
|
|
1858
|
+
}
|
|
1859
|
+
finally {
|
|
1860
|
+
input = pageInput;
|
|
1861
|
+
}
|
|
1862
|
+
};
|
|
1863
|
+
// 1. How tall the module is: its frames placed in the room left,
|
|
1864
|
+
// then everything they set put back.
|
|
1865
|
+
const kept = { rects: new Map(rects), declared: new Map(declared), groupRects: new Map(groupRects), groupDeclared: new Map(groupDeclared), pinned: pinned.length, boxShort: new Map(boxShort), fitted: new Map(fitted) };
|
|
1866
|
+
lay(foot - cursor, false);
|
|
1867
|
+
const placed = names.filter((n) => rects.has(n));
|
|
1868
|
+
const measured = placed.filter((n) => !heldByFoot(byMember.get(n)));
|
|
1869
|
+
const reach = unionRect((measured.length > 0 ? measured : placed).map((n) => rects.get(n)));
|
|
1870
|
+
const height = reach ? Math.max(0, reach.y + reach.height - cursor) : 0;
|
|
1871
|
+
restore(rects, kept.rects);
|
|
1872
|
+
restore(declared, kept.declared);
|
|
1873
|
+
restore(groupRects, kept.groupRects);
|
|
1874
|
+
restore(groupDeclared, kept.groupDeclared);
|
|
1875
|
+
restore(boxShort, kept.boxShort);
|
|
1876
|
+
restore(fitted, kept.fitted);
|
|
1877
|
+
pinned.length = kept.pinned;
|
|
1878
|
+
const fits = cursor + height <= foot + 0.5;
|
|
1879
|
+
if (!fits && fit.gridsOn.has(group.name)) {
|
|
1880
|
+
// This module and the ones after it go on, whole.
|
|
1881
|
+
out = true;
|
|
1882
|
+
spillWhole(names, laidAny, lastLaid);
|
|
1883
|
+
continue;
|
|
1884
|
+
}
|
|
1885
|
+
// 2. The module laid in a box that tall (cut at the foot when it
|
|
1886
|
+
// does not fit).
|
|
1887
|
+
clipFoot = fits ? undefined : foot;
|
|
1888
|
+
try {
|
|
1889
|
+
lay(fits ? height : foot - cursor, true);
|
|
1890
|
+
}
|
|
1891
|
+
finally {
|
|
1892
|
+
clipFoot = undefined;
|
|
1893
|
+
}
|
|
1894
|
+
const u = unionRect(names.flatMap((n) => (rects.has(n) ? [rects.get(n)] : [])));
|
|
1895
|
+
const bottom = u ? Math.max(cursor, u.y + u.height) : cursor;
|
|
1896
|
+
const moduleBox = { x: box.x, y: cursor, width: box.width, height: bottom - cursor };
|
|
1897
|
+
moduleRects.set(mod.name, moduleBox);
|
|
1898
|
+
boxes.push(moduleBox);
|
|
1899
|
+
// Declared: after the modules before it as they declare themselves.
|
|
1900
|
+
const shift = declCursor - cursor;
|
|
1901
|
+
for (const n of names) {
|
|
1902
|
+
const d = declared.get(n);
|
|
1903
|
+
if (d && Math.abs(shift) > 0.001)
|
|
1904
|
+
declared.set(n, { ...d, y: d.y + shift });
|
|
1905
|
+
}
|
|
1906
|
+
const du = unionRect(names.flatMap((n) => (declared.has(n) ? [declared.get(n)] : [])));
|
|
1907
|
+
const declBottom = du ? Math.max(declCursor, du.y + du.height) : declCursor;
|
|
1908
|
+
declBoxes.push({ x: box.x, y: declCursor, width: box.width, height: declBottom - declCursor });
|
|
1909
|
+
laidAny = true;
|
|
1910
|
+
lastLaid = frameIdOf(names[names.length - 1]);
|
|
1911
|
+
cursor = bottom + gap;
|
|
1912
|
+
declCursor = declBottom + gap;
|
|
1913
|
+
}
|
|
1914
|
+
groupRects.set(group.name, ownBox ?? unionRect(boxes) ?? { ...box, height: 0 });
|
|
1915
|
+
groupDeclared.set(group.name, ownBox ?? unionRect(declBoxes) ?? { ...box, height: 0 });
|
|
1916
|
+
};
|
|
1917
|
+
for (const step of composedOrder(template))
|
|
1918
|
+
runStep(step, true);
|
|
1451
1919
|
const log = mergeLog(reflowEvents(motionsOf(template, rects, declared), dpi / MM_PER_IN), [...fitLog, ...overflowLog], template);
|
|
1452
|
-
return { frames, blocks, log, laid, needs, pushRects, pushShapes, fitted, notes, spills, wantsOn };
|
|
1920
|
+
return { frames, blocks, log, laid, needs, pushRects, pushShapes, fitted, notes, spills, wantsOn, clipped, groupRects, moduleRects };
|
|
1453
1921
|
};
|
|
1454
1922
|
const first = run();
|
|
1455
|
-
const { frames, blocks, log, laid, needs, fitted, notes, spills, wantsOn } = first.pushRects.size > 0 ? run(first.pushRects, first.pushShapes) : first;
|
|
1456
|
-
return { frames, blocks, log, laid, needs, template, fitted, spills, wantsOn, ...(notes.length > 0 ? { notes } : {}) };
|
|
1923
|
+
const { frames, blocks, log, laid, needs, fitted, notes, spills, wantsOn, clipped, groupRects, moduleRects } = first.pushRects.size > 0 ? run(first.pushRects, first.pushShapes) : first;
|
|
1924
|
+
return { frames, blocks, log, laid, needs, template, fitted, spills, wantsOn, clipped, groupRects, moduleRects, ...(notes.length > 0 ? { notes } : {}) };
|
|
1457
1925
|
}
|
|
1926
|
+
/** A module's frame placed by its box's foot or middle, or sized by its
|
|
1927
|
+
* height (#1062): it does not say how tall the module is. */
|
|
1928
|
+
function heldByFoot(f) {
|
|
1929
|
+
if (f.height === 'fill' || (typeof f.height === 'object' && 'percent' in f.height))
|
|
1930
|
+
return true;
|
|
1931
|
+
const anchor = f.placement?.anchor;
|
|
1932
|
+
if (!anchor || anchor.to !== 'container')
|
|
1933
|
+
return false;
|
|
1934
|
+
return FOOT_EDGES.has(anchor.edge);
|
|
1935
|
+
}
|
|
1936
|
+
/** The nine-point edges below a box's top. */
|
|
1937
|
+
const FOOT_EDGES = new Set(['left', 'center', 'right', 'start', 'end', 'bottom-left', 'bottom', 'bottom-right', 'bottom-start', 'bottom-end']);
|
|
1458
1938
|
/** `r` turned `deg` (±90) about the centre of `about`: an axis-aligned
|
|
1459
1939
|
* box again, its width and height swapped. */
|
|
1460
1940
|
function turnRectAbout(r, about, deg) {
|
|
@@ -1600,8 +2080,16 @@ export function styleWithLook(base, look) {
|
|
|
1600
2080
|
out.background = look.background;
|
|
1601
2081
|
out.backgroundEnabled = true;
|
|
1602
2082
|
}
|
|
1603
|
-
if (look.border?.color)
|
|
1604
|
-
|
|
2083
|
+
if (look.border?.color) {
|
|
2084
|
+
// Every side takes the look's border colour too (#1059).
|
|
2085
|
+
const color = look.border.color;
|
|
2086
|
+
const sides = base.border.sides;
|
|
2087
|
+
out.border = {
|
|
2088
|
+
...base.border,
|
|
2089
|
+
color,
|
|
2090
|
+
...(sides ? { sides: { top: { ...sides.top, color }, right: { ...sides.right, color }, bottom: { ...sides.bottom, color }, left: { ...sides.left, color } } } : {}),
|
|
2091
|
+
};
|
|
2092
|
+
}
|
|
1605
2093
|
if (look.stripe?.color)
|
|
1606
2094
|
out.stripe = { ...base.stripe, color: look.stripe.color };
|
|
1607
2095
|
if (look.icon?.color)
|
|
@@ -1667,7 +2155,9 @@ export function planComposedPages(blocks, plans, source) {
|
|
|
1667
2155
|
while (end < blocks.length && !(blocks[end].type === 'containerEnd' && blocks[end].containerId === b.containerId))
|
|
1668
2156
|
end++;
|
|
1669
2157
|
end = Math.min(end, blocks.length - 1);
|
|
1670
|
-
|
|
2158
|
+
// (A module, #1062, is never laid as a page.)
|
|
2159
|
+
const t = resolvePageTemplate(source, b.composedPage.template);
|
|
2160
|
+
if (t && !isModuleTemplate(t)) {
|
|
1671
2161
|
const stories = composedStories(i, end, plans);
|
|
1672
2162
|
const list = [...stories.values()];
|
|
1673
2163
|
out.set(i, {
|