postext 1.37.0 → 1.38.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__/comics/frames.test.d.ts +2 -0
- package/dist/__tests__/comics/frames.test.d.ts.map +1 -0
- package/dist/__tests__/comics/frames.test.js +251 -0
- package/dist/__tests__/comics/frames.test.js.map +1 -0
- package/dist/__tests__/composed/continuationRules.test.d.ts +2 -0
- package/dist/__tests__/composed/continuationRules.test.d.ts.map +1 -0
- package/dist/__tests__/composed/continuationRules.test.js +389 -0
- package/dist/__tests__/composed/continuationRules.test.js.map +1 -0
- package/dist/__tests__/composed/coverImages.test.d.ts +2 -0
- package/dist/__tests__/composed/coverImages.test.d.ts.map +1 -0
- package/dist/__tests__/composed/coverImages.test.js +75 -0
- package/dist/__tests__/composed/coverImages.test.js.map +1 -0
- package/dist/__tests__/composed/decorationSize.test.d.ts +2 -0
- package/dist/__tests__/composed/decorationSize.test.d.ts.map +1 -0
- package/dist/__tests__/composed/decorationSize.test.js +79 -0
- package/dist/__tests__/composed/decorationSize.test.js.map +1 -0
- package/dist/__tests__/composed/emptyFrames.test.d.ts +2 -0
- package/dist/__tests__/composed/emptyFrames.test.d.ts.map +1 -0
- package/dist/__tests__/composed/emptyFrames.test.js +129 -0
- package/dist/__tests__/composed/emptyFrames.test.js.map +1 -0
- package/dist/__tests__/composed/fit.test.js +10 -4
- package/dist/__tests__/composed/fit.test.js.map +1 -1
- package/dist/__tests__/composed/groups.test.js +20 -0
- package/dist/__tests__/composed/groups.test.js.map +1 -1
- package/dist/__tests__/composed/ruledFrames.test.d.ts +2 -0
- package/dist/__tests__/composed/ruledFrames.test.d.ts.map +1 -0
- package/dist/__tests__/composed/ruledFrames.test.js +93 -0
- package/dist/__tests__/composed/ruledFrames.test.js.map +1 -0
- package/dist/__tests__/composed/spread.test.js +82 -0
- package/dist/__tests__/composed/spread.test.js.map +1 -1
- package/dist/__tests__/exports.test.js +12 -0
- package/dist/__tests__/exports.test.js.map +1 -1
- package/dist/__tests__/migrate/labelsOnPictures.test.d.ts +2 -0
- package/dist/__tests__/migrate/labelsOnPictures.test.d.ts.map +1 -0
- package/dist/__tests__/migrate/labelsOnPictures.test.js +114 -0
- package/dist/__tests__/migrate/labelsOnPictures.test.js.map +1 -0
- package/dist/__tests__/paragraphDropCap.test.js +38 -0
- package/dist/__tests__/paragraphDropCap.test.js.map +1 -1
- package/dist/__tests__/resourceTypePartial.test.d.ts +2 -0
- package/dist/__tests__/resourceTypePartial.test.d.ts.map +1 -0
- package/dist/__tests__/resourceTypePartial.test.js +60 -0
- package/dist/__tests__/resourceTypePartial.test.js.map +1 -0
- package/dist/canvas-backend/composed.d.ts +3 -0
- package/dist/canvas-backend/composed.d.ts.map +1 -1
- package/dist/canvas-backend/composed.js +47 -26
- package/dist/canvas-backend/composed.js.map +1 -1
- package/dist/canvas-backend/headerFooter.d.ts.map +1 -1
- package/dist/canvas-backend/headerFooter.js +13 -0
- 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 +16 -5
- package/dist/canvas-backend/index.js.map +1 -1
- package/dist/comics/frames.d.ts +82 -0
- package/dist/comics/frames.d.ts.map +1 -0
- package/dist/comics/frames.js +182 -0
- package/dist/comics/frames.js.map +1 -0
- package/dist/comics/index.d.ts +4 -1
- package/dist/comics/index.d.ts.map +1 -1
- package/dist/comics/index.js +3 -1
- package/dist/comics/index.js.map +1 -1
- package/dist/comics/layoutPage.d.ts +9 -0
- package/dist/comics/layoutPage.d.ts.map +1 -1
- package/dist/comics/layoutPage.js +53 -68
- package/dist/comics/layoutPage.js.map +1 -1
- package/dist/comics/page.d.ts.map +1 -1
- package/dist/comics/page.js +10 -1
- package/dist/comics/page.js.map +1 -1
- package/dist/comics/sourceMap.d.ts +60 -0
- package/dist/comics/sourceMap.d.ts.map +1 -0
- package/dist/comics/sourceMap.js +166 -0
- package/dist/comics/sourceMap.js.map +1 -0
- package/dist/comics/spread.d.ts.map +1 -1
- package/dist/comics/spread.js +6 -0
- package/dist/comics/spread.js.map +1 -1
- package/dist/comics/textPanels.d.ts +113 -0
- package/dist/comics/textPanels.d.ts.map +1 -0
- package/dist/comics/textPanels.js +327 -0
- package/dist/comics/textPanels.js.map +1 -0
- package/dist/comics/transform.d.ts +6 -2
- package/dist/comics/transform.d.ts.map +1 -1
- package/dist/comics/transform.js +14 -1
- package/dist/comics/transform.js.map +1 -1
- package/dist/comics/types.d.ts +10 -0
- package/dist/comics/types.d.ts.map +1 -1
- package/dist/composed/continuation.d.ts +55 -5
- package/dist/composed/continuation.d.ts.map +1 -1
- package/dist/composed/continuation.js +118 -16
- package/dist/composed/continuation.js.map +1 -1
- package/dist/composed/groups.d.ts +3 -0
- package/dist/composed/groups.d.ts.map +1 -1
- package/dist/composed/groups.js +34 -4
- package/dist/composed/groups.js.map +1 -1
- package/dist/composed/paint.d.ts +20 -1
- package/dist/composed/paint.d.ts.map +1 -1
- package/dist/composed/paint.js +40 -0
- package/dist/composed/paint.js.map +1 -1
- package/dist/composed/rules.d.ts +31 -0
- package/dist/composed/rules.d.ts.map +1 -0
- package/dist/composed/rules.js +45 -0
- package/dist/composed/rules.js.map +1 -0
- package/dist/composed/slotChecks.d.ts +2 -1
- package/dist/composed/slotChecks.d.ts.map +1 -1
- package/dist/composed/slotChecks.js +56 -2
- package/dist/composed/slotChecks.js.map +1 -1
- package/dist/composed/sourceMap.d.ts.map +1 -1
- package/dist/composed/sourceMap.js +15 -1
- package/dist/composed/sourceMap.js.map +1 -1
- package/dist/composed/spread.d.ts +20 -5
- package/dist/composed/spread.d.ts.map +1 -1
- package/dist/composed/spread.js +51 -26
- package/dist/composed/spread.js.map +1 -1
- package/dist/composed/templates.d.ts +11 -0
- package/dist/composed/templates.d.ts.map +1 -1
- package/dist/composed/templates.js +51 -2
- package/dist/composed/templates.js.map +1 -1
- package/dist/composed/types.d.ts +43 -3
- package/dist/composed/types.d.ts.map +1 -1
- package/dist/composed/validate.d.ts.map +1 -1
- package/dist/composed/validate.js +5 -3
- package/dist/composed/validate.js.map +1 -1
- package/dist/configWarnings.d.ts.map +1 -1
- package/dist/configWarnings.js +11 -1
- package/dist/configWarnings.js.map +1 -1
- package/dist/defaults/headerFooter.d.ts.map +1 -1
- package/dist/defaults/headerFooter.js +4 -0
- package/dist/defaults/headerFooter.js.map +1 -1
- package/dist/defaults/resourceTypes.d.ts +15 -0
- package/dist/defaults/resourceTypes.d.ts.map +1 -1
- package/dist/defaults/resourceTypes.js +39 -1
- package/dist/defaults/resourceTypes.js.map +1 -1
- package/dist/design/layout.d.ts +7 -0
- package/dist/design/layout.d.ts.map +1 -1
- package/dist/design/layout.js +109 -16
- package/dist/design/layout.js.map +1 -1
- package/dist/html-backend.d.ts.map +1 -1
- package/dist/html-backend.js +43 -5
- package/dist/html-backend.js.map +1 -1
- package/dist/htmlComic.d.ts +3 -0
- package/dist/htmlComic.d.ts.map +1 -1
- package/dist/htmlComic.js +2 -0
- package/dist/htmlComic.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/migrate/pageDesign.d.ts +35 -2
- package/dist/migrate/pageDesign.d.ts.map +1 -1
- package/dist/migrate/pageDesign.js +134 -7
- package/dist/migrate/pageDesign.js.map +1 -1
- package/dist/migrate/textToMarkdown.d.ts +33 -1
- package/dist/migrate/textToMarkdown.d.ts.map +1 -1
- package/dist/migrate/textToMarkdown.js +206 -9
- package/dist/migrate/textToMarkdown.js.map +1 -1
- package/dist/parse/blockParser.js +26 -0
- package/dist/parse/blockParser.js.map +1 -1
- package/dist/pipeline/build.d.ts.map +1 -1
- package/dist/pipeline/build.js +219 -40
- package/dist/pipeline/build.js.map +1 -1
- package/dist/pipeline/calloutLayout.d.ts +5 -0
- package/dist/pipeline/calloutLayout.d.ts.map +1 -1
- package/dist/pipeline/calloutLayout.js +70 -0
- package/dist/pipeline/calloutLayout.js.map +1 -1
- package/dist/pipeline/composedLayout.d.ts.map +1 -1
- package/dist/pipeline/composedLayout.js +246 -49
- package/dist/pipeline/composedLayout.js.map +1 -1
- package/dist/pipeline/contentWarnings.d.ts.map +1 -1
- package/dist/pipeline/contentWarnings.js +21 -1
- package/dist/pipeline/contentWarnings.js.map +1 -1
- package/dist/pipeline/dropCap.d.ts +5 -0
- package/dist/pipeline/dropCap.d.ts.map +1 -1
- package/dist/pipeline/dropCap.js +23 -2
- package/dist/pipeline/dropCap.js.map +1 -1
- package/dist/pipeline/frameLayout.d.ts +17 -2
- package/dist/pipeline/frameLayout.d.ts.map +1 -1
- package/dist/pipeline/frameLayout.js +47 -2
- package/dist/pipeline/frameLayout.js.map +1 -1
- package/dist/pipeline/headerFooter.d.ts.map +1 -1
- package/dist/pipeline/headerFooter.js +41 -2
- package/dist/pipeline/headerFooter.js.map +1 -1
- package/dist/pipeline/measureContentBlock.d.ts +1 -1
- package/dist/pipeline/measureContentBlock.d.ts.map +1 -1
- package/dist/pipeline/measureContentBlock.js +4 -1
- package/dist/pipeline/measureContentBlock.js.map +1 -1
- package/dist/pipeline/resourceNumbering.d.ts.map +1 -1
- package/dist/pipeline/resourceNumbering.js +13 -4
- package/dist/pipeline/resourceNumbering.js.map +1 -1
- package/dist/preflight.js +5 -1
- package/dist/preflight.js.map +1 -1
- package/dist/types.d.ts +32 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/vdt.d.ts +90 -2
- package/dist/vdt.d.ts.map +1 -1
- package/dist/vdt.js.map +1 -1
- package/package.json +1 -1
|
@@ -7,13 +7,14 @@ import { FRAME_ATTR } from '../composed/wrap';
|
|
|
7
7
|
import { framePlaceable, nextFrameOf, groupPlaceable, placeBox, unionRect } from '../composed/geometry';
|
|
8
8
|
import { composedOrder, groupOfFrames, layoutGroup } from '../composed/groups';
|
|
9
9
|
import { reflowEvents } from '../composed/reflowLog';
|
|
10
|
-
import { anchorTarget } from '../composed/templates';
|
|
11
|
-
import { continuationTemplate, continuesOffPage } from '../composed/continuation';
|
|
10
|
+
import { anchorTarget, resolveContinueIn } from '../composed/templates';
|
|
11
|
+
import { collapsedOnAddedPage, collapseFrames, continuationTemplate, continuesCollapsed, continuesOffPage, trailingFrames } from '../composed/continuation';
|
|
12
12
|
import { resolvePageTemplate } from '../composed/templates';
|
|
13
13
|
import { frameElementId } from '../composed/ids';
|
|
14
|
+
import { frameLinePx, frameRuleBlocks } from '../composed/rules';
|
|
14
15
|
import { offsetCalloutToAbsolute } from './calloutLayout';
|
|
15
16
|
import { isMarkerBlock } from './buildHelpers';
|
|
16
|
-
import { CUT_START, fragmentRange, makeCalloutLayouter, splitCalloutFragment } from './frameLayout';
|
|
17
|
+
import { CUT_START, fragmentRange, frameCutRules, makeCalloutLayouter, splitCalloutFragment } from './frameLayout';
|
|
17
18
|
const MM_PER_IN = 25.4;
|
|
18
19
|
const NO_FIT = { patches: new Map(), text: new Map(), pictures: new Map(), yieldAll: new Set(), goOn: new Set() };
|
|
19
20
|
/** Step of the text and picture scales the ladder tries (DESIGN §5.4). */
|
|
@@ -85,18 +86,87 @@ export function layoutComposedPage(given) {
|
|
|
85
86
|
const memo = new Map();
|
|
86
87
|
let runs = 0;
|
|
87
88
|
const keyOf = (tpl, fit) => JSON.stringify([tpl.id, [...fit.patches], [...fit.text], [...fit.pictures], [...fit.yieldAll], [...fit.goOn]]);
|
|
89
|
+
/** Frames a page added by continuation lays with no room (#859). */
|
|
90
|
+
const collapsedHere = input.continuing ? collapsedOnAddedPage(given.template, input.continuing) : new Set();
|
|
91
|
+
const holdsStory = (name) => input.stories.has(headOf(name));
|
|
92
|
+
/** The empty frames that go with the rest of a frame cut for a page
|
|
93
|
+
* laid from this template again (#912), by that frame. */
|
|
94
|
+
const travelling = (tpl, fit) => {
|
|
95
|
+
const out = new Map();
|
|
96
|
+
for (const f of tpl.frames) {
|
|
97
|
+
if (!fit.goOn.has(f.name) || !continuesCollapsed(tpl, f, input.continuing?.collapse ?? false))
|
|
98
|
+
continue;
|
|
99
|
+
const t = trailingFrames(tpl, f.name, holdsStory);
|
|
100
|
+
if (t.length > 0)
|
|
101
|
+
out.set(f.name, t);
|
|
102
|
+
}
|
|
103
|
+
return out;
|
|
104
|
+
};
|
|
88
105
|
const compose = (fit, tpl = template) => {
|
|
89
106
|
const key = keyOf(tpl, fit);
|
|
90
107
|
const known = memo.get(key);
|
|
91
108
|
if (known)
|
|
92
109
|
return known;
|
|
93
110
|
runs++;
|
|
94
|
-
const
|
|
111
|
+
const travel = travelling(tpl, fit);
|
|
112
|
+
const lay = (leaving, whole = new Set()) => composePage(input, collapseFrames(patchTemplate(tpl, fit.patches), leaving, whole), fit, leaving.size > 0 ? new Set([...collapsedHere, ...leaving]) : collapsedHere);
|
|
113
|
+
const all = new Map(travel);
|
|
114
|
+
let c = lay(new Set([...travel.values()].flat()));
|
|
115
|
+
// The empty frames go with the rest only when there is a rest: a frame
|
|
116
|
+
// that holds all of it once they leave keeps them after it…
|
|
117
|
+
const staying = [...travel.keys()].filter((f) => !c.spills.has(f));
|
|
118
|
+
if (staying.length > 0) {
|
|
119
|
+
for (const f of staying)
|
|
120
|
+
travel.delete(f);
|
|
121
|
+
c = lay(new Set([...travel.values()].flat()));
|
|
122
|
+
// …unless they then do not fit under it at their size: the whole box
|
|
123
|
+
// goes on with them, and takes no room here.
|
|
124
|
+
const whole = staying.filter((f) => squeezes(c, f));
|
|
125
|
+
if (whole.length > 0) {
|
|
126
|
+
for (const f of whole)
|
|
127
|
+
travel.set(f, all.get(f));
|
|
128
|
+
c = lay(new Set([...whole, ...[...travel.values()].flat()]), new Set(whole));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// A box none of whose content fits goes on whole and takes no room
|
|
132
|
+
// here either.
|
|
133
|
+
const empty = [...fit.goOn].filter((f) => { const sp = c.spills.get(f); return sp !== undefined && !sp.advanced && sp.pieces === 0 && !frameIn(c, f)?.collapsed; });
|
|
134
|
+
if (empty.length > 0) {
|
|
135
|
+
for (const f of empty)
|
|
136
|
+
if (all.has(f))
|
|
137
|
+
travel.set(f, all.get(f));
|
|
138
|
+
c = lay(new Set([...empty, ...[...travel.values()].flat()]), new Set(empty));
|
|
139
|
+
}
|
|
95
140
|
memo.set(key, c);
|
|
96
141
|
return c;
|
|
97
142
|
};
|
|
98
143
|
const frameIn = (c, name) => c.frames.find((f) => f.name === name);
|
|
99
144
|
const overflows = (c, name) => (frameIn(c, name)?.overflowPx ?? 0) > 0.5;
|
|
145
|
+
/** A frame that can go on to another page squeezes the frames after it
|
|
146
|
+
* in its stack below their declared size (#912): the stack reached the
|
|
147
|
+
* foot of its area and the last frames were cut to fit, an answer space
|
|
148
|
+
* under the box lost its lines. The ladder treats it as content that
|
|
149
|
+
* does not fit, so the box goes on and they keep their size. */
|
|
150
|
+
const squeezes = (c, name) => {
|
|
151
|
+
const frame = byName.get(name);
|
|
152
|
+
if (!frame || !continuesOffPage(frame.overflow.continueIn))
|
|
153
|
+
return false;
|
|
154
|
+
const g = groupOf.get(name);
|
|
155
|
+
if (!g || g.kind !== 'stack')
|
|
156
|
+
return false;
|
|
157
|
+
for (const other of g.frames.slice(g.frames.indexOf(name) + 1)) {
|
|
158
|
+
const f = byName.get(other);
|
|
159
|
+
const v = frameIn(c, other);
|
|
160
|
+
if (!f || !v || v.collapsed)
|
|
161
|
+
continue;
|
|
162
|
+
const min = f.minHeight ? dimensionToPx(f.minHeight, dpi, input.emPx) : fixedHeight(f) ? dimensionToPx(fixedHeight(f), dpi, input.emPx) : 0;
|
|
163
|
+
if (v.rect.height < min - 0.5)
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
return false;
|
|
167
|
+
};
|
|
168
|
+
/** The frame's content does not fit, or it squeezes the frames after it. */
|
|
169
|
+
const short = (c, name) => overflows(c, name) || squeezes(c, name);
|
|
100
170
|
/** The ladder's last step (#859): the frame is cut at its foot and the
|
|
101
171
|
* rest goes on on another page, its text and pictures back at full
|
|
102
172
|
* size (they go on anyway). */
|
|
@@ -123,7 +193,7 @@ export function layoutComposedPage(given) {
|
|
|
123
193
|
const attempt = (next, name) => {
|
|
124
194
|
fit = next;
|
|
125
195
|
cur = compose(fit);
|
|
126
|
-
return !
|
|
196
|
+
return !short(cur, name);
|
|
127
197
|
};
|
|
128
198
|
/** The largest scale among `steps` (descending) at which `name` fits,
|
|
129
199
|
* checked at the lowest first, then by bisection; adopted. */
|
|
@@ -136,7 +206,7 @@ export function layoutComposedPage(given) {
|
|
|
136
206
|
let hi = steps.length - 1; // fits at hi
|
|
137
207
|
while (lo < hi && runs < COMPOSE_BUDGET) {
|
|
138
208
|
const mid = Math.floor((lo + hi) / 2);
|
|
139
|
-
if (!
|
|
209
|
+
if (!short(compose(make(steps[mid])), name))
|
|
140
210
|
hi = mid;
|
|
141
211
|
else
|
|
142
212
|
lo = mid + 1;
|
|
@@ -196,7 +266,7 @@ export function layoutComposedPage(given) {
|
|
|
196
266
|
};
|
|
197
267
|
for (const frame of template.frames) {
|
|
198
268
|
const name = frame.name;
|
|
199
|
-
if (!
|
|
269
|
+
if (!short(cur, name) || runs >= COMPOSE_BUDGET)
|
|
200
270
|
continue;
|
|
201
271
|
const steps = [];
|
|
202
272
|
tried.set(name, steps);
|
|
@@ -211,38 +281,57 @@ export function layoutComposedPage(given) {
|
|
|
211
281
|
if (movesOthers(frame))
|
|
212
282
|
steps.push('push');
|
|
213
283
|
// 3. Pictures of the frame and its group, down to imageMinScale.
|
|
214
|
-
const
|
|
215
|
-
|
|
284
|
+
const scaleImages = () => {
|
|
285
|
+
const heads = frame.fit.scaleImages ? pictureHeads(frame) : [];
|
|
286
|
+
if (heads.length === 0 || frame.fit.imageMinScale >= 1)
|
|
287
|
+
return false;
|
|
216
288
|
steps.push('scaleImages');
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
}
|
|
289
|
+
return searchScale(scaleSteps(frame.fit.imageMinScale), (s) => withPictures(fit, heads, s, name), name);
|
|
290
|
+
};
|
|
220
291
|
// 4. Redistribute: every other frame of the group gives space (or
|
|
221
292
|
// width) back, down to its minimum or its content.
|
|
222
|
-
const
|
|
223
|
-
|
|
293
|
+
const redistribute = () => {
|
|
294
|
+
const g = groupOf.get(name);
|
|
295
|
+
if (!g || g.frames.filter((m) => byName.has(m)).length <= 1)
|
|
296
|
+
return false;
|
|
224
297
|
steps.push('redistribute');
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
}
|
|
298
|
+
return attempt({ ...fit, yieldAll: new Set([...fit.yieldAll, g.name]) }, name);
|
|
299
|
+
};
|
|
228
300
|
// 5. The frame's text (its whole story), down to fit.minScale.
|
|
229
|
-
|
|
301
|
+
const shrinkText = () => {
|
|
302
|
+
if (!frame.fit.shrinkText || frame.fit.minScale >= 1 || !holdsText(frame))
|
|
303
|
+
return false;
|
|
230
304
|
steps.push('shrinkText');
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
//
|
|
236
|
-
//
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
305
|
+
return searchScale(scaleSteps(frame.fit.minScale), (s) => withText(fit, headOf(name), s), name);
|
|
306
|
+
};
|
|
307
|
+
// 6. Continuation on another page (`overflow.continueIn: 'next-page'`,
|
|
308
|
+
// `'template:<id>'` or `'page:<id>'`, #859). On a page added by
|
|
309
|
+
// continuation, a frame that would take none of what it receives
|
|
310
|
+
// sends nothing on (it would go on for ever): it warns.
|
|
311
|
+
const goOn = () => {
|
|
312
|
+
if (!continuesOffPage(frame.overflow.continueIn))
|
|
313
|
+
return false;
|
|
240
314
|
steps.push('continue');
|
|
241
315
|
const before = { fit, cur };
|
|
242
|
-
|
|
243
|
-
|
|
316
|
+
// (Only for a story that came from another page: a page's own story
|
|
317
|
+
// may go on whole.)
|
|
318
|
+
const received = input.continuing?.receivers.has(headOf(name)) ?? false;
|
|
319
|
+
if (attempt(goingOn(fit, frame), name) && (!received || cur.spills.get(name)?.advanced !== false))
|
|
320
|
+
return true;
|
|
244
321
|
({ fit, cur } = before);
|
|
245
|
-
|
|
322
|
+
return false;
|
|
323
|
+
};
|
|
324
|
+
// A frame whose content can go on to another page goes on before its
|
|
325
|
+
// pictures and text shrink (`fit.preferContinue`, #920): a story keeps
|
|
326
|
+
// one size from page to page. The pictures and the text shrink only
|
|
327
|
+
// when it cannot go on (the last page continuation may add, or a
|
|
328
|
+
// receiver that takes none of it).
|
|
329
|
+
const order = continuesOffPage(frame.overflow.continueIn) && frame.fit.preferContinue
|
|
330
|
+
? [redistribute, goOn, scaleImages, shrinkText]
|
|
331
|
+
: [scaleImages, redistribute, shrinkText, goOn];
|
|
332
|
+
for (const step of order)
|
|
333
|
+
if (step())
|
|
334
|
+
break;
|
|
246
335
|
}
|
|
247
336
|
// 7. Warn, with what would make each frame that still overflows fit.
|
|
248
337
|
const warnings = [...(cur.notes ?? [])];
|
|
@@ -308,6 +397,7 @@ export function layoutComposedPage(given) {
|
|
|
308
397
|
};
|
|
309
398
|
// What goes on on other pages (#859), in template order.
|
|
310
399
|
const continuations = [];
|
|
400
|
+
const trailing = new Map([...travelling(template, fit)].filter(([f, names]) => cur.spills.has(f) && names.every((n) => frameIn(cur, n)?.collapsed)));
|
|
311
401
|
for (const frame of template.frames) {
|
|
312
402
|
const spill = cur.spills.get(frame.name);
|
|
313
403
|
const story = spill ? input.stories.get(spill.head) : undefined;
|
|
@@ -317,14 +407,19 @@ export function layoutComposedPage(given) {
|
|
|
317
407
|
continuations.push({
|
|
318
408
|
frame: frame.name,
|
|
319
409
|
fromFrameId: spill.frameId,
|
|
320
|
-
|
|
410
|
+
head: spill.head,
|
|
411
|
+
// `{attr.x}` read from the fence (#917).
|
|
412
|
+
rule: resolveContinueIn(frame.overflow.continueIn, fence.attrs),
|
|
321
413
|
template: template.id,
|
|
322
414
|
collapsed: input.continuing?.collapse ?? false,
|
|
323
415
|
story,
|
|
324
416
|
cut: spill.cut,
|
|
325
417
|
pieces: spill.pieces,
|
|
326
418
|
headBlockId: spill.headBlockId,
|
|
327
|
-
|
|
419
|
+
// A story that jumped here (#917) goes on named by this page's frame.
|
|
420
|
+
slot: (input.continuing?.jump ? undefined : came?.slot) ?? frame.name,
|
|
421
|
+
...(trailing.has(frame.name) ? { trailing: trailing.get(frame.name) } : {}),
|
|
422
|
+
...(frame.overflow.fromMark !== undefined ? { fromMark: frame.overflow.fromMark } : {}),
|
|
328
423
|
});
|
|
329
424
|
}
|
|
330
425
|
return { composed, blocks, warnings, laid, ...(fitted.size > 0 ? { fitted } : {}), ...(continuations.length > 0 ? { continuations } : {}) };
|
|
@@ -359,9 +454,12 @@ function overflowProposals(c) {
|
|
|
359
454
|
...(frame.fit.shrinkText ? {} : { also: [{ path: path('fit/shrinkText'), value: true }] }),
|
|
360
455
|
});
|
|
361
456
|
}
|
|
457
|
+
// A frame that holds content (an empty one is short of its own box, #911:
|
|
458
|
+
// more height, text or pages do not help it).
|
|
459
|
+
const holds = cur.needs.has(name);
|
|
362
460
|
// A higher maximum: the frame's height plus the shortfall, in whole mm.
|
|
363
461
|
const fixed = fixedHeight(frame);
|
|
364
|
-
if (frame.maxHeight || fixed) {
|
|
462
|
+
if (holds && (frame.maxHeight || fixed)) {
|
|
365
463
|
const want = Math.ceil((vdt.rect.height + vdt.overflowPx) / mmPx - 1e-6);
|
|
366
464
|
const patch = { maxHeight: mmDim(want), ...(fixed ? { height: 'auto', minHeight: fixed } : {}) };
|
|
367
465
|
if (fits(c.patched(fit, name, patch)))
|
|
@@ -374,7 +472,9 @@ function overflowProposals(c) {
|
|
|
374
472
|
if (g) {
|
|
375
473
|
for (const other of g.frames) {
|
|
376
474
|
const f = c.byName.get(other);
|
|
377
|
-
|
|
475
|
+
// An empty frame's minimum is the room it stands for (an answer
|
|
476
|
+
// space, a picture slot), not room to take (#911).
|
|
477
|
+
if (!f || other === name || f.pin || !f.minHeight || !cur.needs.has(other))
|
|
378
478
|
continue;
|
|
379
479
|
const box = cur.frames.find((x) => x.name === other);
|
|
380
480
|
if (!box)
|
|
@@ -391,8 +491,16 @@ function overflowProposals(c) {
|
|
|
391
491
|
}
|
|
392
492
|
}
|
|
393
493
|
}
|
|
494
|
+
// An empty frame cut short by its group: a lower minimum of its own, the
|
|
495
|
+
// height it was left (#911).
|
|
496
|
+
if (!holds && g && frame.minHeight) {
|
|
497
|
+
const lowered = Math.floor(vdt.rect.height / mmPx + 1e-6);
|
|
498
|
+
if (lowered * mmPx < dimensionToPx(frame.minHeight, c.dpi, c.emPx) - 0.5 && fits(c.patched(fit, name, { minHeight: mmDim(lowered) }))) {
|
|
499
|
+
out.push({ kind: 'lowerMin', path: path('minHeight'), value: mmDim(lowered), frame: name });
|
|
500
|
+
}
|
|
501
|
+
}
|
|
394
502
|
// Continue on the next page (#859 lays it out).
|
|
395
|
-
if (!frame.overflow.continueIn)
|
|
503
|
+
if (holds && !frame.overflow.continueIn)
|
|
396
504
|
out.push({ kind: 'continueNextPage', path: path('overflow/continueIn'), value: 'next-page' });
|
|
397
505
|
// Another template of the book with a frame of this name, where the
|
|
398
506
|
// content fits as it is.
|
|
@@ -447,14 +555,15 @@ export function keepChromeAt(style, scale) {
|
|
|
447
555
|
};
|
|
448
556
|
}
|
|
449
557
|
/** Lay out every frame of the page once, with the reflow ladder's `fit`. */
|
|
450
|
-
function composePage(input, template, fit) {
|
|
558
|
+
function composePage(input, template, fit, collapsed) {
|
|
451
559
|
const { pass, fence, dpi } = input;
|
|
452
560
|
const fi = fence.fenceIndex;
|
|
453
561
|
const cont = input.continuing;
|
|
562
|
+
const cutRules = frameCutRules(pass.resolved);
|
|
454
563
|
/** A frame's id: `cp<fence>:<name>`; on a page added by continuation
|
|
455
564
|
* (#859) `~<k>`, a frame that receives content named by the frame of
|
|
456
565
|
* the fence's page that first sent it on. */
|
|
457
|
-
const frameIdOf = (name) => (cont ? frameElementId(fi, cont.receivers.get(name)?.slot ?? name, cont.generation) : frameElementId(fi, name));
|
|
566
|
+
const frameIdOf = (name) => (cont && !cont.jump ? frameElementId(fi, cont.receivers.get(name)?.slot ?? name, cont.generation) : frameElementId(fi, name));
|
|
458
567
|
const byName = new Map(template.frames.map((f) => [f.name, f]));
|
|
459
568
|
const prev = chainPrev(template, cont?.receivers);
|
|
460
569
|
/** The head of the chain a frame belongs to. */
|
|
@@ -469,6 +578,11 @@ function composePage(input, template, fit) {
|
|
|
469
578
|
};
|
|
470
579
|
/** The text scale of a frame's story (#858). */
|
|
471
580
|
const textScale = (frame) => fit.text.get(headOf(frame.name)) ?? 1;
|
|
581
|
+
/** A page number a mark's `{page}` is laid out with (#917): a guess of
|
|
582
|
+
* the right width, the build writing the true one once pages are
|
|
583
|
+
* numbered (`VDTDesignTextBlock.pageMark`). */
|
|
584
|
+
const toGuess = String(input.page.index + 2);
|
|
585
|
+
const fromGuess = String(Math.max(1, input.page.index));
|
|
472
586
|
/** The style a frame is laid out in: its box as drawn at any text scale. */
|
|
473
587
|
const styleOf = (frame) => {
|
|
474
588
|
const style = keepChromeAt(input.styleOf(frame), textScale(frame));
|
|
@@ -477,7 +591,15 @@ function composePage(input, template, fit) {
|
|
|
477
591
|
// A frame cut for another page (#859) ends with its mark: its own
|
|
478
592
|
// words, none (`false`), or its style's localized ones.
|
|
479
593
|
const mark = frame.overflow.mark;
|
|
480
|
-
return { ...style, continuesMarkerEnabled: mark !== false, continuesMarker: typeof mark === 'string' ? mark : style.continuesMarker };
|
|
594
|
+
return { ...style, continuesMarkerEnabled: mark !== false, continuesMarker: typeof mark === 'string' ? withPage(mark, toGuess) : style.continuesMarker };
|
|
595
|
+
};
|
|
596
|
+
/** The mark of a frame that receives a story from another page (#917):
|
|
597
|
+
* its own `overflow.fromMark`, else the sending frame's, set at the
|
|
598
|
+
* head of the first piece it lays here. */
|
|
599
|
+
const fromMarkOf = (frame) => {
|
|
600
|
+
const came = cont?.receivers.get(headOf(frame.name));
|
|
601
|
+
const words = frame.overflow.fromMark ?? came?.fromMark;
|
|
602
|
+
return came && words !== undefined ? withPage(words, fromGuess) : undefined;
|
|
481
603
|
};
|
|
482
604
|
/** The scale of a frame's pictures (#858), below 1, or undefined. */
|
|
483
605
|
const pictureScale = (frame) => fit.pictures.get(headOf(frame.name))?.scale;
|
|
@@ -542,6 +664,8 @@ function composePage(input, template, fit) {
|
|
|
542
664
|
const declaredRefOf = (name) => declared.get(name) ?? groupRect(name, declared, groupDeclared, declaredRefOf);
|
|
543
665
|
/** Pinned frames laid so far: a group's frames flow round them. */
|
|
544
666
|
const pinned = [];
|
|
667
|
+
/** How far a stack cut each frame below its least height (#911). */
|
|
668
|
+
const boxShort = new Map();
|
|
545
669
|
const frames = [];
|
|
546
670
|
const vdtByName = new Map();
|
|
547
671
|
const blocks = [];
|
|
@@ -591,7 +715,10 @@ function composePage(input, template, fit) {
|
|
|
591
715
|
const holds = reached && !atEnd(st);
|
|
592
716
|
const continuation = st !== undefined && st.pieces > 0;
|
|
593
717
|
const blockId = st && st.pieces > 0 ? `${st.headBlockId}-cont-${st.pieces}` : frameIdOf(frame.name);
|
|
594
|
-
|
|
718
|
+
// The first piece here of a story that came from another page.
|
|
719
|
+
const came = cont?.receivers.get(headOf(frame.name));
|
|
720
|
+
const fromMark = st && came && continuation && st.pieces === came.pieces ? fromMarkOf(frame) : undefined;
|
|
721
|
+
return { frame, st, before, holds, continuation, blockId, ...(fromMark !== undefined ? { fromMark } : {}) };
|
|
595
722
|
};
|
|
596
723
|
/** The content's height at `width`, running round the pushing frames
|
|
597
724
|
* below the top of `at` (the frame's box as first placed). A frame
|
|
@@ -609,8 +736,8 @@ function composePage(input, template, fit) {
|
|
|
609
736
|
if (known !== undefined)
|
|
610
737
|
return known;
|
|
611
738
|
const exclusions = at ? unscale(exclusionsFor(p.frame, { ...at, width }, true), s) : undefined;
|
|
612
|
-
const opts = { ...(exclusions ? { exclusions } : {}), ...(pic !== undefined ? { pictureScale: pic } : {}) };
|
|
613
|
-
const r = p.st.L.layoutRange(p.st.cut, p.st.L.end, width / s, p.blockId, p.continuation, input.mirrored, opts.exclusions || opts.pictureScale !== undefined ? opts : undefined);
|
|
739
|
+
const opts = { ...(exclusions ? { exclusions } : {}), ...(pic !== undefined ? { pictureScale: pic } : {}), ...(p.fromMark !== undefined ? { continuedMark: p.fromMark } : {}) };
|
|
740
|
+
const r = p.st.L.layoutRange(p.st.cut, p.st.L.end, width / s, p.blockId, p.continuation, input.mirrored, opts.exclusions || opts.pictureScale !== undefined || opts.continuedMark !== undefined ? opts : undefined);
|
|
614
741
|
const h = r.totalHeight * s;
|
|
615
742
|
memo.set(key, h);
|
|
616
743
|
return h;
|
|
@@ -707,6 +834,7 @@ function composePage(input, template, fit) {
|
|
|
707
834
|
pin: f.pin,
|
|
708
835
|
fixedHeight: !auto && !fill,
|
|
709
836
|
need: natural,
|
|
837
|
+
floor: minH,
|
|
710
838
|
};
|
|
711
839
|
if (yieldAll && mode === 'final' && !f.pin) {
|
|
712
840
|
// Down to its minimum, never under what its content needs, never
|
|
@@ -718,6 +846,14 @@ function composePage(input, template, fit) {
|
|
|
718
846
|
if (group.kind === 'stack')
|
|
719
847
|
item.min = Math.min(height, Math.max(minH, natural(box.width)));
|
|
720
848
|
}
|
|
849
|
+
if (fit.goOn.has(f.name) && mode === 'final' && !f.pin) {
|
|
850
|
+
// A frame cut for another page (#859) gives the room first,
|
|
851
|
+
// down to its minimum: the frames after it in the group keep
|
|
852
|
+
// their size (#912), and its rest goes on.
|
|
853
|
+
item.shrink = Math.max(f.shrink, 1);
|
|
854
|
+
item.priority = Number.NEGATIVE_INFINITY;
|
|
855
|
+
item.min = minH;
|
|
856
|
+
}
|
|
721
857
|
return item;
|
|
722
858
|
});
|
|
723
859
|
const firstFree = items.find((it) => !it.pin) ?? items[0];
|
|
@@ -739,7 +875,7 @@ function composePage(input, template, fit) {
|
|
|
739
875
|
for (const it of items)
|
|
740
876
|
if (it.pin)
|
|
741
877
|
out.set(it.name, it.own);
|
|
742
|
-
return { rects: out, box: ownBox ?? unionRect([...out.values()]) ?? box };
|
|
878
|
+
return { rects: out, box: ownBox ?? unionRect([...out.values()]) ?? box, items };
|
|
743
879
|
};
|
|
744
880
|
let naturals = preps.map((p) => naturalOf(p));
|
|
745
881
|
let fin = solve('final', naturals);
|
|
@@ -751,6 +887,20 @@ function composePage(input, template, fit) {
|
|
|
751
887
|
fin = solve('final', naturals);
|
|
752
888
|
}
|
|
753
889
|
const decl = solve('declared', naturals);
|
|
890
|
+
// A frame the stack cut below the least it may have (its
|
|
891
|
+
// `minHeight`, a fixed height its own) is short of its box, content
|
|
892
|
+
// or none (#911): an empty answer space or picture slot overflows
|
|
893
|
+
// too.
|
|
894
|
+
for (const it of fin.items) {
|
|
895
|
+
if (it.pin || group.kind !== 'stack')
|
|
896
|
+
continue;
|
|
897
|
+
const least = it.fixedHeight && (it.floor ?? 0) <= 0.5 ? it.own.height : it.floor ?? 0;
|
|
898
|
+
const got = fin.rects.get(it.name).height;
|
|
899
|
+
if (least - got > 0.5)
|
|
900
|
+
boxShort.set(it.name, least - got);
|
|
901
|
+
else
|
|
902
|
+
boxShort.delete(it.name);
|
|
903
|
+
}
|
|
754
904
|
for (const m of members) {
|
|
755
905
|
rects.set(m.name, fin.rects.get(m.name));
|
|
756
906
|
declared.set(m.name, decl.rects.get(m.name));
|
|
@@ -783,7 +933,7 @@ function composePage(input, template, fit) {
|
|
|
783
933
|
let known;
|
|
784
934
|
needs.set(frame.name, () => (known ??= naturalOf(startAt)(width)));
|
|
785
935
|
const exclusions = unscale(exclusionsFor(frame, rect, false), s);
|
|
786
|
-
const extra = { ...(exclusions ? { exclusions } : {}), ...(pic !== undefined ? { pictureScale: pic } : {}) };
|
|
936
|
+
const extra = { ...(exclusions ? { exclusions } : {}), ...(pic !== undefined ? { pictureScale: pic } : {}), ...(p.fromMark !== undefined ? { continuedMark: p.fromMark } : {}) };
|
|
787
937
|
const opts = { boxHeight: laidH, verticalAlign: frame.verticalAlign, ...extra };
|
|
788
938
|
const whole = st.L.layoutRange(from, st.L.end, laidW, blockId, continuation, input.mirrored, opts);
|
|
789
939
|
const nextName = nextFrameOf(frame);
|
|
@@ -795,13 +945,13 @@ function composePage(input, template, fit) {
|
|
|
795
945
|
// The rest goes on in the next frame of the chain, or on another
|
|
796
946
|
// page.
|
|
797
947
|
const minLines = Math.max(1, style.splitMinLines);
|
|
798
|
-
|
|
948
|
+
// A heading stays with what follows it, a list keeps two items
|
|
949
|
+
// on each side of the cut (#913).
|
|
950
|
+
const frag = splitCalloutFragment(pass, st.L, from, laidW, laidH, blockId, continuation, minLines, input.mirrored, extra.exclusions || extra.pictureScale !== undefined || extra.continuedMark !== undefined ? extra : undefined, cutRules);
|
|
799
951
|
const to = frag?.to ?? from;
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
// (and its mark) when the content goes on elsewhere.
|
|
804
|
-
: goesOn && frame.style ? st.L.layoutRange(from, from, laidW, blockId, continuation, input.mirrored, { boxHeight: laidH }) : undefined;
|
|
952
|
+
// A frame none of whose content fits draws nothing: the whole box
|
|
953
|
+
// goes on (#912), not a tab and a mark over an empty piece.
|
|
954
|
+
result = frag ? st.L.layoutRange(from, to, laidW, blockId, continuation, input.mirrored, opts) : undefined;
|
|
805
955
|
st.cut = to;
|
|
806
956
|
}
|
|
807
957
|
else {
|
|
@@ -815,6 +965,26 @@ function composePage(input, template, fit) {
|
|
|
815
965
|
// A styled frame with nothing (left) to hold still draws its box.
|
|
816
966
|
result = st.L.layoutRange(st.L.end, st.L.end, laidW, blockId, true, input.mirrored, { boxHeight: laidH });
|
|
817
967
|
}
|
|
968
|
+
// A frame cut below its least height overflows by the cut, holding
|
|
969
|
+
// content or not (#911).
|
|
970
|
+
overflowPx = Math.max(overflowPx, boxShort.get(frame.name) ?? 0);
|
|
971
|
+
// Ruled lines (#914): on the box, over its background, in its
|
|
972
|
+
// laid-out coordinates; an empty frame keeps them for the decoration.
|
|
973
|
+
let emptyRules;
|
|
974
|
+
if (frame.rules) {
|
|
975
|
+
const linePx = frameLinePx(style, dpi);
|
|
976
|
+
if (result?.frame.designOverlay && result.frame.callout) {
|
|
977
|
+
result.frame.designOverlay.blocks.push(...frameRuleBlocks(frame.rules, result.frame.callout.innerRect, linePx, s, dpi, input.emPx));
|
|
978
|
+
}
|
|
979
|
+
else if (!result) {
|
|
980
|
+
const pad = (d) => dimensionToPx(d, dpi, input.emPx);
|
|
981
|
+
const p = style.padding;
|
|
982
|
+
const inner = { x: rect.x + pad(p.left), y: rect.y + pad(p.top), width: rect.width - pad(p.left) - pad(p.right), height: rect.height - pad(p.top) - pad(p.bottom) };
|
|
983
|
+
const blocks = frameRuleBlocks(frame.rules, inner, linePx, 1, dpi, input.emPx);
|
|
984
|
+
if (blocks.length > 0)
|
|
985
|
+
emptyRules = blocks;
|
|
986
|
+
}
|
|
987
|
+
}
|
|
818
988
|
const vdt = {
|
|
819
989
|
id: frameIdOf(frame.name),
|
|
820
990
|
name: frame.name,
|
|
@@ -828,6 +998,8 @@ function composePage(input, template, fit) {
|
|
|
828
998
|
blockIds: [],
|
|
829
999
|
configPath: frame.configPath,
|
|
830
1000
|
...(frame.exclude === 'push' ? { push: true } : {}),
|
|
1001
|
+
...(collapsed.has(frame.name) ? { collapsed: true } : {}),
|
|
1002
|
+
...(emptyRules ? { rules: emptyRules } : {}),
|
|
831
1003
|
};
|
|
832
1004
|
const decl = declared.get(frame.name);
|
|
833
1005
|
if (decl && !sameRect(decl, rect))
|
|
@@ -842,6 +1014,14 @@ function composePage(input, template, fit) {
|
|
|
842
1014
|
// Content from the page before (#859).
|
|
843
1015
|
vdt.continuedFrom = cont.receivers.get(frame.name).fromFrameId;
|
|
844
1016
|
}
|
|
1017
|
+
if (result) {
|
|
1018
|
+
// The marks whose `{page}` the build fills in (#917).
|
|
1019
|
+
if (goesOn && typeof frame.overflow.mark === 'string' && frame.overflow.mark.includes('{page}'))
|
|
1020
|
+
tagPageMark(result.frame, withPage(frame.overflow.mark, toGuess), frame.overflow.mark, 'to');
|
|
1021
|
+
const fromWords = frame.overflow.fromMark ?? cont?.receivers.get(headOf(frame.name))?.fromMark;
|
|
1022
|
+
if (p.fromMark !== undefined && fromWords?.includes('{page}'))
|
|
1023
|
+
tagPageMark(result.frame, p.fromMark, fromWords, 'from');
|
|
1024
|
+
}
|
|
845
1025
|
if (result && st) {
|
|
846
1026
|
const range = fragmentRange(st.L, from, st.cut);
|
|
847
1027
|
commitFrame(result, rect, st.story, range, input, vdt, blocks);
|
|
@@ -857,6 +1037,8 @@ function composePage(input, template, fit) {
|
|
|
857
1037
|
fitLog.push({ frame: frame.name, kind: 'textScaled', scale: s });
|
|
858
1038
|
}
|
|
859
1039
|
if (goesOn && st) {
|
|
1040
|
+
// Laid here even when none of it fits: the rest goes on (#912).
|
|
1041
|
+
laid.add(headOf(frame.name));
|
|
860
1042
|
spills.set(frame.name, { head: headOf(frame.name), cut: st.cut, advanced: !sameCut(from, st.cut), pieces: st.pieces, headBlockId: st.headBlockId, frameId: vdt.id });
|
|
861
1043
|
}
|
|
862
1044
|
if (overflowPx > 0.5) {
|
|
@@ -1072,4 +1254,19 @@ export function composedPageAt(pages, idx) {
|
|
|
1072
1254
|
return p;
|
|
1073
1255
|
return undefined;
|
|
1074
1256
|
}
|
|
1257
|
+
/** `words` with `{page}` as `page` (#917). */
|
|
1258
|
+
const withPage = (words, page) => words.split('{page}').join(page);
|
|
1259
|
+
/** Mark the design text of `box` that sets `shown` as a continuation mark
|
|
1260
|
+
* whose `{page}` the build fills in once pages are numbered (#917). */
|
|
1261
|
+
function tagPageMark(box, shown, text, page) {
|
|
1262
|
+
const want = shown.trim();
|
|
1263
|
+
for (const b of box.designOverlay?.blocks ?? []) {
|
|
1264
|
+
if (b.kind !== 'text' || !b.artifact || b.pageMark)
|
|
1265
|
+
continue;
|
|
1266
|
+
if (b.lines.map((l) => l.text).join(' ').trim() !== want && b.lines.map((l) => l.text).join('').trim() !== want)
|
|
1267
|
+
continue;
|
|
1268
|
+
b.pageMark = { text: text.trim(), page };
|
|
1269
|
+
return;
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1075
1272
|
//# sourceMappingURL=composedLayout.js.map
|