@segnavia/format 0.24.0 → 0.26.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/fold.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ import "./paper.js";
2
+ //#region src/fold.d.ts
3
+ export declare const FOLD_KINDS: readonly ["half", "letter", "z", "gate", "custom"];
4
+ export type FoldKind = (typeof FOLD_KINDS)[number];
5
+ export declare const FOLD_TUCK_IN_MM = 1.5;
6
+ export declare function foldColumns(fold: FoldKind, panelCount?: number): number;
7
+ export declare function foldPanelMap(fold: FoldKind, columns: number): {
8
+ front: number[];
9
+ back: number[];
10
+ };
11
+ export declare function foldCellPages(fold: FoldKind, columns: number): Array<{
12
+ front: number;
13
+ back: number;
14
+ }>;
15
+ export declare function foldPageCountMessage(fold: FoldKind, pageCount: number, columns: number): string;
16
+ //#endregion
package/dist/fold.js ADDED
@@ -0,0 +1,175 @@
1
+ import { fromMillimeters, roundMillimeters, sheetMm, toMillimeters } from "./paper.js";
2
+ import { refuseOverflow, refuseSafe } from "./imposition-fit.js";
3
+ //#region src/fold.ts
4
+ const FOLD_KINDS = [
5
+ "half",
6
+ "letter",
7
+ "z",
8
+ "gate",
9
+ "custom"
10
+ ];
11
+ const FOLD_TUCK_IN_MM = 1.5;
12
+ const FOLD_HEIGHT_REMEDY = "reduce the vertical margins or cell height";
13
+ function foldColumns(fold, panelCount = 0) {
14
+ if (fold === "custom") return panelCount;
15
+ return fold === "half" ? 2 : 3;
16
+ }
17
+ function foldPanelMap(fold, columns) {
18
+ if (fold === "gate") return {
19
+ front: [
20
+ 2,
21
+ 6,
22
+ 1
23
+ ],
24
+ back: [
25
+ 3,
26
+ 4,
27
+ 5
28
+ ]
29
+ };
30
+ return {
31
+ front: [...Array.from({ length: columns - 1 }, (_, index) => columns + 2 + index), 1],
32
+ back: Array.from({ length: columns }, (_, index) => index + 2)
33
+ };
34
+ }
35
+ function foldCellPages(fold, columns) {
36
+ const map = foldPanelMap(fold, columns);
37
+ return Array.from({ length: columns }, (_, cell) => ({
38
+ front: (map.front[cell] ?? 1) - 1,
39
+ back: (map.back[columns - 1 - cell] ?? 1) - 1
40
+ }));
41
+ }
42
+ function foldPageCountMessage(fold, pageCount, columns) {
43
+ const need = columns * 2;
44
+ return `this ${fold} fold has ${pageCount} pages and needs ${need} (2 × ${columns} panels); pass ${need} pages to clear this refusal`;
45
+ }
46
+ function splitSum(available, count) {
47
+ const share = available / count;
48
+ const widths = Array.from({ length: count - 1 }, () => roundMillimeters(share));
49
+ const used = widths.reduce((sum, width) => sum + width, 0);
50
+ widths.push(roundMillimeters(available - used));
51
+ return widths;
52
+ }
53
+ function presetPanelWidthsMm(fold, availableMm) {
54
+ if (fold === "letter") {
55
+ const tuck = roundMillimeters(availableMm / 3 - FOLD_TUCK_IN_MM);
56
+ const rest = availableMm - tuck;
57
+ const second = roundMillimeters(rest / 2);
58
+ return [
59
+ tuck,
60
+ second,
61
+ roundMillimeters(rest - second)
62
+ ];
63
+ }
64
+ if (fold === "gate") {
65
+ const flap = roundMillimeters(availableMm / 4 - FOLD_TUCK_IN_MM);
66
+ return [
67
+ flap,
68
+ roundMillimeters(availableMm - flap * 2),
69
+ flap
70
+ ];
71
+ }
72
+ return splitSum(availableMm, foldColumns(fold));
73
+ }
74
+ function availableWidthMm(draft) {
75
+ const paper = sheetMm({
76
+ paper: draft.paper,
77
+ orientation: draft.orientation
78
+ });
79
+ return roundMillimeters(paper.width - toMillimeters(draft.margin.left, draft.unit) - toMillimeters(draft.margin.right, draft.unit));
80
+ }
81
+ function panelWidthsMm(draft) {
82
+ if (draft.panels) return draft.panels.map((width) => toMillimeters(width, draft.unit));
83
+ if (!draft.fold || draft.fold === "custom") return [];
84
+ return presetPanelWidthsMm(draft.fold, availableWidthMm(draft));
85
+ }
86
+ function panelsInUnit(draft) {
87
+ if (draft.panels) return draft.panels;
88
+ return panelWidthsMm(draft).map((width) => draft.unit === "mm" ? width : fromMillimeters(width, draft.unit));
89
+ }
90
+ function issue(ctx, path, message) {
91
+ ctx.addIssue({
92
+ code: "custom",
93
+ path,
94
+ message
95
+ });
96
+ }
97
+ function refuseShape(draft, ctx, columns) {
98
+ if (draft.rows !== void 0 && draft.rows !== 1) issue(ctx, ["rows"], `rows is ${draft.rows}, but a fold is one row; set rows to 1 or omit it to clear this refusal`);
99
+ if (draft.sides === "one") issue(ctx, ["sides"], "sides is one, but a fold is two-sided; set sides to two or omit it to clear this refusal");
100
+ if (draft.fill === "repeat") issue(ctx, ["fill"], "fill is repeat, but a fold fills in sequence; set fill to sequence or omit it to clear this refusal");
101
+ if (draft.skip !== 0) issue(ctx, ["skip"], `skip is ${draft.skip}, but a fold has no skipped cells; set skip to 0 or omit it to clear this refusal`);
102
+ if (draft.gap.column !== 0) issue(ctx, ["gap", "column"], `column gap is ${draft.gap.column}, but a fold's panels touch; set gap.column to 0 or omit it to clear this refusal`);
103
+ if (draft.columns !== void 0 && draft.columns !== columns) issue(ctx, ["columns"], `columns is ${draft.columns}, but a ${draft.fold} fold has ${columns} panels; set columns to ${columns} or omit it to clear this refusal`);
104
+ }
105
+ function refineFold(draft, ctx) {
106
+ const fold = draft.fold;
107
+ if (!fold) return;
108
+ if (fold === "custom" && (draft.panels === void 0 || draft.panels.length < 2)) {
109
+ issue(ctx, ["panels"], "a custom fold needs panels with at least two widths; give panel widths that sum to the paper width to clear this refusal");
110
+ return;
111
+ }
112
+ const columns = foldColumns(fold, draft.panels?.length);
113
+ if (fold !== "custom" && draft.panels !== void 0 && draft.panels.length !== columns) {
114
+ issue(ctx, ["panels"], `panels has ${draft.panels.length} widths and a ${fold} fold has ${columns} columns; give ${columns} widths or omit panels to use the preset`);
115
+ return;
116
+ }
117
+ refuseShape(draft, ctx, columns);
118
+ const paper = sheetMm({
119
+ paper: draft.paper,
120
+ orientation: draft.orientation
121
+ });
122
+ const available = availableWidthMm(draft);
123
+ if (available <= 0) {
124
+ issue(ctx, ["margin"], `the horizontal margins leave ${available}mm of the ${paper.width}mm paper; reduce them`);
125
+ return;
126
+ }
127
+ const widths = panelWidthsMm(draft);
128
+ if (widths.some((width) => width <= 0)) {
129
+ issue(ctx, ["panels"], `a ${fold} fold has a non-positive panel after the ${FOLD_TUCK_IN_MM}mm tuck-in allowance; use a wider paper or override panels to clear this refusal`);
130
+ return;
131
+ }
132
+ const marginLeft = toMillimeters(draft.margin.left, draft.unit);
133
+ const marginRight = toMillimeters(draft.margin.right, draft.unit);
134
+ const sum = roundMillimeters(marginLeft + widths.reduce((total, width) => total + width, 0) + marginRight);
135
+ if (Math.abs(sum - paper.width) > .01) issue(ctx, ["panels"], `the panels and horizontal margins sum to ${sum}mm and the paper is ${paper.width}mm wide; change panels or margins so they sum to ${paper.width}mm to clear this refusal`);
136
+ const height = toMillimeters(draft.margin.top, draft.unit) + toMillimeters(draft.cell.height, draft.unit) + toMillimeters(draft.margin.bottom, draft.unit);
137
+ refuseOverflow(ctx, paper, { height }, { height: {
138
+ path: ["cell", "height"],
139
+ subject: "the folded piece",
140
+ remedy: FOLD_HEIGHT_REMEDY
141
+ } });
142
+ refuseSafe(ctx, toMillimeters(draft.safe, draft.unit), {
143
+ width: Math.min(...widths),
144
+ height: toMillimeters(draft.cell.height, draft.unit)
145
+ });
146
+ }
147
+ function resolveImposition(value) {
148
+ if (!value.fold) return {
149
+ ...value,
150
+ columns: value.columns ?? 1,
151
+ rows: value.rows ?? 1,
152
+ sides: value.sides ?? "one",
153
+ cell: {
154
+ width: value.cell.width ?? 1,
155
+ height: value.cell.height
156
+ }
157
+ };
158
+ const columns = foldColumns(value.fold, value.panels?.length);
159
+ const panels = panelsInUnit(value);
160
+ return {
161
+ ...value,
162
+ columns,
163
+ rows: 1,
164
+ sides: "two",
165
+ fill: "sequence",
166
+ skip: 0,
167
+ gap: {
168
+ column: 0,
169
+ row: value.gap.row
170
+ },
171
+ panels
172
+ };
173
+ }
174
+ //#endregion
175
+ export { FOLD_KINDS, FOLD_TUCK_IN_MM, foldCellPages, foldColumns, foldPageCountMessage, foldPanelMap, panelWidthsMm, presetPanelWidthsMm, refineFold, resolveImposition };
@@ -0,0 +1,3 @@
1
+ //#region src/imposition-fit.d.ts
2
+ export declare const PAPER_FIT_TOLERANCE_MM = 0.01;
3
+ //#endregion
@@ -0,0 +1,33 @@
1
+ import { roundMillimeters } from "./paper.js";
2
+ //#region src/imposition-fit.ts
3
+ const PAPER_FIT_TOLERANCE_MM = .01;
4
+ const GRID_WIDTH_REMEDY = "reduce the horizontal margins, columns, cell width or column gap";
5
+ const GRID_HEIGHT_REMEDY = "reduce the vertical margins, rows, cell height or row gap";
6
+ function refuseOverflow(ctx, paper, used, axis = {}) {
7
+ const width = used.width;
8
+ if (width !== void 0 && width - paper.width > .01) ctx.addIssue({
9
+ code: "custom",
10
+ path: axis.width?.path ?? ["columns"],
11
+ message: `${axis.width?.subject ?? "the grid"} is ${roundMillimeters(width)}mm wide and the paper is ${paper.width}mm wide, an overflow of ${roundMillimeters(width - paper.width)}mm; ${axis.width?.remedy ?? GRID_WIDTH_REMEDY}`
12
+ });
13
+ const height = used.height;
14
+ if (height !== void 0 && height - paper.height > .01) ctx.addIssue({
15
+ code: "custom",
16
+ path: axis.height?.path ?? ["rows"],
17
+ message: `${axis.height?.subject ?? "the grid"} is ${roundMillimeters(height)}mm high and the paper is ${paper.height}mm high, an overflow of ${roundMillimeters(height - paper.height)}mm; ${axis.height?.remedy ?? GRID_HEIGHT_REMEDY}`
18
+ });
19
+ }
20
+ function refuseSafe(ctx, safe, cell) {
21
+ if (safe * 2 >= cell.width) ctx.addIssue({
22
+ code: "custom",
23
+ path: ["safe"],
24
+ message: `safe is ${roundMillimeters(safe)}mm on the left and right, but the cell is ${roundMillimeters(cell.width)}mm wide; safe must leave area inside the cell`
25
+ });
26
+ if (safe * 2 >= cell.height) ctx.addIssue({
27
+ code: "custom",
28
+ path: ["safe"],
29
+ message: `safe is ${roundMillimeters(safe)}mm on the top and bottom, but the cell is ${roundMillimeters(cell.height)}mm high; safe must leave area inside the cell`
30
+ });
31
+ }
32
+ //#endregion
33
+ export { PAPER_FIT_TOLERANCE_MM, refuseOverflow, refuseSafe };
@@ -1,9 +1,9 @@
1
1
  import { roundMillimeters } from "./paper.js";
2
- import { impose } from "./imposition.js";
2
+ import { gridPlacements } from "./imposition.js";
3
3
  //#region src/imposition-marks.ts
4
4
  const MIN_MARK_LENGTH_MM = 2;
5
5
  const unique = (values) => [...new Set(values.map(roundMillimeters))].sort((a, b) => a - b);
6
- function addMark(result, edge, cutPosition, start, available, horizontal, direction) {
6
+ function addMark(result, edge, cutPosition, start, available, horizontal, direction, dashed = false) {
7
7
  const length = Math.min(5, roundMillimeters(available));
8
8
  if (length < 2) {
9
9
  result.omittedMarks.push({
@@ -14,19 +14,22 @@ function addMark(result, edge, cutPosition, start, available, horizontal, direct
14
14
  return;
15
15
  }
16
16
  const end = roundMillimeters(start + direction * length);
17
+ const dash = dashed ? { dashed: true } : {};
17
18
  result.marks.push(horizontal ? {
18
19
  x1: Math.min(start, end),
19
20
  y1: cutPosition,
20
21
  x2: Math.max(start, end),
21
- y2: cutPosition
22
+ y2: cutPosition,
23
+ ...dash
22
24
  } : {
23
25
  x1: cutPosition,
24
26
  y1: Math.min(start, end),
25
27
  x2: cutPosition,
26
- y2: Math.max(start, end)
28
+ y2: Math.max(start, end),
29
+ ...dash
27
30
  });
28
31
  }
29
- function outerMarks(side, placements, paper) {
32
+ function outerMarks(side, placements, paper, foldCuts) {
30
33
  const verticalCuts = unique(placements.flatMap(({ trim }) => [trim.x, trim.x + trim.width]));
31
34
  const horizontalCuts = unique(placements.flatMap(({ trim }) => [trim.y, trim.y + trim.height]));
32
35
  const top = Math.min(...placements.map(({ bleedBox }) => bleedBox.y));
@@ -34,6 +37,7 @@ function outerMarks(side, placements, paper) {
34
37
  const bottom = Math.max(...placements.map(({ bleedBox }) => bleedBox.y + bleedBox.height));
35
38
  const left = Math.min(...placements.map(({ bleedBox }) => bleedBox.x));
36
39
  for (const cut of verticalCuts) {
40
+ if (foldCuts.has(cut)) continue;
37
41
  addMark(side, "top", cut, roundMillimeters(top - 1), top - 1, false, -1);
38
42
  addMark(side, "bottom", cut, roundMillimeters(bottom + 1), paper.height - bottom - 1, false, 1);
39
43
  }
@@ -41,6 +45,10 @@ function outerMarks(side, placements, paper) {
41
45
  addMark(side, "left", cut, roundMillimeters(left - 1), left - 1, true, -1);
42
46
  addMark(side, "right", cut, roundMillimeters(right + 1), paper.width - right - 1, true, 1);
43
47
  }
48
+ for (const cut of foldCuts) {
49
+ addMark(side, "top", cut, roundMillimeters(top - 1), top - 1, false, -1, true);
50
+ addMark(side, "bottom", cut, roundMillimeters(bottom + 1), paper.height - bottom - 1, false, 1, true);
51
+ }
44
52
  }
45
53
  function intersectsBleed(mark, boxes) {
46
54
  return boxes.some((box) => Math.max(mark.x1, box.x) <= Math.min(mark.x2, box.x + box.width) && Math.max(mark.y1, box.y) <= Math.min(mark.y2, box.y + box.height));
@@ -146,39 +154,38 @@ function cornerMarks(side, placements, rows) {
146
154
  }
147
155
  }
148
156
  }
157
+ function foldCutPositions(placements) {
158
+ const left = Math.min(...placements.map(({ trim }) => trim.x));
159
+ const right = Math.max(...placements.map(({ trim }) => trim.x + trim.width));
160
+ return new Set(unique(placements.flatMap(({ trim }) => [trim.x, trim.x + trim.width])).filter((cut) => cut !== left && cut !== right));
161
+ }
149
162
  /** Computes physical crop-mark geometry without changing the fixed paper size. */
150
163
  function impositionMarks(imposition) {
151
164
  if (!imposition.marks) return [];
152
- const cellCount = imposition.columns * imposition.rows;
153
- const frontImposed = impose({
154
- ...imposition,
155
- sides: "one",
156
- fill: "sequence",
157
- skip: 0
158
- }, cellCount);
159
- const frontPlacements = frontImposed.placements;
165
+ const { paper, placements: frontPlacements } = gridPlacements(imposition);
166
+ const foldCuts = imposition.fold ? foldCutPositions(frontPlacements) : /* @__PURE__ */ new Set();
160
167
  const build = (sideName, placements) => {
161
168
  const side = {
162
169
  side: sideName,
163
170
  marks: [],
164
171
  omittedMarks: []
165
172
  };
166
- outerMarks(side, placements, frontImposed.paper);
173
+ outerMarks(side, placements, paper, foldCuts);
167
174
  if (imposition.cornerMarks) cornerMarks(side, placements, imposition.rows);
168
175
  return side;
169
176
  };
170
177
  const front = build("front", frontPlacements);
171
178
  if (imposition.sides === "one") return [front];
172
- const portrait = frontImposed.paper.width <= frontImposed.paper.height;
179
+ const portrait = paper.width <= paper.height;
173
180
  const axis = imposition.flip === "long" === portrait ? "x" : "y";
174
181
  const mirrorMark = (mark) => axis === "x" ? {
175
182
  ...mark,
176
- x1: roundMillimeters(frontImposed.paper.width - mark.x1),
177
- x2: roundMillimeters(frontImposed.paper.width - mark.x2)
183
+ x1: roundMillimeters(paper.width - mark.x1),
184
+ x2: roundMillimeters(paper.width - mark.x2)
178
185
  } : {
179
186
  ...mark,
180
- y1: roundMillimeters(frontImposed.paper.height - mark.y1),
181
- y2: roundMillimeters(frontImposed.paper.height - mark.y2)
187
+ y1: roundMillimeters(paper.height - mark.y1),
188
+ y2: roundMillimeters(paper.height - mark.y2)
182
189
  };
183
190
  const mirrorEdge = (edge) => {
184
191
  if (axis === "x") return edge === "left" ? "right" : edge === "right" ? "left" : edge;
@@ -190,7 +197,7 @@ function impositionMarks(imposition) {
190
197
  omittedMarks: front.omittedMarks.map(({ edge, cutPosition }) => ({
191
198
  side: "back",
192
199
  edge: mirrorEdge(edge),
193
- cutPosition: roundMillimeters(axis === "x" && (edge === "top" || edge === "bottom") ? frontImposed.paper.width - cutPosition : axis === "y" && (edge === "left" || edge === "right") ? frontImposed.paper.height - cutPosition : cutPosition)
200
+ cutPosition: roundMillimeters(axis === "x" && (edge === "top" || edge === "bottom") ? paper.width - cutPosition : axis === "y" && (edge === "left" || edge === "right") ? paper.height - cutPosition : cutPosition)
194
201
  }))
195
202
  }];
196
203
  }
@@ -1,4 +1,5 @@
1
1
  import { PX_PER_MM, roundMillimeters, sheetMm, toMillimeters } from "./paper.js";
2
+ import { foldCellPages, foldPageCountMessage } from "./fold.js";
2
3
  //#region src/imposition.ts
3
4
  const zeroCrop = () => ({
4
5
  top: 0,
@@ -6,16 +7,34 @@ const zeroCrop = () => ({
6
7
  bottom: 0,
7
8
  left: 0
8
9
  });
10
+ function columnWidthsMm(imposition) {
11
+ if (imposition.fold) return (imposition.panels ?? []).map((width) => toMillimeters(width, imposition.unit));
12
+ return Array.from({ length: imposition.columns }, () => toMillimeters(imposition.cell.width ?? 0, imposition.unit));
13
+ }
14
+ function columnXMm(imposition, column, widths, paperWidth) {
15
+ const mm = (value) => toMillimeters(value, imposition.unit);
16
+ const gap = mm(imposition.gap.column);
17
+ if (imposition.dir === "rtl") {
18
+ let x = paperWidth - mm(imposition.margin.right);
19
+ for (let index = 0; index <= column; index += 1) x -= widths[index] ?? 0;
20
+ for (let index = 0; index < column; index += 1) x -= gap;
21
+ return x;
22
+ }
23
+ let x = mm(imposition.margin.left);
24
+ for (let index = 0; index < column; index += 1) x += (widths[index] ?? 0) + gap;
25
+ return x;
26
+ }
9
27
  function placementAt(imposition, paper, cell, page, paperSize) {
10
28
  const mm = (value) => toMillimeters(value, imposition.unit);
11
29
  const column = cell % imposition.columns;
12
30
  const row = Math.floor(cell / imposition.columns);
13
31
  const physicalColumn = imposition.dir === "rtl" ? imposition.columns - column - 1 : column;
14
- const cellWidth = mm(imposition.cell.width);
32
+ const widths = columnWidthsMm(imposition);
33
+ const cellWidth = widths[column] ?? mm(imposition.cell.width ?? 0);
15
34
  const cellHeight = mm(imposition.cell.height);
16
35
  const columnGap = mm(imposition.gap.column);
17
36
  const rowGap = mm(imposition.gap.row);
18
- const x = imposition.dir === "rtl" ? paperSize.width - mm(imposition.margin.right) - cellWidth - column * (cellWidth + columnGap) : mm(imposition.margin.left) + column * (cellWidth + columnGap);
37
+ const x = columnXMm(imposition, column, widths, paperSize.width);
19
38
  const y = mm(imposition.margin.top) + row * (cellHeight + rowGap);
20
39
  const requested = mm(imposition.bleed);
21
40
  const bleed = {
@@ -145,6 +164,38 @@ function expandAssignments(imposition, assignments, pageCount, paper) {
145
164
  flush();
146
165
  return placements;
147
166
  }
167
+ function imposeFold(imposition, pageCount, paper) {
168
+ const fold = imposition.fold;
169
+ if (!fold) throw new Error("imposeFold requires a fold");
170
+ const columns = imposition.columns;
171
+ if (pageCount !== columns * 2) throw new Error(foldPageCountMessage(fold, pageCount, columns));
172
+ const cells = foldCellPages(fold, columns);
173
+ const fronts = [];
174
+ const backs = [];
175
+ for (const [cell, pages] of cells.entries()) {
176
+ if (!pages) continue;
177
+ const front = placementAt(imposition, 0, cell, pages.front, paper);
178
+ fronts.push(front);
179
+ backs.push(mirrorPlacement(front, paper, imposition.flip, pages.back));
180
+ }
181
+ return {
182
+ paper,
183
+ papers: 1,
184
+ sides: 2,
185
+ placements: [...fronts, ...backs]
186
+ };
187
+ }
188
+ function gridPlacements(imposition) {
189
+ const paper = sheetMm({
190
+ paper: imposition.paper,
191
+ orientation: imposition.orientation
192
+ });
193
+ const cells = imposition.columns * imposition.rows;
194
+ return {
195
+ paper,
196
+ placements: Array.from({ length: cells }, (_, cell) => placementAt(imposition, 0, cell, 0, paper))
197
+ };
198
+ }
148
199
  function impose(imposition, pageCount) {
149
200
  if (!Number.isInteger(pageCount) || pageCount < 0) throw new RangeError(`pageCount must be a nonnegative integer; received ${String(pageCount)}`);
150
201
  const paper = sheetMm({
@@ -152,6 +203,7 @@ function impose(imposition, pageCount) {
152
203
  orientation: imposition.orientation
153
204
  });
154
205
  const sides = imposition.sides === "two" ? 2 : 1;
206
+ if (imposition.fold) return imposeFold(imposition, pageCount, paper);
155
207
  if (pageCount === 0) return {
156
208
  paper,
157
209
  papers: 0,
@@ -291,4 +343,4 @@ function pagePlacementLayout(size, placement, fit) {
291
343
  };
292
344
  }
293
345
  //#endregion
294
- export { fitPage, impose, mirrorPlacement, pagePlacementLayout };
346
+ export { fitPage, gridPlacements, impose, mirrorPlacement, pagePlacementLayout };
package/dist/index.d.ts CHANGED
@@ -9,7 +9,9 @@ import { assignMembership, fitSection, fitTouchedSections, makeRoom, settleBoard
9
9
  import { Book, BookContents, BookFrontMatterEntry, BookInput, BookMode, BookPage, BookSection, BookView, BookViewInput, Chapter, isBookContents, isHebrew, noteMarkerIssues } from "./book.js";
10
10
  import { DeckFromSlidesOptions, SlideRow, deckFromSlides } from "./deck-from-slides.js";
11
11
  import { Direction, TextDirection, firstStrongDirection, languageDirection, resolveDirection } from "./direction.js";
12
- import { CUSTOM_PAPER_MAX_MM, CUSTOM_PAPER_MIN_MM, MARK_GAP_MM, MARK_LENGTH_MM, MM_PER_PT, MarkSegment, NAMED_PAPERS, NamedPaper, NamedPaperMetadata, ORIENTATIONS, Orientation, PAPER_GROUPS, PAPER_METADATA, PAPER_MM, PAPER_UNITS, PX_PER_MM, Paper, PaperBox, PaperGroup, PaperUnit, PrintSetting, PrintSettingInput, fromMillimeters, paperPixels, printBoxes, printPadding, printProperties, roundMillimeters, sheetMm, toMillimeters } from "./paper.js";
12
+ import { PAPER_FIT_TOLERANCE_MM } from "./imposition-fit.js";
13
+ import { CUSTOM_PAPER_MAX_MM, CUSTOM_PAPER_MIN_MM, FOLD_DASH_OFF_MM, FOLD_DASH_ON_MM, MARK_GAP_MM, MARK_LENGTH_MM, MM_PER_PT, MarkSegment, NAMED_PAPERS, NamedPaper, NamedPaperMetadata, ORIENTATIONS, Orientation, PAPER_GROUPS, PAPER_METADATA, PAPER_MM, PAPER_UNITS, PX_PER_MM, Paper, PaperBox, PaperGroup, PaperUnit, PrintSetting, PrintSettingInput, fromMillimeters, paperPixels, printBoxes, printPadding, printProperties, roundMillimeters, sheetMm, toMillimeters } from "./paper.js";
14
+ import { FOLD_KINDS, FOLD_TUCK_IN_MM, FoldKind, foldCellPages, foldColumns, foldPageCountMessage, foldPanelMap } from "./fold.js";
13
15
  import { Imposed, MillimeterEdges, PageFit, PagePlacementKind, PagePlacementLayout, Placement, fitPage, impose, mirrorPlacement, pagePlacementLayout } from "./imposition.js";
14
16
  import { ImpositionMarkEdge, ImpositionSideMarks, MIN_MARK_LENGTH_MM, OmittedImpositionMark, impositionMarks } from "./imposition-marks.js";
15
17
  import { Lexicon, PronunciationEntry, lexiconVersion } from "./lexicon.js";
@@ -18,7 +20,7 @@ import { Scripts } from "./scripts.js";
18
20
  import { ShotUse, shotsUsed } from "./shots-used.js";
19
21
  import { MAX_SLIDE_TIMING_MS } from "./timing.js";
20
22
  import { DEFAULT_TRANSITION_DURATION_MS, MAX_TRANSITION_DURATION_MS, MIN_TRANSITION_DURATION_MS, Transition, TransitionInput } from "./transition.js";
21
- import { Fill, SLOT_TYPES, SlotDeclaration, SlotDeclarationInput, SlotReport, SlotSource, SlotState, SlotType, SlotValue, Slots, SlotsInput, SlotsOptions, mergeSlotDeclarations } from "./slots.js";
23
+ import { Fill, FillValues, SLOT_TYPES, SlotDeclaration, SlotDeclarationInput, SlotKey, SlotReport, SlotSource, SlotState, SlotType, SlotValue, Slots, SlotsInput, SlotsOptions, mergeSlotDeclarations } from "./slots.js";
22
24
  import { z } from "zod";
23
25
  //#region src/index.d.ts
24
26
  export declare const Margin: z.ZodObject<{
@@ -27,6 +29,11 @@ export declare const Margin: z.ZodObject<{
27
29
  bottom: z.ZodDefault<z.ZodNumber>;
28
30
  left: z.ZodDefault<z.ZodNumber>;
29
31
  }, z.core.$strip>;
32
+ export declare const MarkColor: z.ZodEnum<{
33
+ black: "black";
34
+ registration: "registration";
35
+ }>;
36
+ export type MarkColor = z.infer<typeof MarkColor>;
30
37
  export declare const Print: z.ZodObject<{
31
38
  paper: z.ZodUnion<readonly [z.ZodEnum<{
32
39
  letter: "letter";
@@ -78,11 +85,15 @@ export declare const Print: z.ZodObject<{
78
85
  bleed: z.ZodDefault<z.ZodNumber>;
79
86
  safe: z.ZodDefault<z.ZodNumber>;
80
87
  marks: z.ZodDefault<z.ZodBoolean>;
88
+ markColor: z.ZodDefault<z.ZodEnum<{
89
+ black: "black";
90
+ registration: "registration";
91
+ }>>;
81
92
  }, z.core.$strip>;
82
93
  export type Print = z.infer<typeof Print>;
83
94
  export type PrintInput = z.input<typeof Print>;
84
95
  export declare const MAX_IMPOSITION_CELLS = 10000;
85
- export declare const Imposition: z.ZodObject<{
96
+ export declare const Imposition: z.ZodPipe<z.ZodObject<{
86
97
  paper: z.ZodUnion<readonly [z.ZodEnum<{
87
98
  letter: "letter";
88
99
  legal: "legal";
@@ -135,10 +146,10 @@ export declare const Imposition: z.ZodObject<{
135
146
  bottom: z.ZodDefault<z.ZodNumber>;
136
147
  left: z.ZodDefault<z.ZodNumber>;
137
148
  }, z.core.$strip>>;
138
- columns: z.ZodNumber;
139
- rows: z.ZodNumber;
149
+ columns: z.ZodOptional<z.ZodNumber>;
150
+ rows: z.ZodOptional<z.ZodNumber>;
140
151
  cell: z.ZodObject<{
141
- width: z.ZodNumber;
152
+ width: z.ZodOptional<z.ZodNumber>;
142
153
  height: z.ZodNumber;
143
154
  }, z.core.$strip>;
144
155
  gap: z.ZodDefault<z.ZodObject<{
@@ -155,7 +166,7 @@ export declare const Imposition: z.ZodObject<{
155
166
  sequence: "sequence";
156
167
  repeat: "repeat";
157
168
  }>>;
158
- sides: z.ZodDefault<z.ZodEnum<{
169
+ sides: z.ZodOptional<z.ZodEnum<{
159
170
  one: "one";
160
171
  two: "two";
161
172
  }>>;
@@ -169,8 +180,98 @@ export declare const Imposition: z.ZodObject<{
169
180
  rtl: "rtl";
170
181
  }>>;
171
182
  marks: z.ZodDefault<z.ZodBoolean>;
183
+ markColor: z.ZodDefault<z.ZodEnum<{
184
+ black: "black";
185
+ registration: "registration";
186
+ }>>;
172
187
  cornerMarks: z.ZodDefault<z.ZodBoolean>;
173
- }, z.core.$strip>;
188
+ fold: z.ZodOptional<z.ZodEnum<{
189
+ custom: "custom";
190
+ letter: "letter";
191
+ half: "half";
192
+ z: "z";
193
+ gate: "gate";
194
+ }>>;
195
+ panels: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
196
+ }, z.core.$strip>, z.ZodTransform<{
197
+ paper: "letter" | "legal" | "tabloid" | "a3" | "a4" | "a5" | "business-card-us" | "business-card-eu" | "business-card-square-us" | "business-card-slim-us" | "postcard-4x6" | "postcard-5x7" | "postcard-6x9" | "postcard-6x11" | "card-square-4in" | "half-letter" | "a6" | "dl" | "rack-card-4x9" | "rack-card-3.5x8.5" | "poster-12x18" | "poster-16x20" | "poster-18x24" | "poster-24x36" | "a2" | "a1" | "a0" | {
198
+ width: number;
199
+ height: number;
200
+ unit: "mm" | "in" | "pt";
201
+ };
202
+ orientation: "portrait" | "landscape";
203
+ unit: "mm" | "in" | "pt";
204
+ margin: {
205
+ top: number;
206
+ right: number;
207
+ bottom: number;
208
+ left: number;
209
+ };
210
+ cell: {
211
+ height: number;
212
+ width?: number | undefined;
213
+ };
214
+ gap: {
215
+ column: number;
216
+ row: number;
217
+ };
218
+ bleed: number;
219
+ safe: number;
220
+ fit: "contain" | "cover";
221
+ fill: "sequence" | "repeat";
222
+ flip: "long" | "short";
223
+ skip: number;
224
+ dir: "ltr" | "rtl";
225
+ marks: boolean;
226
+ markColor: "black" | "registration";
227
+ cornerMarks: boolean;
228
+ columns?: number | undefined;
229
+ rows?: number | undefined;
230
+ sides?: "one" | "two" | undefined;
231
+ fold?: "custom" | "letter" | "half" | "z" | "gate" | undefined;
232
+ panels?: number[] | undefined;
233
+ } & {
234
+ columns: number;
235
+ rows: number;
236
+ sides: "one" | "two";
237
+ }, {
238
+ paper: "letter" | "legal" | "tabloid" | "a3" | "a4" | "a5" | "business-card-us" | "business-card-eu" | "business-card-square-us" | "business-card-slim-us" | "postcard-4x6" | "postcard-5x7" | "postcard-6x9" | "postcard-6x11" | "card-square-4in" | "half-letter" | "a6" | "dl" | "rack-card-4x9" | "rack-card-3.5x8.5" | "poster-12x18" | "poster-16x20" | "poster-18x24" | "poster-24x36" | "a2" | "a1" | "a0" | {
239
+ width: number;
240
+ height: number;
241
+ unit: "mm" | "in" | "pt";
242
+ };
243
+ orientation: "portrait" | "landscape";
244
+ unit: "mm" | "in" | "pt";
245
+ margin: {
246
+ top: number;
247
+ right: number;
248
+ bottom: number;
249
+ left: number;
250
+ };
251
+ cell: {
252
+ height: number;
253
+ width?: number | undefined;
254
+ };
255
+ gap: {
256
+ column: number;
257
+ row: number;
258
+ };
259
+ bleed: number;
260
+ safe: number;
261
+ fit: "contain" | "cover";
262
+ fill: "sequence" | "repeat";
263
+ flip: "long" | "short";
264
+ skip: number;
265
+ dir: "ltr" | "rtl";
266
+ marks: boolean;
267
+ markColor: "black" | "registration";
268
+ cornerMarks: boolean;
269
+ columns?: number | undefined;
270
+ rows?: number | undefined;
271
+ sides?: "one" | "two" | undefined;
272
+ fold?: "custom" | "letter" | "half" | "z" | "gate" | undefined;
273
+ panels?: number[] | undefined;
274
+ }>>;
174
275
  export type Imposition = z.infer<typeof Imposition>;
175
276
  export type ImpositionInput = z.input<typeof Imposition>;
176
277
  export declare const PageSize: z.ZodUnion<readonly [z.ZodLiteral<"fluid">, z.ZodObject<{
@@ -252,6 +353,10 @@ export declare const Page: z.ZodObject<{
252
353
  bleed: z.ZodDefault<z.ZodNumber>;
253
354
  safe: z.ZodDefault<z.ZodNumber>;
254
355
  marks: z.ZodDefault<z.ZodBoolean>;
356
+ markColor: z.ZodDefault<z.ZodEnum<{
357
+ black: "black";
358
+ registration: "registration";
359
+ }>>;
255
360
  }, z.core.$strip>>;
256
361
  slots: z.ZodOptional<z.ZodArray<z.ZodPipe<z.ZodObject<{
257
362
  key: z.ZodString;
@@ -502,6 +607,10 @@ export declare function jsonSchemas(): {
502
607
  bleed: z.ZodDefault<z.ZodNumber>;
503
608
  safe: z.ZodDefault<z.ZodNumber>;
504
609
  marks: z.ZodDefault<z.ZodBoolean>;
610
+ markColor: z.ZodDefault<z.ZodEnum<{
611
+ black: "black";
612
+ registration: "registration";
613
+ }>>;
505
614
  }, z.core.$strip>>;
506
615
  slots: z.ZodOptional<z.ZodArray<z.ZodPipe<z.ZodObject<{
507
616
  key: z.ZodString;
@@ -548,7 +657,7 @@ export declare function jsonSchemas(): {
548
657
  ipa: z.ZodOptional<z.ZodString>;
549
658
  }, z.core.$strip>>;
550
659
  }, z.core.$strip>>;
551
- imposition: z.core.ZodStandardJSONSchemaPayload<z.ZodObject<{
660
+ imposition: z.core.ZodStandardJSONSchemaPayload<z.ZodPipe<z.ZodObject<{
552
661
  paper: z.ZodUnion<readonly [z.ZodEnum<{
553
662
  letter: "letter";
554
663
  legal: "legal";
@@ -601,10 +710,10 @@ export declare function jsonSchemas(): {
601
710
  bottom: z.ZodDefault<z.ZodNumber>;
602
711
  left: z.ZodDefault<z.ZodNumber>;
603
712
  }, z.core.$strip>>;
604
- columns: z.ZodNumber;
605
- rows: z.ZodNumber;
713
+ columns: z.ZodOptional<z.ZodNumber>;
714
+ rows: z.ZodOptional<z.ZodNumber>;
606
715
  cell: z.ZodObject<{
607
- width: z.ZodNumber;
716
+ width: z.ZodOptional<z.ZodNumber>;
608
717
  height: z.ZodNumber;
609
718
  }, z.core.$strip>;
610
719
  gap: z.ZodDefault<z.ZodObject<{
@@ -621,7 +730,7 @@ export declare function jsonSchemas(): {
621
730
  sequence: "sequence";
622
731
  repeat: "repeat";
623
732
  }>>;
624
- sides: z.ZodDefault<z.ZodEnum<{
733
+ sides: z.ZodOptional<z.ZodEnum<{
625
734
  one: "one";
626
735
  two: "two";
627
736
  }>>;
@@ -635,8 +744,98 @@ export declare function jsonSchemas(): {
635
744
  rtl: "rtl";
636
745
  }>>;
637
746
  marks: z.ZodDefault<z.ZodBoolean>;
747
+ markColor: z.ZodDefault<z.ZodEnum<{
748
+ black: "black";
749
+ registration: "registration";
750
+ }>>;
638
751
  cornerMarks: z.ZodDefault<z.ZodBoolean>;
639
- }, z.core.$strip>>;
752
+ fold: z.ZodOptional<z.ZodEnum<{
753
+ custom: "custom";
754
+ letter: "letter";
755
+ half: "half";
756
+ z: "z";
757
+ gate: "gate";
758
+ }>>;
759
+ panels: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
760
+ }, z.core.$strip>, z.ZodTransform<{
761
+ paper: "letter" | "legal" | "tabloid" | "a3" | "a4" | "a5" | "business-card-us" | "business-card-eu" | "business-card-square-us" | "business-card-slim-us" | "postcard-4x6" | "postcard-5x7" | "postcard-6x9" | "postcard-6x11" | "card-square-4in" | "half-letter" | "a6" | "dl" | "rack-card-4x9" | "rack-card-3.5x8.5" | "poster-12x18" | "poster-16x20" | "poster-18x24" | "poster-24x36" | "a2" | "a1" | "a0" | {
762
+ width: number;
763
+ height: number;
764
+ unit: "mm" | "in" | "pt";
765
+ };
766
+ orientation: "portrait" | "landscape";
767
+ unit: "mm" | "in" | "pt";
768
+ margin: {
769
+ top: number;
770
+ right: number;
771
+ bottom: number;
772
+ left: number;
773
+ };
774
+ cell: {
775
+ height: number;
776
+ width?: number | undefined;
777
+ };
778
+ gap: {
779
+ column: number;
780
+ row: number;
781
+ };
782
+ bleed: number;
783
+ safe: number;
784
+ fit: "contain" | "cover";
785
+ fill: "sequence" | "repeat";
786
+ flip: "long" | "short";
787
+ skip: number;
788
+ dir: "ltr" | "rtl";
789
+ marks: boolean;
790
+ markColor: "black" | "registration";
791
+ cornerMarks: boolean;
792
+ columns?: number | undefined;
793
+ rows?: number | undefined;
794
+ sides?: "one" | "two" | undefined;
795
+ fold?: "custom" | "letter" | "half" | "z" | "gate" | undefined;
796
+ panels?: number[] | undefined;
797
+ } & {
798
+ columns: number;
799
+ rows: number;
800
+ sides: "one" | "two";
801
+ }, {
802
+ paper: "letter" | "legal" | "tabloid" | "a3" | "a4" | "a5" | "business-card-us" | "business-card-eu" | "business-card-square-us" | "business-card-slim-us" | "postcard-4x6" | "postcard-5x7" | "postcard-6x9" | "postcard-6x11" | "card-square-4in" | "half-letter" | "a6" | "dl" | "rack-card-4x9" | "rack-card-3.5x8.5" | "poster-12x18" | "poster-16x20" | "poster-18x24" | "poster-24x36" | "a2" | "a1" | "a0" | {
803
+ width: number;
804
+ height: number;
805
+ unit: "mm" | "in" | "pt";
806
+ };
807
+ orientation: "portrait" | "landscape";
808
+ unit: "mm" | "in" | "pt";
809
+ margin: {
810
+ top: number;
811
+ right: number;
812
+ bottom: number;
813
+ left: number;
814
+ };
815
+ cell: {
816
+ height: number;
817
+ width?: number | undefined;
818
+ };
819
+ gap: {
820
+ column: number;
821
+ row: number;
822
+ };
823
+ bleed: number;
824
+ safe: number;
825
+ fit: "contain" | "cover";
826
+ fill: "sequence" | "repeat";
827
+ flip: "long" | "short";
828
+ skip: number;
829
+ dir: "ltr" | "rtl";
830
+ marks: boolean;
831
+ markColor: "black" | "registration";
832
+ cornerMarks: boolean;
833
+ columns?: number | undefined;
834
+ rows?: number | undefined;
835
+ sides?: "one" | "two" | undefined;
836
+ fold?: "custom" | "letter" | "half" | "z" | "gate" | undefined;
837
+ panels?: number[] | undefined;
838
+ }>>>;
640
839
  deck: z.core.ZodStandardJSONSchemaPayload<z.ZodObject<{
641
840
  title: z.ZodString;
642
841
  size: z.ZodDefault<z.ZodObject<{
@@ -1139,4 +1338,4 @@ export declare function jsonSchemas(): {
1139
1338
  }>>>;
1140
1339
  };
1141
1340
  //#endregion
1142
- export { Annotation, type ArrangeOptions, Board, type BoardInput, BoardItem, type BoardItemAnchor, BoardLabel, type BoardListingGroup, BoardSection, type BoardShapes, type BoardView, Book, BookContents, BookFrontMatterEntry, type BookInput, BookMode, BookPage, BookSection, BookView, type BookViewInput, Box, CUSTOM_PAPER_MAX_MM, CUSTOM_PAPER_MIN_MM, Chapter, Cue, DECK_SIZE, DEFAULT_TRANSITION_DURATION_MS, Deck, type DeckFromSlidesOptions, type DeckInput, type DeckLimits, Direction, Fill, GridCell, type GridDropTarget, ImageFit, type Imposed, type ImpositionMarkEdge, type ImpositionSideMarks, Lexicon, MAKE_ROOM_LIMIT, MARK_GAP_MM, MARK_LENGTH_MM, MAX_BOARD_ZOOM, MAX_SLIDE_TIMING_MS, MAX_TRANSITION_DURATION_MS, MIN_BOARD_ITEM_WIDTH, MIN_BOARD_ZOOM, MIN_MARK_LENGTH_MM, MIN_TRANSITION_DURATION_MS, MM_PER_PT, Manifest, type MarkSegment, type MillimeterEdges, NAMED_PAPERS, type NamedPaper, type NamedPaperMetadata, Narration, NoteMarker, NumberSystem, ORIENTATIONS, type OmittedImpositionMark, Orientation, PAPER_GROUPS, PAPER_METADATA, PAPER_MM, PAPER_UNITS, PLAYBACK_MODES, PX_PER_MM, type PageFit, type PagePlacementKind, type PagePlacementLayout, Paper, type PaperBox, type PaperGroup, PaperUnit, type Placement, Playback, type PlaybackMode, Point, PrintSetting, PrintSettingInput, PronunciationEntry, PublishedShot, SECTION_GAP, SECTION_MIN_SIZE, SECTION_PADDING, SECTION_TITLE_ROOM, SHOT_KEY, SLOT_TYPES, Scripts, Shot, type ShotUse, Size, Slide, SlideContent, type SlideRow, SlotDeclaration, SlotDeclarationInput, SlotReport, SlotSource, SlotState, SlotType, SlotValue, Slots, SlotsInput, SlotsOptions, TextDirection, Transition, TransitionInput, Word, type ZoomBounds, addItem, annotationCueIssues, arrange, assignMembership, boardBounds, boardListing, boardListingIsEmpty, boardToScreen, deckFromSlides, deriveSectionCells, exceedsLimits, firstStrongDirection, fitPage, fitSection, fitTouchedSections, foldForSearch, formatNumber, fromMillimeters, gridDropMarkerBox, gridDropTarget, impose, impositionMarks, insertIntoGrid, isBookContents, isHebrew, itemAt, itemHeight, languageDirection, layoutSection, lexiconVersion, makeRoom, mergeSlotDeclarations, mirrorPlacement, moveItems, moveSection, nameMatches, noteMarker, noteMarkerIssues, pagePlacementLayout, paperPixels, parsePlayback, printBoxes, printPadding, printProperties, removeFromGrid, removeItems, resizeItem, resolveDirection, revealView, roundMillimeters, screenToBoard, settleBoard, sheetMm, shotsUsed, toMillimeters, visibleItems, zoomAt, zoomToFit };
1341
+ export { Annotation, type ArrangeOptions, Board, type BoardInput, BoardItem, type BoardItemAnchor, BoardLabel, type BoardListingGroup, BoardSection, type BoardShapes, type BoardView, Book, BookContents, BookFrontMatterEntry, type BookInput, BookMode, BookPage, BookSection, BookView, type BookViewInput, Box, CUSTOM_PAPER_MAX_MM, CUSTOM_PAPER_MIN_MM, Chapter, Cue, DECK_SIZE, DEFAULT_TRANSITION_DURATION_MS, Deck, type DeckFromSlidesOptions, type DeckInput, type DeckLimits, Direction, FOLD_DASH_OFF_MM, FOLD_DASH_ON_MM, FOLD_KINDS, FOLD_TUCK_IN_MM, Fill, FillValues, type FoldKind, GridCell, type GridDropTarget, ImageFit, type Imposed, type ImpositionMarkEdge, type ImpositionSideMarks, Lexicon, MAKE_ROOM_LIMIT, MARK_GAP_MM, MARK_LENGTH_MM, MAX_BOARD_ZOOM, MAX_SLIDE_TIMING_MS, MAX_TRANSITION_DURATION_MS, MIN_BOARD_ITEM_WIDTH, MIN_BOARD_ZOOM, MIN_MARK_LENGTH_MM, MIN_TRANSITION_DURATION_MS, MM_PER_PT, Manifest, type MarkSegment, type MillimeterEdges, NAMED_PAPERS, type NamedPaper, type NamedPaperMetadata, Narration, NoteMarker, NumberSystem, ORIENTATIONS, type OmittedImpositionMark, Orientation, PAPER_FIT_TOLERANCE_MM, PAPER_GROUPS, PAPER_METADATA, PAPER_MM, PAPER_UNITS, PLAYBACK_MODES, PX_PER_MM, type PageFit, type PagePlacementKind, type PagePlacementLayout, Paper, type PaperBox, type PaperGroup, PaperUnit, type Placement, Playback, type PlaybackMode, Point, PrintSetting, PrintSettingInput, PronunciationEntry, PublishedShot, SECTION_GAP, SECTION_MIN_SIZE, SECTION_PADDING, SECTION_TITLE_ROOM, SHOT_KEY, SLOT_TYPES, Scripts, Shot, type ShotUse, Size, Slide, SlideContent, type SlideRow, SlotDeclaration, SlotDeclarationInput, SlotKey, SlotReport, SlotSource, SlotState, SlotType, SlotValue, Slots, SlotsInput, SlotsOptions, TextDirection, Transition, TransitionInput, Word, type ZoomBounds, addItem, annotationCueIssues, arrange, assignMembership, boardBounds, boardListing, boardListingIsEmpty, boardToScreen, deckFromSlides, deriveSectionCells, exceedsLimits, firstStrongDirection, fitPage, fitSection, fitTouchedSections, foldCellPages, foldColumns, foldForSearch, foldPageCountMessage, foldPanelMap, formatNumber, fromMillimeters, gridDropMarkerBox, gridDropTarget, impose, impositionMarks, insertIntoGrid, isBookContents, isHebrew, itemAt, itemHeight, languageDirection, layoutSection, lexiconVersion, makeRoom, mergeSlotDeclarations, mirrorPlacement, moveItems, moveSection, nameMatches, noteMarker, noteMarkerIssues, pagePlacementLayout, paperPixels, parsePlayback, printBoxes, printPadding, printProperties, removeFromGrid, removeItems, resizeItem, resolveDirection, revealView, roundMillimeters, screenToBoard, settleBoard, sheetMm, shotsUsed, toMillimeters, visibleItems, zoomAt, zoomToFit };
package/dist/index.js CHANGED
@@ -1,13 +1,15 @@
1
1
  import { Direction, TextDirection, firstStrongDirection, languageDirection, resolveDirection } from "./direction.js";
2
2
  import { Scripts } from "./scripts.js";
3
- import { SLOT_TYPES, SlotDeclaration, SlotDeclarationInput, SlotType, Slots, SlotsInput, mergeSlotDeclarations } from "./slots.js";
3
+ import { FillValues, SLOT_TYPES, SlotDeclaration, SlotDeclarationInput, SlotKey, SlotType, SlotValue, Slots, SlotsInput, mergeSlotDeclarations } from "./slots.js";
4
4
  import { MAX_SLIDE_TIMING_MS } from "./timing.js";
5
5
  import { DEFAULT_TRANSITION_DURATION_MS, MAX_TRANSITION_DURATION_MS, MIN_TRANSITION_DURATION_MS, Transition } from "./transition.js";
6
6
  import { Annotation, Box, Cue, DECK_SIZE, Deck, DeckShape, ImageFit, Manifest, Narration, PLAYBACK_MODES, Playback, Point, PublishedShot, SHOT_KEY, Shot, Size, Slide, SlideContent, Word, annotationCueIssues, exceedsLimits, parsePlayback } from "./deck.js";
7
7
  import { Board, BoardItem, BoardLabel, BoardSection, GridCell } from "./board.js";
8
8
  import { NoteMarker, NumberSystem, formatNumber, noteMarker } from "./numbering.js";
9
- import { CUSTOM_PAPER_MAX_MM, CUSTOM_PAPER_MIN_MM, MARK_GAP_MM, MARK_LENGTH_MM, MM_PER_PT, NAMED_PAPERS, ORIENTATIONS, Orientation, PAPER_GROUPS, PAPER_METADATA, PAPER_MM, PAPER_UNITS, PX_PER_MM, Paper, PaperUnit, PrintSetting, PrintSettingInput, fromMillimeters, paperPixels, printBoxes, printPadding, printProperties, roundMillimeters, sheetMm, toMillimeters } from "./paper.js";
9
+ import { CUSTOM_PAPER_MAX_MM, CUSTOM_PAPER_MIN_MM, FOLD_DASH_OFF_MM, FOLD_DASH_ON_MM, MARK_GAP_MM, MARK_LENGTH_MM, MM_PER_PT, NAMED_PAPERS, ORIENTATIONS, Orientation, PAPER_GROUPS, PAPER_METADATA, PAPER_MM, PAPER_UNITS, PX_PER_MM, Paper, PaperUnit, PrintSetting, PrintSettingInput, fromMillimeters, paperPixels, printBoxes, printPadding, printProperties, roundMillimeters, sheetMm, toMillimeters } from "./paper.js";
10
10
  import { Book, BookContents, BookFrontMatterEntry, BookMode, BookPage, BookSection, BookShape, BookView, Chapter, isBookContents, isHebrew, noteMarkerIssues } from "./book.js";
11
+ import { PAPER_FIT_TOLERANCE_MM, refuseOverflow, refuseSafe } from "./imposition-fit.js";
12
+ import { FOLD_KINDS, FOLD_TUCK_IN_MM, foldCellPages, foldColumns, foldPageCountMessage, foldPanelMap, refineFold, resolveImposition } from "./fold.js";
11
13
  import { Lexicon, PronunciationEntry, lexiconVersion } from "./lexicon.js";
12
14
  import { MIN_BOARD_ITEM_WIDTH, addItem, moveItems, moveSection, removeItems, resizeItem } from "./board-edit.js";
13
15
  import { MAX_BOARD_ZOOM, MIN_BOARD_ZOOM, arrange, boardBounds, boardToScreen, itemAt, itemHeight, revealView, screenToBoard, visibleItems, zoomAt, zoomToFit } from "./board-geometry.js";
@@ -27,14 +29,21 @@ const Margin = z.object({
27
29
  bottom: z.number().nonnegative().default(0),
28
30
  left: z.number().nonnegative().default(0)
29
31
  });
32
+ const MarkColor = z.enum(["black", "registration"]);
30
33
  const Print = z.object({
31
34
  paper: Paper,
32
35
  orientation: Orientation.default("portrait"),
33
36
  margin: Margin.optional(),
34
37
  bleed: z.number().nonnegative().default(0),
35
38
  safe: z.number().nonnegative().default(0),
36
- marks: z.boolean().default(false)
39
+ marks: z.boolean().default(false),
40
+ markColor: MarkColor.default("black")
37
41
  }).superRefine((print, ctx) => {
42
+ if (print.markColor === "registration" && !print.marks) ctx.addIssue({
43
+ code: "custom",
44
+ path: ["markColor"],
45
+ message: "markColor requires marks to be true"
46
+ });
38
47
  const trim = sheetMm(print);
39
48
  if (print.safe * 2 >= trim.width) ctx.addIssue({
40
49
  code: "custom",
@@ -62,10 +71,10 @@ const Imposition = z.object({
62
71
  bottom: 0,
63
72
  left: 0
64
73
  }),
65
- columns: z.number().int().positive(),
66
- rows: z.number().int().positive(),
74
+ columns: z.number().int().positive().optional(),
75
+ rows: z.number().int().positive().optional(),
67
76
  cell: z.object({
68
- width: z.number().positive(),
77
+ width: z.number().positive().optional(),
69
78
  height: z.number().positive()
70
79
  }),
71
80
  gap: ImpositionGap.default({
@@ -76,19 +85,61 @@ const Imposition = z.object({
76
85
  safe: z.number().nonnegative().default(0),
77
86
  fit: z.enum(["contain", "cover"]).default("contain"),
78
87
  fill: z.enum(["sequence", "repeat"]).default("sequence"),
79
- sides: z.enum(["one", "two"]).default("one"),
88
+ sides: z.enum(["one", "two"]).optional(),
80
89
  flip: z.enum(["long", "short"]).default("long"),
81
90
  skip: z.number().int().nonnegative().default(0),
82
91
  dir: z.enum(["ltr", "rtl"]).default("ltr"),
83
92
  marks: z.boolean().default(false),
84
- cornerMarks: z.boolean().default(false)
93
+ markColor: MarkColor.default("black"),
94
+ cornerMarks: z.boolean().default(false),
95
+ fold: z.enum(FOLD_KINDS).optional(),
96
+ panels: z.array(z.number().positive()).optional()
85
97
  }).superRefine((imposition, ctx) => {
86
- const cellCount = BigInt(imposition.columns) * BigInt(imposition.rows);
98
+ if (imposition.markColor === "registration" && !imposition.marks) ctx.addIssue({
99
+ code: "custom",
100
+ path: ["markColor"],
101
+ message: "markColor requires marks to be true"
102
+ });
87
103
  if (imposition.cornerMarks && !imposition.marks) ctx.addIssue({
88
104
  code: "custom",
89
105
  path: ["cornerMarks"],
90
106
  message: "cornerMarks requires marks to be true"
91
107
  });
108
+ if (imposition.panels !== void 0 && !imposition.fold) ctx.addIssue({
109
+ code: "custom",
110
+ path: ["panels"],
111
+ message: "panels needs fold; set fold or remove panels"
112
+ });
113
+ if (imposition.fold) {
114
+ const panelCount = imposition.panels?.length ?? 0;
115
+ if (panelCount > 1e4) {
116
+ ctx.addIssue({
117
+ code: "custom",
118
+ path: ["panels"],
119
+ message: `the fold has ${panelCount} panels and the ceiling is ${MAX_IMPOSITION_CELLS}; fewer panels clears this refusal`
120
+ });
121
+ return;
122
+ }
123
+ refineFold(imposition, ctx);
124
+ return;
125
+ }
126
+ if (imposition.columns === void 0) ctx.addIssue({
127
+ code: "custom",
128
+ path: ["columns"],
129
+ message: "columns is required; give a column count to clear this refusal"
130
+ });
131
+ if (imposition.rows === void 0) ctx.addIssue({
132
+ code: "custom",
133
+ path: ["rows"],
134
+ message: "rows is required; give a row count to clear this refusal"
135
+ });
136
+ if (imposition.cell.width === void 0) ctx.addIssue({
137
+ code: "custom",
138
+ path: ["cell", "width"],
139
+ message: "cell.width is required; give a cell width to clear this refusal"
140
+ });
141
+ if (imposition.columns === void 0 || imposition.rows === void 0 || imposition.cell.width === void 0) return;
142
+ const cellCount = BigInt(imposition.columns) * BigInt(imposition.rows);
92
143
  if (imposition.columns > 1e4 || imposition.rows > 1e4 || cellCount > BigInt(1e4)) {
93
144
  ctx.addIssue({
94
145
  code: "custom",
@@ -104,28 +155,13 @@ const Imposition = z.object({
104
155
  });
105
156
  const gridWidth = mm(imposition.margin.left + imposition.columns * imposition.cell.width + (imposition.columns - 1) * imposition.gap.column + imposition.margin.right);
106
157
  const gridHeight = mm(imposition.margin.top + imposition.rows * imposition.cell.height + (imposition.rows - 1) * imposition.gap.row + imposition.margin.bottom);
107
- if (gridWidth - paper.width > .01) ctx.addIssue({
108
- code: "custom",
109
- path: ["columns"],
110
- message: `the grid is ${roundMillimeters(gridWidth)}mm wide and the paper is ${paper.width}mm wide, an overflow of ${roundMillimeters(gridWidth - paper.width)}mm; reduce the horizontal margins, columns, cell width or column gap`
158
+ refuseOverflow(ctx, paper, {
159
+ width: gridWidth,
160
+ height: gridHeight
111
161
  });
112
- if (gridHeight - paper.height > .01) ctx.addIssue({
113
- code: "custom",
114
- path: ["rows"],
115
- message: `the grid is ${roundMillimeters(gridHeight)}mm high and the paper is ${paper.height}mm high, an overflow of ${roundMillimeters(gridHeight - paper.height)}mm; reduce the vertical margins, rows, cell height or row gap`
116
- });
117
- const safe = mm(imposition.safe);
118
- const cellWidth = mm(imposition.cell.width);
119
- const cellHeight = mm(imposition.cell.height);
120
- if (safe * 2 >= cellWidth) ctx.addIssue({
121
- code: "custom",
122
- path: ["safe"],
123
- message: `safe is ${roundMillimeters(safe)}mm on the left and right, but the cell is ${roundMillimeters(cellWidth)}mm wide; safe must leave area inside the cell`
124
- });
125
- if (safe * 2 >= cellHeight) ctx.addIssue({
126
- code: "custom",
127
- path: ["safe"],
128
- message: `safe is ${roundMillimeters(safe)}mm on the top and bottom, but the cell is ${roundMillimeters(cellHeight)}mm high; safe must leave area inside the cell`
162
+ refuseSafe(ctx, mm(imposition.safe), {
163
+ width: mm(imposition.cell.width),
164
+ height: mm(imposition.cell.height)
129
165
  });
130
166
  const cells = imposition.columns * imposition.rows;
131
167
  if (imposition.skip >= cells) ctx.addIssue({
@@ -133,7 +169,7 @@ const Imposition = z.object({
133
169
  path: ["skip"],
134
170
  message: `skip is ${imposition.skip}, but the grid has ${cells} cells; skip must be less than ${cells}`
135
171
  });
136
- });
172
+ }).transform(resolveImposition);
137
173
  const PageSize = z.union([
138
174
  z.literal("fluid"),
139
175
  Size,
@@ -170,4 +206,4 @@ function jsonSchemas() {
170
206
  };
171
207
  }
172
208
  //#endregion
173
- export { Annotation, Board, BoardItem, BoardLabel, BoardSection, Book, BookContents, BookFrontMatterEntry, BookMode, BookPage, BookSection, BookView, Box, CUSTOM_PAPER_MAX_MM, CUSTOM_PAPER_MIN_MM, Chapter, Cue, DECK_SIZE, DEFAULT_TRANSITION_DURATION_MS, Deck, Direction, GridCell, ImageFit, Imposition, Lexicon, MAKE_ROOM_LIMIT, MARK_GAP_MM, MARK_LENGTH_MM, MAX_BOARD_ZOOM, MAX_IMPOSITION_CELLS, MAX_SLIDE_TIMING_MS, MAX_TRANSITION_DURATION_MS, MIN_BOARD_ITEM_WIDTH, MIN_BOARD_ZOOM, MIN_MARK_LENGTH_MM, MIN_TRANSITION_DURATION_MS, MM_PER_PT, Manifest, Margin, NAMED_PAPERS, Narration, NoteMarker, NumberSystem, ORIENTATIONS, Orientation, PAPER_GROUPS, PAPER_METADATA, PAPER_MM, PAPER_UNITS, PLAYBACK_MODES, PX_PER_MM, Page, PageSize, Paper, PaperUnit, Playback, Point, Print, PrintSetting, PrintSettingInput, PronunciationEntry, PublishedShot, SECTION_GAP, SECTION_MIN_SIZE, SECTION_PADDING, SECTION_TITLE_ROOM, SHOT_KEY, SLOT_TYPES, Scripts, Shot, Size, Slide, SlideContent, SlotDeclaration, SlotDeclarationInput, SlotType, Slots, SlotsInput, TextDirection, Transition, Word, addItem, annotationCueIssues, arrange, assignMembership, boardBounds, boardListing, boardListingIsEmpty, boardToScreen, deckFromSlides, deriveSectionCells, exceedsLimits, firstStrongDirection, fitPage, fitSection, fitTouchedSections, foldForSearch, formatNumber, fromMillimeters, gridDropMarkerBox, gridDropTarget, impose, impositionMarks, insertIntoGrid, isBookContents, isHebrew, itemAt, itemHeight, jsonSchemas, languageDirection, layoutSection, lexiconVersion, makeRoom, mergeSlotDeclarations, mirrorPlacement, moveItems, moveSection, nameMatches, noteMarker, noteMarkerIssues, pagePlacementLayout, paperPixels, parsePlayback, printBoxes, printPadding, printProperties, removeFromGrid, removeItems, resizeItem, resolveDirection, revealView, roundMillimeters, screenToBoard, settleBoard, sheetMm, shotsUsed, toMillimeters, visibleItems, zoomAt, zoomToFit };
209
+ export { Annotation, Board, BoardItem, BoardLabel, BoardSection, Book, BookContents, BookFrontMatterEntry, BookMode, BookPage, BookSection, BookView, Box, CUSTOM_PAPER_MAX_MM, CUSTOM_PAPER_MIN_MM, Chapter, Cue, DECK_SIZE, DEFAULT_TRANSITION_DURATION_MS, Deck, Direction, FOLD_DASH_OFF_MM, FOLD_DASH_ON_MM, FOLD_KINDS, FOLD_TUCK_IN_MM, FillValues, GridCell, ImageFit, Imposition, Lexicon, MAKE_ROOM_LIMIT, MARK_GAP_MM, MARK_LENGTH_MM, MAX_BOARD_ZOOM, MAX_IMPOSITION_CELLS, MAX_SLIDE_TIMING_MS, MAX_TRANSITION_DURATION_MS, MIN_BOARD_ITEM_WIDTH, MIN_BOARD_ZOOM, MIN_MARK_LENGTH_MM, MIN_TRANSITION_DURATION_MS, MM_PER_PT, Manifest, Margin, MarkColor, NAMED_PAPERS, Narration, NoteMarker, NumberSystem, ORIENTATIONS, Orientation, PAPER_FIT_TOLERANCE_MM, PAPER_GROUPS, PAPER_METADATA, PAPER_MM, PAPER_UNITS, PLAYBACK_MODES, PX_PER_MM, Page, PageSize, Paper, PaperUnit, Playback, Point, Print, PrintSetting, PrintSettingInput, PronunciationEntry, PublishedShot, SECTION_GAP, SECTION_MIN_SIZE, SECTION_PADDING, SECTION_TITLE_ROOM, SHOT_KEY, SLOT_TYPES, Scripts, Shot, Size, Slide, SlideContent, SlotDeclaration, SlotDeclarationInput, SlotKey, SlotType, SlotValue, Slots, SlotsInput, TextDirection, Transition, Word, addItem, annotationCueIssues, arrange, assignMembership, boardBounds, boardListing, boardListingIsEmpty, boardToScreen, deckFromSlides, deriveSectionCells, exceedsLimits, firstStrongDirection, fitPage, fitSection, fitTouchedSections, foldCellPages, foldColumns, foldForSearch, foldPageCountMessage, foldPanelMap, formatNumber, fromMillimeters, gridDropMarkerBox, gridDropTarget, impose, impositionMarks, insertIntoGrid, isBookContents, isHebrew, itemAt, itemHeight, jsonSchemas, languageDirection, layoutSection, lexiconVersion, makeRoom, mergeSlotDeclarations, mirrorPlacement, moveItems, moveSection, nameMatches, noteMarker, noteMarkerIssues, pagePlacementLayout, paperPixels, parsePlayback, printBoxes, printPadding, printProperties, removeFromGrid, removeItems, resizeItem, resolveDirection, revealView, roundMillimeters, screenToBoard, settleBoard, sheetMm, shotsUsed, toMillimeters, visibleItems, zoomAt, zoomToFit };
package/dist/paper.d.ts CHANGED
@@ -291,6 +291,8 @@ export type PrintSettingInput = z.input<typeof PrintSettingInput>;
291
291
  export declare const MM_PER_PT: number;
292
292
  export declare const MARK_LENGTH_MM = 5;
293
293
  export declare const MARK_GAP_MM = 1;
294
+ export declare const FOLD_DASH_ON_MM = 2;
295
+ export declare const FOLD_DASH_OFF_MM = 1;
294
296
  export declare const roundMillimeters: (mm: number) => number;
295
297
  export declare function toMillimeters(value: number, unit: PaperUnit): number;
296
298
  export declare function fromMillimeters(millimeters: number, unit: PaperUnit): number;
@@ -322,6 +324,7 @@ export interface MarkSegment {
322
324
  y1: number;
323
325
  x2: number;
324
326
  y2: number;
327
+ dashed?: boolean;
325
328
  }
326
329
  export interface PrintBoxes {
327
330
  media: {
package/dist/paper.js CHANGED
@@ -206,6 +206,8 @@ const PrintSettingInput = z.strictObject(PrintSettingShape);
206
206
  const MM_PER_PT = 25.4 / 72;
207
207
  const MARK_LENGTH_MM = 5;
208
208
  const MARK_GAP_MM = 1;
209
+ const FOLD_DASH_ON_MM = 2;
210
+ const FOLD_DASH_OFF_MM = 1;
209
211
  const roundMillimeters = (mm) => Math.round(mm * 100) / 100;
210
212
  function toMillimeters(value, unit) {
211
213
  return value * (unit === "in" ? 25.4 : unit === "pt" ? MM_PER_PT : 1);
@@ -483,4 +485,4 @@ function printBoxes(print) {
483
485
  };
484
486
  }
485
487
  //#endregion
486
- export { CUSTOM_PAPER_MAX_MM, CUSTOM_PAPER_MIN_MM, MARK_GAP_MM, MARK_LENGTH_MM, MM_PER_PT, NAMED_PAPERS, ORIENTATIONS, Orientation, PAPER_GROUPS, PAPER_METADATA, PAPER_MM, PAPER_UNITS, PX_PER_MM, Paper, PaperUnit, PrintSetting, PrintSettingInput, fromMillimeters, paperPixels, printBoxes, printPadding, printProperties, roundMillimeters, sheetMm, toMillimeters };
488
+ export { CUSTOM_PAPER_MAX_MM, CUSTOM_PAPER_MIN_MM, FOLD_DASH_OFF_MM, FOLD_DASH_ON_MM, MARK_GAP_MM, MARK_LENGTH_MM, MM_PER_PT, NAMED_PAPERS, ORIENTATIONS, Orientation, PAPER_GROUPS, PAPER_METADATA, PAPER_MM, PAPER_UNITS, PX_PER_MM, Paper, PaperUnit, PrintSetting, PrintSettingInput, fromMillimeters, paperPixels, printBoxes, printPadding, printProperties, roundMillimeters, sheetMm, toMillimeters };
package/dist/slots.d.ts CHANGED
@@ -10,6 +10,8 @@ export declare const SlotType: z.ZodEnum<{
10
10
  image: "image";
11
11
  }>;
12
12
  export type SlotType = z.infer<typeof SlotType>;
13
+ export declare const SlotKey: z.ZodString;
14
+ export type SlotKey = z.infer<typeof SlotKey>;
13
15
  export declare const SlotDeclaration: z.ZodPipe<z.ZodObject<{
14
16
  key: z.ZodString;
15
17
  label: z.ZodString;
@@ -164,13 +166,18 @@ export declare const SlotsInput: z.ZodArray<z.ZodPipe<z.ZodObject<{
164
166
  minSize?: number | undefined;
165
167
  }>>>;
166
168
  export type SlotsInput = z.input<typeof SlotsInput>;
167
- export type SlotValue = string | {
168
- asset: string;
169
- };
169
+ export declare const SlotValue: z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
170
+ asset: z.ZodString;
171
+ }, z.core.$strip>]>;
172
+ export type SlotValue = z.infer<typeof SlotValue>;
173
+ export declare const FillValues: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
174
+ asset: z.ZodString;
175
+ }, z.core.$strip>]>>;
176
+ export type FillValues = z.infer<typeof FillValues>;
170
177
  export interface Fill {
171
178
  id: string;
172
179
  label?: string;
173
- values: Record<string, SlotValue>;
180
+ values: FillValues;
174
181
  }
175
182
  export interface SlotSource {
176
183
  id: string;
package/dist/slots.js CHANGED
@@ -9,8 +9,9 @@ const SLOT_TYPES = [
9
9
  "image"
10
10
  ];
11
11
  const SlotType = z.enum(SLOT_TYPES);
12
+ const SlotKey = z.string().regex(/^[^.\s]+(?:\.[^.\s]+)*$/, "a slot key must be a dotted path");
12
13
  const SlotDeclarationShape = {
13
- key: z.string().regex(/^[^.\s]+(?:\.[^.\s]+)*$/, "a slot key must be a dotted path"),
14
+ key: SlotKey,
14
15
  label: z.string().min(1),
15
16
  type: SlotType,
16
17
  required: z.boolean().default(false),
@@ -69,6 +70,8 @@ const SlotsInput = z.array(SlotDeclarationInput).superRefine((slots, ctx) => {
69
70
  seen.add(slot.key);
70
71
  });
71
72
  });
73
+ const SlotValue = z.union([z.string(), z.object({ asset: z.string() })]);
74
+ const FillValues = z.record(SlotKey, SlotValue);
72
75
  function mergeSlotDeclarations(...groups) {
73
76
  const merged = /* @__PURE__ */ new Map();
74
77
  for (const slot of groups.flat()) {
@@ -82,4 +85,4 @@ function mergeSlotDeclarations(...groups) {
82
85
  return [...merged.values()];
83
86
  }
84
87
  //#endregion
85
- export { SLOT_TYPES, SlotDeclaration, SlotDeclarationInput, SlotType, Slots, SlotsInput, mergeSlotDeclarations };
88
+ export { FillValues, SLOT_TYPES, SlotDeclaration, SlotDeclarationInput, SlotKey, SlotType, SlotValue, Slots, SlotsInput, mergeSlotDeclarations };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@segnavia/format",
3
- "version": "0.24.0",
3
+ "version": "0.26.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {