postext 1.50.0 → 1.51.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__/composed/fixtures/moduleNesting.d.ts +25 -0
- package/dist/__tests__/composed/fixtures/moduleNesting.d.ts.map +1 -0
- package/dist/__tests__/composed/fixtures/moduleNesting.js +36 -0
- package/dist/__tests__/composed/fixtures/moduleNesting.js.map +1 -0
- package/dist/__tests__/composed/moduleNesting.test.d.ts +2 -0
- package/dist/__tests__/composed/moduleNesting.test.d.ts.map +1 -0
- package/dist/__tests__/composed/moduleNesting.test.js +177 -0
- package/dist/__tests__/composed/moduleNesting.test.js.map +1 -0
- package/dist/__tests__/composed/moduleRows.test.js +9 -3
- package/dist/__tests__/composed/moduleRows.test.js.map +1 -1
- package/dist/__tests__/exports.test.js +1 -0
- package/dist/__tests__/exports.test.js.map +1 -1
- package/dist/composed/groups.d.ts.map +1 -1
- package/dist/composed/groups.js +9 -1
- package/dist/composed/groups.js.map +1 -1
- package/dist/composed/modules.d.ts +9 -0
- package/dist/composed/modules.d.ts.map +1 -1
- package/dist/composed/modules.js +38 -4
- package/dist/composed/modules.js.map +1 -1
- package/dist/composed/templates.d.ts +3 -0
- package/dist/composed/templates.d.ts.map +1 -1
- package/dist/composed/templates.js +15 -7
- package/dist/composed/templates.js.map +1 -1
- package/dist/composed/types.d.ts +26 -5
- package/dist/composed/types.d.ts.map +1 -1
- package/dist/composed/validate.d.ts.map +1 -1
- package/dist/composed/validate.js +20 -4
- package/dist/composed/validate.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/pipeline/composedLayout.d.ts.map +1 -1
- package/dist/pipeline/composedLayout.js +193 -85
- package/dist/pipeline/composedLayout.js.map +1 -1
- package/dist/vdt.d.ts +4 -0
- package/dist/vdt.d.ts.map +1 -1
- package/dist/vdt.js.map +1 -1
- package/package.json +1 -1
|
@@ -46,7 +46,7 @@ import { collapsedOnAddedPage, collapseFrames, continuationTemplate, continuesCo
|
|
|
46
46
|
import { isModuleTemplate, resolvePageTemplate } from '../composed/templates';
|
|
47
47
|
import { frameElementId } from '../composed/ids';
|
|
48
48
|
import { expandRepeats, instanceOf, repeatItemsOf } from '../composed/repeat';
|
|
49
|
-
import { moduleOfFrame } from '../composed/modules';
|
|
49
|
+
import { moduleOfFrame, nestedChain } from '../composed/modules';
|
|
50
50
|
import { frameLinePx, frameRuleBlocks } from '../composed/rules';
|
|
51
51
|
import { overlapChecks } from '../composed/overlap';
|
|
52
52
|
import { offsetCalloutToAbsolute } from './calloutLayout';
|
|
@@ -1029,6 +1029,12 @@ function composePage(pageInput, template, fit, collapsed) {
|
|
|
1029
1029
|
const id = input.stories.get(headOf(frame.name))?.plan.attrs.look?.trim();
|
|
1030
1030
|
return id ? frameLooks.find((l) => l.id === id) : undefined;
|
|
1031
1031
|
};
|
|
1032
|
+
/** The look a frame's story names that `frameLooks` does not have
|
|
1033
|
+
* (#1095): the canvas marks the frame. */
|
|
1034
|
+
const unknownLookOf = (frame) => {
|
|
1035
|
+
const id = input.stories.get(headOf(frame.name))?.plan.attrs.look?.trim();
|
|
1036
|
+
return id && !frameLooks?.some((l) => l.id === id) ? id : undefined;
|
|
1037
|
+
};
|
|
1032
1038
|
/** The style a frame is laid out in: its box as drawn at any text scale. */
|
|
1033
1039
|
const styleOf = (frame) => {
|
|
1034
1040
|
const style = keepChromeAt(input.styleOf(withNamedLook(frame, namedLookOf(frame))), textScale(frame));
|
|
@@ -1163,6 +1169,9 @@ function composePage(pageInput, template, fit, collapsed) {
|
|
|
1163
1169
|
const moduleRects = new Map();
|
|
1164
1170
|
/** The foot a module cut at its group's foot is clipped to (#1062). */
|
|
1165
1171
|
let clipFoot;
|
|
1172
|
+
/** A module a stretching row lays taller than it is (#1095): its
|
|
1173
|
+
* frames, its own foot (`at`) and the row's. */
|
|
1174
|
+
let stretchTo;
|
|
1166
1175
|
const pushed = seed
|
|
1167
1176
|
? [...seed].map(([name, box]) => ({ name, box, ...(seedShapes?.get(name) ? { contour: seedShapes.get(name) } : {}) }))
|
|
1168
1177
|
: [];
|
|
@@ -1760,6 +1769,7 @@ function composePage(pageInput, template, fit, collapsed) {
|
|
|
1760
1769
|
...(unmirroredAt(frame) !== undefined ? { unmirrorX: unmirroredAt(frame) } : {}),
|
|
1761
1770
|
layer: frame.layer,
|
|
1762
1771
|
...(frame.style ? { styleId: frame.style } : {}),
|
|
1772
|
+
...(holds && unknownLookOf(frame) !== undefined ? { lookUnknown: unknownLookOf(frame) } : {}),
|
|
1763
1773
|
scale: s,
|
|
1764
1774
|
...(pic !== undefined && holds ? { imageScale: pic } : {}),
|
|
1765
1775
|
overflowPx,
|
|
@@ -1852,6 +1862,27 @@ function composePage(pageInput, template, fit, collapsed) {
|
|
|
1852
1862
|
rects.set(name, out);
|
|
1853
1863
|
return out;
|
|
1854
1864
|
};
|
|
1865
|
+
/** A module's `'auto'` box that ends at the module's foot, in a row
|
|
1866
|
+
* that stretches the module (#1095): to the row's foot, its declared
|
|
1867
|
+
* box by as much (the template asks for it). A frame as wide as its
|
|
1868
|
+
* content (a pill, a tab) keeps its height. */
|
|
1869
|
+
const stretchAuto = (name, r) => {
|
|
1870
|
+
const s = stretchTo;
|
|
1871
|
+
if (!s || !s.names.has(name))
|
|
1872
|
+
return r;
|
|
1873
|
+
const f = byName.get(name);
|
|
1874
|
+
if (!f || f.height !== 'auto' || f.width === 'auto' || f.pin || heldByFoot(f))
|
|
1875
|
+
return r;
|
|
1876
|
+
const bottom = r.y + r.height;
|
|
1877
|
+
if (Math.abs(bottom - s.at) > 0.5 || s.foot - bottom <= 0.01)
|
|
1878
|
+
return r;
|
|
1879
|
+
const out = { ...r, height: s.foot - r.y };
|
|
1880
|
+
rects.set(name, out);
|
|
1881
|
+
const d = declared.get(name);
|
|
1882
|
+
if (d)
|
|
1883
|
+
declared.set(name, { ...d, height: d.height + (s.foot - bottom) });
|
|
1884
|
+
return out;
|
|
1885
|
+
};
|
|
1855
1886
|
/** The frames of `names` whose content goes on whole on another page
|
|
1856
1887
|
* (#1061, #1062): none of it is laid here. */
|
|
1857
1888
|
const spillWhole = (names, advanced, lastLaid) => {
|
|
@@ -1868,7 +1899,7 @@ function composePage(pageInput, template, fit, collapsed) {
|
|
|
1868
1899
|
const runStep = (step, filling) => {
|
|
1869
1900
|
if (step.kind === 'frame') {
|
|
1870
1901
|
const p = prepare(step.frame);
|
|
1871
|
-
const r = clipAtFoot(step.frame.name, placeFrame(p));
|
|
1902
|
+
const r = clipAtFoot(step.frame.name, stretchAuto(step.frame.name, placeFrame(p)));
|
|
1872
1903
|
if (filling)
|
|
1873
1904
|
fill(p, r);
|
|
1874
1905
|
return;
|
|
@@ -1889,7 +1920,7 @@ function composePage(pageInput, template, fit, collapsed) {
|
|
|
1889
1920
|
let lastLaid;
|
|
1890
1921
|
for (const f of step.frames) {
|
|
1891
1922
|
if (!grid.spilled.has(f.name)) {
|
|
1892
|
-
fill(prepare(f), clipAtFoot(f.name, grid.rects.get(f.name)));
|
|
1923
|
+
fill(prepare(f), clipAtFoot(f.name, stretchAuto(f.name, grid.rects.get(f.name))));
|
|
1893
1924
|
lastLaid = frameIdOf(f.name);
|
|
1894
1925
|
continue;
|
|
1895
1926
|
}
|
|
@@ -1901,7 +1932,7 @@ function composePage(pageInput, template, fit, collapsed) {
|
|
|
1901
1932
|
// A frame of a chain inside the group is reached once the frame
|
|
1902
1933
|
// before it was filled: each is prepared again as it is filled.
|
|
1903
1934
|
for (const f of step.frames) {
|
|
1904
|
-
const r = clipAtFoot(f.name, solved.get(f.name));
|
|
1935
|
+
const r = clipAtFoot(f.name, stretchAuto(f.name, solved.get(f.name)));
|
|
1905
1936
|
if (filling)
|
|
1906
1937
|
fill(prepare(f), r);
|
|
1907
1938
|
}
|
|
@@ -1911,16 +1942,19 @@ function composePage(pageInput, template, fit, collapsed) {
|
|
|
1911
1942
|
* its own, as wide as the group (or its template's `width`, #1088), a
|
|
1912
1943
|
* `'row'` puts them all in one, start to end (each its `width`, else
|
|
1913
1944
|
* an equal share of what is left), a `'grid'` `columns` to a row in
|
|
1914
|
-
* equal columns; a run of modules a group inside
|
|
1915
|
-
*
|
|
1916
|
-
*
|
|
1945
|
+
* equal columns; a run of modules a group inside it takes (`within`)
|
|
1946
|
+
* is laid as that group says where its first module comes: its rows
|
|
1947
|
+
* among a stack's, one cell of a row or a grid (#1095: to any depth).
|
|
1948
|
+
* A row's room past its modules' widths goes by `grow`, what it is
|
|
1949
|
+
* short by comes back by `shrink` (#1095). Rows run from the start side of the page's lines (the flow frame is
|
|
1917
1950
|
* mirrored on a right-to-left page, so its left is the start). A
|
|
1918
1951
|
* module is placed as its template draws its frames in its box
|
|
1919
1952
|
* (`'container'` is the box) and its groups laid in it: first in the
|
|
1920
1953
|
* room left, to find how tall it is (the frames held by the box's foot
|
|
1921
1954
|
* or middle, or sized by its height, left out), then in a box that
|
|
1922
1955
|
* tall, or (`rowAlign` `'stretch'`, a row of several) as tall as its
|
|
1923
|
-
* row
|
|
1956
|
+
* row, its `'auto'` boxes that end at its foot reaching the row's
|
|
1957
|
+
* (#1095). A row that does not fit is cut at the group's foot (its frames
|
|
1924
1958
|
* clipped there), or, when the group goes on to another page
|
|
1925
1959
|
* (`FitState.gridsOn`), it and every row after it go on, whole. The
|
|
1926
1960
|
* modules' declared boxes follow each other at the heights their
|
|
@@ -1933,75 +1967,101 @@ function composePage(pageInput, template, fit, collapsed) {
|
|
|
1933
1967
|
const box = ownBox ?? pageInput.areas.area;
|
|
1934
1968
|
const foot = box.y + box.height;
|
|
1935
1969
|
const toPx = (d) => dimensionToPx(d, dpi, pageInput.emPx);
|
|
1970
|
+
const groupNamed = new Map(template.groups.map((g) => [g.name, g]));
|
|
1936
1971
|
const mods = [];
|
|
1937
1972
|
for (const item of group.items ?? []) {
|
|
1938
1973
|
const mod = template.modules?.find((m) => m.name === item.module);
|
|
1939
1974
|
const names = item.frames.filter((n) => byMember.has(n));
|
|
1940
1975
|
if (mod && names.length > 0)
|
|
1941
|
-
mods.push({ mod, names });
|
|
1976
|
+
mods.push({ mod, names, chain: nestedChain(template.groups, mod.nested) });
|
|
1942
1977
|
}
|
|
1943
|
-
/** A module's width
|
|
1944
|
-
|
|
1978
|
+
/** A module's width by its template in a group `width` wide
|
|
1979
|
+
* (`'fill'`: none). */
|
|
1980
|
+
const fixedWidth = (l, width) => {
|
|
1945
1981
|
const w = l.mod.width;
|
|
1946
1982
|
if (w === undefined || w === 'fill')
|
|
1947
1983
|
return undefined;
|
|
1948
|
-
return 'percent' in w ? (
|
|
1984
|
+
return 'percent' in w ? (width * w.percent) / 100 : toPx(w);
|
|
1949
1985
|
};
|
|
1950
|
-
/** `list`
|
|
1951
|
-
*
|
|
1952
|
-
const
|
|
1953
|
-
const
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1986
|
+
/** The cells of `list` in `g`: each module `g` lays itself, and each
|
|
1987
|
+
* run of the modules of a group inside `g`. */
|
|
1988
|
+
const cellsOf = (list, g) => {
|
|
1989
|
+
const out = [];
|
|
1990
|
+
for (const l of list) {
|
|
1991
|
+
const name = l.chain.find((n) => groupNamed.get(n)?.within === g.name);
|
|
1992
|
+
const child = name !== undefined ? groupNamed.get(name) : undefined;
|
|
1993
|
+
const last = out[out.length - 1];
|
|
1994
|
+
if (child && last?.kind === 'group' && last.group === child)
|
|
1995
|
+
last.list.push(l);
|
|
1996
|
+
else
|
|
1997
|
+
out.push(child ? { kind: 'group', group: child, list: [l] } : { kind: 'module', l });
|
|
1998
|
+
}
|
|
1999
|
+
return out;
|
|
2000
|
+
};
|
|
2001
|
+
const namesOf = (c) => (c.kind === 'module' ? c.l.names : c.list.flatMap((l) => l.names));
|
|
2002
|
+
/** `cells` side by side across `width` from `x`, `gap` between them:
|
|
2003
|
+
* each as wide as its template says, then the room left shared by
|
|
2004
|
+
* `grow` (a `'fill'` module, and a group's cell, 1 at least), or,
|
|
2005
|
+
* when the widths run past the end, given back by `shrink` in
|
|
2006
|
+
* proportion to each width (#1095). */
|
|
2007
|
+
const across = (cells, gap, x, width) => {
|
|
2008
|
+
const fixed = cells.map((c) => (c.kind === 'module' ? fixedWidth(c.l, width) : undefined));
|
|
2009
|
+
const taken = fixed.reduce((a, w) => a + (w ?? 0), 0) + gap * Math.max(0, cells.length - 1);
|
|
2010
|
+
const spare = width - taken;
|
|
2011
|
+
let widths;
|
|
2012
|
+
if (spare >= 0) {
|
|
2013
|
+
const grows = cells.map((c, k) => (c.kind !== 'module' ? 1 : fixed[k] === undefined ? Math.max(1, c.l.mod.grow ?? 1) : c.l.mod.grow ?? 0));
|
|
2014
|
+
const total = grows.reduce((a, g) => a + g, 0);
|
|
2015
|
+
widths = fixed.map((w, k) => Math.max(0, total > 0 ? (w ?? 0) + (spare * grows[k]) / total : w ?? 0));
|
|
2016
|
+
}
|
|
2017
|
+
else {
|
|
2018
|
+
const weights = cells.map((c, k) => (c.kind === 'module' && fixed[k] !== undefined ? (c.l.mod.shrink ?? 0) * fixed[k] : 0));
|
|
2019
|
+
const total = weights.reduce((a, g) => a + g, 0);
|
|
2020
|
+
widths = fixed.map((w, k) => Math.max(0, total > 0 ? (w ?? 0) + (spare * weights[k]) / total : w ?? 0));
|
|
2021
|
+
}
|
|
1958
2022
|
const xs = [];
|
|
1959
|
-
let
|
|
2023
|
+
let at = x;
|
|
1960
2024
|
for (const w of widths) {
|
|
1961
|
-
xs.push(
|
|
1962
|
-
|
|
2025
|
+
xs.push(at);
|
|
2026
|
+
at += w + gap;
|
|
1963
2027
|
}
|
|
1964
2028
|
return { xs, widths };
|
|
1965
2029
|
};
|
|
1966
|
-
/** The rows `list` makes in a group of `g`'s kind
|
|
1967
|
-
* after the row before it.
|
|
1968
|
-
|
|
2030
|
+
/** The rows `list` makes in a group of `g`'s kind across `width`
|
|
2031
|
+
* from `x`, the first `first` after the row before it. A group
|
|
2032
|
+
* inside a stack adds its rows to the stack's; inside a row or a
|
|
2033
|
+
* grid, a run of its modules is one cell. */
|
|
2034
|
+
const rowsOf = (list, g, x, width, first) => {
|
|
1969
2035
|
const gap = toPx(g.gap);
|
|
1970
2036
|
const align = g.rowAlign ?? 'stretch';
|
|
1971
|
-
const
|
|
2037
|
+
const cells = cellsOf(list, g);
|
|
1972
2038
|
if (g.kind === 'row')
|
|
1973
|
-
return [{
|
|
2039
|
+
return [{ cells, ...across(cells, gap, x, width), align, gapBefore: first }];
|
|
1974
2040
|
if (g.kind === 'grid') {
|
|
1975
2041
|
const columns = Math.max(1, g.columns ?? 1);
|
|
1976
2042
|
const colGap = toPx(g.columnGap ?? g.gap);
|
|
1977
2043
|
const rowGap = toPx(g.rowGap ?? g.gap);
|
|
1978
|
-
const colW = Math.max(1, (
|
|
2044
|
+
const colW = Math.max(1, (width - colGap * (columns - 1)) / columns);
|
|
1979
2045
|
const out = [];
|
|
1980
|
-
for (let k = 0; k <
|
|
1981
|
-
const chunk =
|
|
1982
|
-
out.push({
|
|
2046
|
+
for (let k = 0; k < cells.length; k += columns) {
|
|
2047
|
+
const chunk = cells.slice(k, k + columns);
|
|
2048
|
+
out.push({ cells: chunk, xs: chunk.map((_, c) => x + c * (colW + colGap)), widths: chunk.map(() => colW), align, gapBefore: k === 0 ? first : rowGap });
|
|
1983
2049
|
}
|
|
1984
2050
|
return out;
|
|
1985
2051
|
}
|
|
1986
|
-
// A stack: a row of its own per module, at its width from the
|
|
1987
|
-
|
|
2052
|
+
// A stack: a row of its own per module, at its width from the
|
|
2053
|
+
// start; a group's rows in turn.
|
|
2054
|
+
const out = [];
|
|
2055
|
+
cells.forEach((c, k) => {
|
|
2056
|
+
const before = k === 0 ? first : gap;
|
|
2057
|
+
if (c.kind === 'module')
|
|
2058
|
+
out.push({ cells: [c], xs: [x], widths: [fixedWidth(c.l, width) ?? width], align: 'start', gapBefore: before });
|
|
2059
|
+
else
|
|
2060
|
+
out.push(...rowsOf(c.list, c.group, x, width, before));
|
|
2061
|
+
});
|
|
2062
|
+
return out;
|
|
1988
2063
|
};
|
|
1989
|
-
const rows =
|
|
1990
|
-
if (group.kind !== 'stack')
|
|
1991
|
-
rows.push(...rowsOf(mods, group, 0));
|
|
1992
|
-
else {
|
|
1993
|
-
const stackGap = toPx(group.gap);
|
|
1994
|
-
for (let k = 0; k < mods.length;) {
|
|
1995
|
-
const nested = mods[k].mod.nested;
|
|
1996
|
-
const inner = nested !== undefined ? template.groups.find((g) => g.name === nested) : undefined;
|
|
1997
|
-
let end = k + 1;
|
|
1998
|
-
if (inner)
|
|
1999
|
-
while (end < mods.length && mods[end].mod.nested === nested)
|
|
2000
|
-
end++;
|
|
2001
|
-
rows.push(...rowsOf(mods.slice(k, end), inner ?? group, k === 0 ? 0 : stackGap, inner ? nested : undefined));
|
|
2002
|
-
k = end;
|
|
2003
|
-
}
|
|
2004
|
-
}
|
|
2064
|
+
const rows = rowsOf(mods, group, box.x, box.width, 0);
|
|
2005
2065
|
let cursor = box.y;
|
|
2006
2066
|
let declCursor = box.y;
|
|
2007
2067
|
let out = false;
|
|
@@ -2043,43 +2103,53 @@ function composePage(pageInput, template, fit, collapsed) {
|
|
|
2043
2103
|
pinned.length = kept.pinned;
|
|
2044
2104
|
return reach ? Math.max(0, reach.y + reach.height - y) : 0;
|
|
2045
2105
|
};
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
return;
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2106
|
+
/** How tall a cell is at `(x, y)`, `width` wide: a module's height,
|
|
2107
|
+
* or a group's rows one after another (#1095). */
|
|
2108
|
+
const measureCell = (c, x, y, width) => {
|
|
2109
|
+
if (c.kind === 'module')
|
|
2110
|
+
return measure(c.l, x, y, width);
|
|
2111
|
+
let at = y;
|
|
2112
|
+
rowsOf(c.list, c.group, x, width, 0).forEach((row, r) => {
|
|
2113
|
+
if (r > 0)
|
|
2114
|
+
at += row.gapBefore;
|
|
2115
|
+
at += Math.max(0, ...row.cells.map((d, k) => measureCell(d, row.xs[k], at, row.widths[k])));
|
|
2116
|
+
});
|
|
2117
|
+
return at - y;
|
|
2118
|
+
};
|
|
2119
|
+
/** Lay `row` at `rowTop` (its declared top `declTop`), its cells
|
|
2120
|
+
* `heights` tall: each module in a box that tall (cut at the foot
|
|
2121
|
+
* when the row does not fit), a shorter one placed by `rowAlign`; a
|
|
2122
|
+
* group's cell its rows in turn. The row's foot, laid and declared. */
|
|
2123
|
+
const layRow = (row, rowTop, declTop, heights, fits) => {
|
|
2057
2124
|
const rowH = Math.max(0, ...heights);
|
|
2058
|
-
const
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
spillWhole(names, laidAny, lastLaid);
|
|
2063
|
-
return;
|
|
2064
|
-
}
|
|
2065
|
-
// Each module laid in a box that tall (cut at the foot when the row
|
|
2066
|
-
// does not fit); a shorter one placed by `rowAlign`.
|
|
2067
|
-
const several = row.mods.length > 1;
|
|
2068
|
-
let rowBottom = cursor;
|
|
2069
|
-
let rowDeclBottom = declCursor;
|
|
2070
|
-
row.mods.forEach((l, k) => {
|
|
2125
|
+
const several = row.cells.length > 1;
|
|
2126
|
+
let rowBottom = rowTop;
|
|
2127
|
+
let rowDeclBottom = declTop;
|
|
2128
|
+
row.cells.forEach((c, k) => {
|
|
2071
2129
|
const x = row.xs[k];
|
|
2072
2130
|
const width = row.widths[k];
|
|
2073
2131
|
const spare = rowH - heights[k];
|
|
2074
|
-
const stretched = fits && several && row.align === 'stretch';
|
|
2132
|
+
const stretched = fits && several && row.align === 'stretch' && c.kind === 'module';
|
|
2075
2133
|
const dy = fits && several && spare > 0.01 ? (row.align === 'end' ? spare : row.align === 'center' ? spare / 2 : 0) : 0;
|
|
2076
|
-
const y =
|
|
2134
|
+
const y = rowTop + dy;
|
|
2135
|
+
if (c.kind === 'group') {
|
|
2136
|
+
// A run of a group inside this one (#1095): its rows, from the
|
|
2137
|
+
// cell's top.
|
|
2138
|
+
const laid = layRows(rowsOf(c.list, c.group, x, width, 0), y, declTop + dy, fits);
|
|
2139
|
+
rowBottom = Math.max(rowBottom, laid.bottom);
|
|
2140
|
+
rowDeclBottom = Math.max(rowDeclBottom, laid.declBottom);
|
|
2141
|
+
return;
|
|
2142
|
+
}
|
|
2143
|
+
const l = c.l;
|
|
2077
2144
|
clipFoot = fits ? undefined : foot;
|
|
2145
|
+
// Its 'auto' boxes that end at its foot reach the row's (#1095).
|
|
2146
|
+
stretchTo = stretched && spare > 0.01 ? { at: y + heights[k], foot: y + rowH, names: new Set(l.names) } : undefined;
|
|
2078
2147
|
try {
|
|
2079
|
-
lay(l, x, y, width, fits ? (stretched ? rowH : heights[k]) : foot -
|
|
2148
|
+
lay(l, x, y, width, fits ? (stretched ? rowH : heights[k]) : foot - rowTop, true);
|
|
2080
2149
|
}
|
|
2081
2150
|
finally {
|
|
2082
2151
|
clipFoot = undefined;
|
|
2152
|
+
stretchTo = undefined;
|
|
2083
2153
|
}
|
|
2084
2154
|
const u = unionRect(l.names.flatMap((n) => (rects.has(n) ? [rects.get(n)] : [])));
|
|
2085
2155
|
const bottom = Math.max(stretched ? y + rowH : y, u ? u.y + u.height : y);
|
|
@@ -2087,32 +2157,70 @@ function composePage(pageInput, template, fit, collapsed) {
|
|
|
2087
2157
|
moduleRects.set(l.mod.name, moduleBox);
|
|
2088
2158
|
boxes.push(moduleBox);
|
|
2089
2159
|
// Declared: after the rows before it as they declare themselves.
|
|
2090
|
-
const shift =
|
|
2160
|
+
const shift = declTop - rowTop;
|
|
2091
2161
|
for (const n of l.names) {
|
|
2092
2162
|
const d = declared.get(n);
|
|
2093
2163
|
if (d && Math.abs(shift) > 0.001)
|
|
2094
2164
|
declared.set(n, { ...d, y: d.y + shift });
|
|
2095
2165
|
}
|
|
2096
|
-
const declY =
|
|
2166
|
+
const declY = declTop + dy;
|
|
2097
2167
|
const du = unionRect(l.names.flatMap((n) => (declared.has(n) ? [declared.get(n)] : [])));
|
|
2098
2168
|
const declBottom = du ? Math.max(declY, du.y + du.height) : declY;
|
|
2099
2169
|
const declBox = { x, y: declY, width, height: declBottom - declY };
|
|
2100
2170
|
declBoxes.push(declBox);
|
|
2101
|
-
|
|
2102
|
-
const n = nestedBoxes.get(
|
|
2171
|
+
for (const name of l.chain) {
|
|
2172
|
+
const n = nestedBoxes.get(name) ?? { laid: [], declared: [] };
|
|
2103
2173
|
n.laid.push(moduleBox);
|
|
2104
2174
|
n.declared.push(declBox);
|
|
2105
|
-
nestedBoxes.set(
|
|
2175
|
+
nestedBoxes.set(name, n);
|
|
2106
2176
|
}
|
|
2107
2177
|
rowBottom = Math.max(rowBottom, bottom);
|
|
2108
2178
|
rowDeclBottom = Math.max(rowDeclBottom, declBottom);
|
|
2109
2179
|
});
|
|
2180
|
+
return { bottom: rowBottom, declBottom: rowDeclBottom };
|
|
2181
|
+
};
|
|
2182
|
+
/** The rows of a group's cell, one after another from `top`. */
|
|
2183
|
+
const layRows = (list, top, declTop, fits) => {
|
|
2184
|
+
let at = top;
|
|
2185
|
+
let declAt = declTop;
|
|
2186
|
+
list.forEach((row, r) => {
|
|
2187
|
+
if (r > 0) {
|
|
2188
|
+
at += row.gapBefore;
|
|
2189
|
+
declAt += row.gapBefore;
|
|
2190
|
+
}
|
|
2191
|
+
const heights = row.cells.map((c, k) => measureCell(c, row.xs[k], at, row.widths[k]));
|
|
2192
|
+
const laid = layRow(row, at, declAt, heights, fits);
|
|
2193
|
+
at = laid.bottom;
|
|
2194
|
+
declAt = laid.declBottom;
|
|
2195
|
+
});
|
|
2196
|
+
return { bottom: at, declBottom: declAt };
|
|
2197
|
+
};
|
|
2198
|
+
rows.forEach((row, r) => {
|
|
2199
|
+
const names = row.cells.flatMap(namesOf);
|
|
2200
|
+
if (out) {
|
|
2201
|
+
spillWhole(names, laidAny, lastLaid);
|
|
2202
|
+
return;
|
|
2203
|
+
}
|
|
2204
|
+
if (r > 0) {
|
|
2205
|
+
cursor += row.gapBefore;
|
|
2206
|
+
declCursor += row.gapBefore;
|
|
2207
|
+
}
|
|
2208
|
+
const heights = row.cells.map((c, k) => measureCell(c, row.xs[k], cursor, row.widths[k]));
|
|
2209
|
+
const rowH = Math.max(0, ...heights);
|
|
2210
|
+
const fits = cursor + rowH <= foot + 0.5;
|
|
2211
|
+
if (!fits && fit.gridsOn.has(group.name)) {
|
|
2212
|
+
// This row and the ones after it go on, whole.
|
|
2213
|
+
out = true;
|
|
2214
|
+
spillWhole(names, laidAny, lastLaid);
|
|
2215
|
+
return;
|
|
2216
|
+
}
|
|
2217
|
+
const laid = layRow(row, cursor, declCursor, heights, fits);
|
|
2110
2218
|
laidAny = true;
|
|
2111
2219
|
lastLaid = frameIdOf(names[names.length - 1]);
|
|
2112
|
-
cursor =
|
|
2113
|
-
declCursor =
|
|
2220
|
+
cursor = laid.bottom;
|
|
2221
|
+
declCursor = laid.declBottom;
|
|
2114
2222
|
});
|
|
2115
|
-
// A group inside
|
|
2223
|
+
// A group inside another (#1088, #1095) is the box of its modules.
|
|
2116
2224
|
for (const [name, b] of nestedBoxes) {
|
|
2117
2225
|
groupRects.set(name, unionRect(b.laid));
|
|
2118
2226
|
groupDeclared.set(name, unionRect(b.declared));
|