@segnavia/format 0.37.0 → 0.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/board-edit.d.ts +2 -1
  2. package/dist/board-geometry.d.ts +2 -1
  3. package/dist/board-section-grid.d.ts +2 -1
  4. package/dist/board-sections.d.ts +2 -1
  5. package/dist/board.d.ts +8 -8
  6. package/dist/board.js +15 -11
  7. package/dist/book-exports.d.ts +4 -0
  8. package/dist/book-section.d.ts +225 -3
  9. package/dist/book-section.js +82 -17
  10. package/dist/book.d.ts +878 -416
  11. package/dist/book.js +236 -37
  12. package/dist/cover.d.ts +337 -0
  13. package/dist/cover.js +100 -0
  14. package/dist/deck-from-slides.d.ts +23 -4
  15. package/dist/deck.d.ts +144 -42
  16. package/dist/deck.js +22 -24
  17. package/dist/dependency-policy.d.ts +12 -0
  18. package/dist/dependency-policy.js +42 -0
  19. package/dist/direction.d.ts +1 -1
  20. package/dist/font-collection.d.ts +8 -0
  21. package/dist/font-collection.js +191 -0
  22. package/dist/font-face.d.ts +8 -0
  23. package/dist/font-face.js +24 -0
  24. package/dist/font-refusal.d.ts +5 -0
  25. package/dist/font-refusal.js +9 -0
  26. package/dist/font-signature.d.ts +5 -0
  27. package/dist/font-signature.js +13 -0
  28. package/dist/fonts.d.ts +6 -1
  29. package/dist/fonts.js +3 -1
  30. package/dist/geometry.d.ts +20 -0
  31. package/dist/geometry.js +18 -0
  32. package/dist/image-fit.d.ts +10 -0
  33. package/dist/image-fit.js +10 -0
  34. package/dist/imposition-marks.d.ts +1 -1
  35. package/dist/imposition-schema.d.ts +185 -0
  36. package/dist/imposition-schema.js +122 -0
  37. package/dist/imposition.d.ts +8 -6
  38. package/dist/index.d.ts +29 -1797
  39. package/dist/index.js +30 -210
  40. package/dist/json-schemas.d.ts +1860 -0
  41. package/dist/json-schemas.js +43 -0
  42. package/dist/local-font-limits.d.ts +15 -0
  43. package/dist/local-font-limits.js +24 -0
  44. package/dist/media.d.ts +152 -0
  45. package/dist/media.js +119 -0
  46. package/dist/note-series.d.ts +70 -0
  47. package/dist/note-series.js +153 -0
  48. package/dist/page.d.ts +174 -0
  49. package/dist/page.js +37 -0
  50. package/dist/paper.d.ts +2 -1
  51. package/dist/paper.js +2 -1
  52. package/dist/placement-cycle.d.ts +5 -0
  53. package/dist/placement-cycle.js +30 -0
  54. package/dist/placement-refusal.d.ts +5 -0
  55. package/dist/placement-refusal.js +6 -0
  56. package/dist/placement.d.ts +76 -0
  57. package/dist/placement.js +100 -0
  58. package/dist/print.d.ts +72 -0
  59. package/dist/print.js +38 -0
  60. package/dist/printed-page-imposition.d.ts +2 -1
  61. package/dist/printed-pages.d.ts +14 -0
  62. package/dist/printed-pages.js +14 -1
  63. package/dist/shots-used.d.ts +0 -1
  64. package/dist/shots-used.js +2 -2
  65. package/dist/slots.d.ts +13 -13
  66. package/package.json +1 -1
@@ -1,5 +1,6 @@
1
1
  import { Board, BoardItem } from "./board.js";
2
- import { Point } from "./deck.js";
2
+ import { Point } from "./geometry.js";
3
+ import "./deck.js";
3
4
  //#region src/board-edit.d.ts
4
5
  export declare const MIN_BOARD_ITEM_WIDTH = 16;
5
6
  export type BoardItemAnchor = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
@@ -1,5 +1,6 @@
1
1
  import { Board, BoardItem } from "./board.js";
2
- import { Box, Point, Size } from "./deck.js";
2
+ import { Box, Point, Size } from "./geometry.js";
3
+ import "./deck.js";
3
4
  //#region src/board-geometry.d.ts
4
5
  export interface BoardShapes {
5
6
  items: Record<string, Size>;
@@ -1,5 +1,6 @@
1
1
  import { Board, GridCell } from "./board.js";
2
- import { Box, Point } from "./deck.js";
2
+ import { Box, Point } from "./geometry.js";
3
+ import "./deck.js";
3
4
  import { BoardShapes } from "./board-geometry.js";
4
5
  //#region src/board-section-grid.d.ts
5
6
  export type GridDropTarget = {
@@ -1,5 +1,6 @@
1
1
  import { Board, BoardSection } from "./board.js";
2
- import { Point } from "./deck.js";
2
+ import { Point } from "./geometry.js";
3
+ import "./deck.js";
3
4
  import { BoardShapes } from "./board-geometry.js";
4
5
  import { MAKE_ROOM_LIMIT, SECTION_GAP, SECTION_MIN_SIZE, SECTION_PADDING, SECTION_TITLE_ROOM } from "./board-section-constants.js";
5
6
  //#region src/board-sections.d.ts
package/dist/board.d.ts CHANGED
@@ -3,12 +3,12 @@ import { z } from "zod";
3
3
  export declare const BoardItem: z.ZodObject<{
4
4
  id: z.ZodString;
5
5
  kind: z.ZodEnum<{
6
- paper: "paper";
7
- image: "image";
6
+ deck: "deck";
8
7
  page: "page";
8
+ paper: "paper";
9
9
  book: "book";
10
+ media: "media";
10
11
  shot: "shot";
11
- deck: "deck";
12
12
  }>;
13
13
  address: z.ZodString;
14
14
  x: z.ZodNumber;
@@ -50,7 +50,7 @@ export declare const BoardSection: z.ZodObject<{
50
50
  }, z.core.$strip>>>;
51
51
  }, z.core.$strip>;
52
52
  export type BoardSection = z.infer<typeof BoardSection>;
53
- export declare const Board: z.ZodObject<{
53
+ export declare const Board: z.ZodPreprocess<z.ZodObject<{
54
54
  title: z.ZodString;
55
55
  direction: z.ZodEnum<{
56
56
  ltr: "ltr";
@@ -59,12 +59,12 @@ export declare const Board: z.ZodObject<{
59
59
  items: z.ZodArray<z.ZodObject<{
60
60
  id: z.ZodString;
61
61
  kind: z.ZodEnum<{
62
- paper: "paper";
63
- image: "image";
62
+ deck: "deck";
64
63
  page: "page";
64
+ paper: "paper";
65
65
  book: "book";
66
+ media: "media";
66
67
  shot: "shot";
67
- deck: "deck";
68
68
  }>;
69
69
  address: z.ZodString;
70
70
  x: z.ZodNumber;
@@ -97,7 +97,7 @@ export declare const Board: z.ZodObject<{
97
97
  column: z.ZodNumber;
98
98
  }, z.core.$strip>>>;
99
99
  }, z.core.$strip>>;
100
- }, z.core.$strip>;
100
+ }, z.core.$strip>, unknown>;
101
101
  export type Board = z.infer<typeof Board>;
102
102
  export type BoardInput = z.input<typeof Board>;
103
103
  //#endregion
package/dist/board.js CHANGED
@@ -1,15 +1,9 @@
1
1
  import { TextDirection } from "./direction.js";
2
- import { Box } from "./deck.js";
2
+ import { Box } from "./geometry.js";
3
+ import { AssetKind } from "./placement.js";
3
4
  import { z } from "zod";
4
5
  //#region src/board.ts
5
- const BoardKind = z.enum([
6
- "deck",
7
- "page",
8
- "paper",
9
- "book",
10
- "image",
11
- "shot"
12
- ], { error: "item kind is unknown; use deck, page, paper, book, image or shot" });
6
+ const BoardKind = AssetKind;
13
7
  const BoardItem = z.object({
14
8
  id: z.string(),
15
9
  kind: BoardKind,
@@ -37,13 +31,23 @@ const BoardSection = z.object({
37
31
  layout: z.enum(["auto", "manual"]).optional(),
38
32
  cells: z.array(GridCell).optional()
39
33
  });
40
- const Board = z.object({
34
+ const Board = z.preprocess((value) => {
35
+ if (typeof value !== "object" || value === null || !Array.isArray(value.items)) return value;
36
+ const board = value;
37
+ return {
38
+ ...board,
39
+ items: board.items.map((item) => typeof item === "object" && item !== null && item.kind === "image" ? {
40
+ ...item,
41
+ kind: "media"
42
+ } : item)
43
+ };
44
+ }, z.object({
41
45
  title: z.string(),
42
46
  direction: TextDirection,
43
47
  items: z.array(BoardItem),
44
48
  labels: z.array(BoardLabel),
45
49
  sections: z.array(BoardSection)
46
- }).superRefine((board, ctx) => {
50
+ })).superRefine((board, ctx) => {
47
51
  const ids = /* @__PURE__ */ new Set();
48
52
  const checkIds = (entries, listName) => {
49
53
  entries.forEach((entry, index) => {
@@ -0,0 +1,4 @@
1
+ import { NoteNumbering, NotePlacement, NoteSeries, NoteSeriesInput, ResolvedNoteSeries, noteMarkerIssues, resolveNoteSeries } from "./note-series.js";
2
+ import { BookChapterEntry, BookContents, BookDivision, BookDivisions, BookFrontMatterEntry, BookItem, BookOpens, BookSection, BookSectionEntry, BookSectionParents, BookTemplate, Chapter, DesignedPage, DesignedSection, MAX_PART_DEPTH, Part, PlacedSection, REGION_NAME, TemplatedPage, TemplatedSection, bookSections, isBookContents, isChapter, isDesignedSection, isPart, isPlacedSection, isTemplatedSection } from "./book-section.js";
3
+ import { Book, BookInput, BookMode, BookPage, BookRunningHead, BookRunningHeadSource, BookView, BookViewInput, BookViewPagination, resolveBookPagination } from "./book.js";
4
+ export { Book, BookChapterEntry, BookContents, type BookDivision, type BookDivisions, BookFrontMatterEntry, type BookInput, BookItem, BookMode, BookOpens, BookPage, BookRunningHead, BookRunningHeadSource, BookSection, type BookSectionEntry, BookSectionParents, BookTemplate, BookView, type BookViewInput, BookViewPagination, Chapter, DesignedPage, DesignedSection, MAX_PART_DEPTH, NoteNumbering, NotePlacement, NoteSeries, type NoteSeriesInput, Part, PlacedSection, REGION_NAME, type ResolvedNoteSeries, TemplatedPage, TemplatedSection, bookSections, isBookContents, isChapter, isDesignedSection, isPart, isPlacedSection, isTemplatedSection, noteMarkerIssues, resolveBookPagination, resolveNoteSeries };
@@ -20,6 +20,7 @@ export declare const DesignedPage: z.ZodObject<{
20
20
  }, z.core.$strip>;
21
21
  export type DesignedPage = z.infer<typeof DesignedPage>;
22
22
  export declare const REGION_NAME: RegExp;
23
+ export declare const MAX_PART_DEPTH = 6;
23
24
  export declare const TemplatedPage: z.ZodObject<{
24
25
  template: z.ZodOptional<z.ZodString>;
25
26
  regions: z.ZodRecord<z.ZodString, z.ZodString>;
@@ -37,6 +38,25 @@ export declare const BookTemplate: z.ZodObject<{
37
38
  }, z.core.$strip>>;
38
39
  }, z.core.$strip>;
39
40
  export type BookTemplate = z.infer<typeof BookTemplate>;
41
+ declare const partFields: {
42
+ name: z.ZodString;
43
+ title: z.ZodOptional<z.ZodString>;
44
+ html: z.ZodOptional<z.ZodString>;
45
+ contents: z.ZodDefault<z.ZodBoolean>;
46
+ opens: z.ZodOptional<z.ZodEnum<{
47
+ any: "any";
48
+ recto: "recto";
49
+ verso: "verso";
50
+ }>>;
51
+ parents: z.ZodOptional<z.ZodObject<{
52
+ opener: z.ZodOptional<z.ZodString>;
53
+ recto: z.ZodOptional<z.ZodString>;
54
+ verso: z.ZodOptional<z.ZodString>;
55
+ blank: z.ZodOptional<z.ZodString>;
56
+ fixed: z.ZodOptional<z.ZodString>;
57
+ }, z.core.$strip>>;
58
+ runningHead: z.ZodOptional<z.ZodString>;
59
+ };
40
60
  export declare const DesignedSection: z.ZodObject<{
41
61
  pages: z.ZodArray<z.ZodObject<{
42
62
  html: z.ZodString;
@@ -116,6 +136,64 @@ export declare const BookContents: z.ZodObject<{
116
136
  }, z.core.$strip>>;
117
137
  }, z.core.$strip>;
118
138
  export type BookContents = z.infer<typeof BookContents>;
139
+ export declare const PlacedSection: z.ZodObject<{
140
+ title: z.ZodOptional<z.ZodString>;
141
+ contents: z.ZodDefault<z.ZodBoolean>;
142
+ opens: z.ZodOptional<z.ZodEnum<{
143
+ any: "any";
144
+ recto: "recto";
145
+ verso: "verso";
146
+ }>>;
147
+ parents: z.ZodOptional<z.ZodObject<{
148
+ opener: z.ZodOptional<z.ZodString>;
149
+ recto: z.ZodOptional<z.ZodString>;
150
+ verso: z.ZodOptional<z.ZodString>;
151
+ blank: z.ZodOptional<z.ZodString>;
152
+ fixed: z.ZodOptional<z.ZodString>;
153
+ }, z.core.$strip>>;
154
+ kind: z.ZodLiteral<"placed">;
155
+ placement: z.ZodObject<{
156
+ kind: z.ZodEnum<{
157
+ deck: "deck";
158
+ page: "page";
159
+ paper: "paper";
160
+ book: "book";
161
+ media: "media";
162
+ shot: "shot";
163
+ }>;
164
+ address: z.ZodString;
165
+ page: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
166
+ box: z.ZodOptional<z.ZodEnum<{
167
+ media: "media";
168
+ bleed: "bleed";
169
+ crop: "crop";
170
+ trim: "trim";
171
+ art: "art";
172
+ }>>;
173
+ crop: z.ZodOptional<z.ZodObject<{
174
+ top: z.ZodOptional<z.ZodString>;
175
+ right: z.ZodOptional<z.ZodString>;
176
+ bottom: z.ZodOptional<z.ZodString>;
177
+ left: z.ZodOptional<z.ZodString>;
178
+ }, z.core.$strip>>;
179
+ fit: z.ZodOptional<z.ZodEnum<{
180
+ width: "width";
181
+ contain: "contain";
182
+ cover: "cover";
183
+ focus: "focus";
184
+ }>>;
185
+ alt: z.ZodOptional<z.ZodObject<{
186
+ text: z.ZodString;
187
+ lang: z.ZodOptional<z.ZodString>;
188
+ dir: z.ZodOptional<z.ZodEnum<{
189
+ auto: "auto";
190
+ ltr: "ltr";
191
+ rtl: "rtl";
192
+ }>>;
193
+ }, z.core.$strip>>;
194
+ }, z.core.$strip>;
195
+ }, z.core.$strip>;
196
+ export type PlacedSection = z.infer<typeof PlacedSection>;
119
197
  export declare const BookFrontMatterEntry: z.ZodDiscriminatedUnion<[z.ZodObject<{
120
198
  pages: z.ZodArray<z.ZodObject<{
121
199
  html: z.ZodString;
@@ -171,6 +249,62 @@ export declare const BookFrontMatterEntry: z.ZodDiscriminatedUnion<[z.ZodObject<
171
249
  blank: z.ZodOptional<z.ZodString>;
172
250
  fixed: z.ZodOptional<z.ZodString>;
173
251
  }, z.core.$strip>>;
252
+ }, z.core.$strip>, z.ZodObject<{
253
+ title: z.ZodOptional<z.ZodString>;
254
+ contents: z.ZodDefault<z.ZodBoolean>;
255
+ opens: z.ZodOptional<z.ZodEnum<{
256
+ any: "any";
257
+ recto: "recto";
258
+ verso: "verso";
259
+ }>>;
260
+ parents: z.ZodOptional<z.ZodObject<{
261
+ opener: z.ZodOptional<z.ZodString>;
262
+ recto: z.ZodOptional<z.ZodString>;
263
+ verso: z.ZodOptional<z.ZodString>;
264
+ blank: z.ZodOptional<z.ZodString>;
265
+ fixed: z.ZodOptional<z.ZodString>;
266
+ }, z.core.$strip>>;
267
+ kind: z.ZodLiteral<"placed">;
268
+ placement: z.ZodObject<{
269
+ kind: z.ZodEnum<{
270
+ deck: "deck";
271
+ page: "page";
272
+ paper: "paper";
273
+ book: "book";
274
+ media: "media";
275
+ shot: "shot";
276
+ }>;
277
+ address: z.ZodString;
278
+ page: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
279
+ box: z.ZodOptional<z.ZodEnum<{
280
+ media: "media";
281
+ bleed: "bleed";
282
+ crop: "crop";
283
+ trim: "trim";
284
+ art: "art";
285
+ }>>;
286
+ crop: z.ZodOptional<z.ZodObject<{
287
+ top: z.ZodOptional<z.ZodString>;
288
+ right: z.ZodOptional<z.ZodString>;
289
+ bottom: z.ZodOptional<z.ZodString>;
290
+ left: z.ZodOptional<z.ZodString>;
291
+ }, z.core.$strip>>;
292
+ fit: z.ZodOptional<z.ZodEnum<{
293
+ width: "width";
294
+ contain: "contain";
295
+ cover: "cover";
296
+ focus: "focus";
297
+ }>>;
298
+ alt: z.ZodOptional<z.ZodObject<{
299
+ text: z.ZodString;
300
+ lang: z.ZodOptional<z.ZodString>;
301
+ dir: z.ZodOptional<z.ZodEnum<{
302
+ auto: "auto";
303
+ ltr: "ltr";
304
+ rtl: "rtl";
305
+ }>>;
306
+ }, z.core.$strip>>;
307
+ }, z.core.$strip>;
174
308
  }, z.core.$strip>, z.ZodObject<{
175
309
  title: z.ZodOptional<z.ZodString>;
176
310
  contents: z.ZodDefault<z.ZodBoolean>;
@@ -248,6 +382,62 @@ export declare const BookChapterEntry: z.ZodDiscriminatedUnion<[z.ZodObject<{
248
382
  fixed: z.ZodOptional<z.ZodString>;
249
383
  }, z.core.$strip>>;
250
384
  kind: z.ZodLiteral<"templated">;
385
+ }, z.core.$strip>, z.ZodObject<{
386
+ title: z.ZodOptional<z.ZodString>;
387
+ contents: z.ZodDefault<z.ZodBoolean>;
388
+ opens: z.ZodOptional<z.ZodEnum<{
389
+ any: "any";
390
+ recto: "recto";
391
+ verso: "verso";
392
+ }>>;
393
+ parents: z.ZodOptional<z.ZodObject<{
394
+ opener: z.ZodOptional<z.ZodString>;
395
+ recto: z.ZodOptional<z.ZodString>;
396
+ verso: z.ZodOptional<z.ZodString>;
397
+ blank: z.ZodOptional<z.ZodString>;
398
+ fixed: z.ZodOptional<z.ZodString>;
399
+ }, z.core.$strip>>;
400
+ kind: z.ZodLiteral<"placed">;
401
+ placement: z.ZodObject<{
402
+ kind: z.ZodEnum<{
403
+ deck: "deck";
404
+ page: "page";
405
+ paper: "paper";
406
+ book: "book";
407
+ media: "media";
408
+ shot: "shot";
409
+ }>;
410
+ address: z.ZodString;
411
+ page: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
412
+ box: z.ZodOptional<z.ZodEnum<{
413
+ media: "media";
414
+ bleed: "bleed";
415
+ crop: "crop";
416
+ trim: "trim";
417
+ art: "art";
418
+ }>>;
419
+ crop: z.ZodOptional<z.ZodObject<{
420
+ top: z.ZodOptional<z.ZodString>;
421
+ right: z.ZodOptional<z.ZodString>;
422
+ bottom: z.ZodOptional<z.ZodString>;
423
+ left: z.ZodOptional<z.ZodString>;
424
+ }, z.core.$strip>>;
425
+ fit: z.ZodOptional<z.ZodEnum<{
426
+ width: "width";
427
+ contain: "contain";
428
+ cover: "cover";
429
+ focus: "focus";
430
+ }>>;
431
+ alt: z.ZodOptional<z.ZodObject<{
432
+ text: z.ZodString;
433
+ lang: z.ZodOptional<z.ZodString>;
434
+ dir: z.ZodOptional<z.ZodEnum<{
435
+ auto: "auto";
436
+ ltr: "ltr";
437
+ rtl: "rtl";
438
+ }>>;
439
+ }, z.core.$strip>>;
440
+ }, z.core.$strip>;
251
441
  }, z.core.$strip>, z.ZodObject<{
252
442
  title: z.ZodString;
253
443
  html: z.ZodString;
@@ -267,8 +457,40 @@ export declare const BookChapterEntry: z.ZodDiscriminatedUnion<[z.ZodObject<{
267
457
  kind: z.ZodOptional<z.ZodLiteral<"chapter">>;
268
458
  }, z.core.$strip>], "kind">;
269
459
  export type BookChapterEntry = z.infer<typeof BookChapterEntry>;
270
- export declare function isBookContents(entry: BookFrontMatterEntry): entry is BookContents;
271
- export declare function isDesignedSection(entry: BookFrontMatterEntry | BookChapterEntry): entry is DesignedSection;
272
- export declare function isTemplatedSection(entry: BookFrontMatterEntry | BookChapterEntry): entry is TemplatedSection;
460
+ export interface Part extends z.infer<z.ZodObject<typeof partFields>> {
461
+ children: BookItem[];
462
+ }
463
+ export type BookItem = Part | BookFrontMatterEntry | BookChapterEntry;
464
+ export declare const Part: z.ZodType<Part>;
465
+ export declare const BookItem: z.ZodType<BookItem>;
466
+ export type BookDivision = 'front' | 'body' | 'end';
467
+ interface BookSectionLocation {
468
+ ancestry: Array<{
469
+ name: string;
470
+ title?: string;
471
+ runningHead?: string;
472
+ id: string;
473
+ }>;
474
+ depth: number;
475
+ path: (string | number)[];
476
+ }
477
+ export type BookSectionEntry = BookSectionLocation & {
478
+ entry: BookItem;
479
+ division: BookDivision;
480
+ id?: string;
481
+ };
482
+ export declare function isPart(entry: BookItem): entry is Part;
483
+ export interface BookDivisions {
484
+ frontMatter: BookItem[];
485
+ body: BookItem[];
486
+ bodyKey?: 'body' | 'chapters';
487
+ endMatter: BookItem[];
488
+ }
489
+ /** The canonical reading order for every feature that consumes a book. */
490
+ export declare function bookSections(book: BookDivisions): BookSectionEntry[];
491
+ export declare function isBookContents(entry: BookItem): entry is BookContents;
492
+ export declare function isDesignedSection(entry: BookItem): entry is DesignedSection;
493
+ export declare function isTemplatedSection(entry: BookItem): entry is TemplatedSection;
494
+ export declare function isPlacedSection(entry: BookItem): entry is PlacedSection;
273
495
  export declare function isChapter(entry: BookChapterEntry): entry is Chapter;
274
496
  //#endregion
@@ -1,3 +1,4 @@
1
+ import { PlacementShape } from "./placement.js";
1
2
  import { BOOK_PARENT_NAMES, parentListIssues } from "./printed-pages.js";
2
3
  import { z } from "zod";
3
4
  //#region src/book-section.ts
@@ -15,6 +16,7 @@ const BookSectionParents = z.object({
15
16
  });
16
17
  const DesignedPage = z.object({ html: z.string() });
17
18
  const REGION_NAME = /^[A-Za-z][\w-]*$/;
19
+ const MAX_PART_DEPTH = 6;
18
20
  const TemplatedPage = z.object({
19
21
  template: z.string().min(1).optional(),
20
22
  regions: z.record(z.string(), z.string())
@@ -33,6 +35,15 @@ const sectionFields = {
33
35
  opens: BookOpens.optional(),
34
36
  parents: BookSectionParents.optional()
35
37
  };
38
+ const partFields = {
39
+ name: z.string().regex(REGION_NAME, "a part name must be an HTML name token"),
40
+ title: z.string().optional(),
41
+ html: z.string().optional(),
42
+ contents: z.boolean().default(true),
43
+ opens: BookOpens.optional(),
44
+ parents: BookSectionParents.optional(),
45
+ runningHead: z.string().optional()
46
+ };
36
47
  const DesignedSection = z.object({
37
48
  kind: z.literal("designed"),
38
49
  ...sectionFields,
@@ -54,11 +65,17 @@ const BookContents = z.object({
54
65
  opens: BookOpens.optional(),
55
66
  parents: BookSectionParents.optional()
56
67
  });
68
+ const PlacedSection = z.object({
69
+ kind: z.literal("placed"),
70
+ placement: PlacementShape,
71
+ ...sectionFields
72
+ });
57
73
  const flowingFront = BookSection.extend({ kind: z.literal("front").optional() });
58
74
  const BookFrontMatterEntry = z.discriminatedUnion("kind", [
59
75
  DesignedSection,
60
76
  TemplatedSection,
61
77
  BookContents,
78
+ PlacedSection,
62
79
  flowingFront
63
80
  ]);
64
81
  const Chapter = z.object({
@@ -72,8 +89,61 @@ const flowingChapter = Chapter.extend({ kind: z.literal("chapter").optional() })
72
89
  const BookChapterEntry = z.discriminatedUnion("kind", [
73
90
  DesignedSection,
74
91
  TemplatedSection,
92
+ PlacedSection,
75
93
  flowingChapter
76
94
  ]);
95
+ const Part = z.lazy(() => z.object({
96
+ ...partFields,
97
+ children: z.array(BookItem).default([])
98
+ }));
99
+ const BookItem = z.lazy(() => z.union([
100
+ Part,
101
+ BookFrontMatterEntry,
102
+ BookChapterEntry
103
+ ]));
104
+ function isPart(entry) {
105
+ return "name" in entry;
106
+ }
107
+ /** The canonical reading order for every feature that consumes a book. */
108
+ function bookSections(book) {
109
+ const sections = [];
110
+ let partNumber = 0;
111
+ const walk = (items, division, parentPath, ancestry) => {
112
+ items.forEach((entry, index) => {
113
+ const path = [...parentPath, index];
114
+ if (!isPart(entry)) {
115
+ sections.push({
116
+ entry,
117
+ division,
118
+ ancestry,
119
+ depth: ancestry.length,
120
+ path
121
+ });
122
+ return;
123
+ }
124
+ partNumber += 1;
125
+ const id = `segnavia-part-${partNumber}`;
126
+ if (entry.html !== void 0 || entry.title !== void 0) sections.push({
127
+ entry,
128
+ division,
129
+ ancestry,
130
+ depth: ancestry.length,
131
+ path,
132
+ id
133
+ });
134
+ walk(entry.children, division, [...path, "children"], [...ancestry, {
135
+ name: entry.name,
136
+ title: entry.title,
137
+ runningHead: entry.runningHead,
138
+ id
139
+ }]);
140
+ });
141
+ };
142
+ walk(book.frontMatter, "front", ["frontMatter"], []);
143
+ walk(book.body, "body", [book.bodyKey ?? "body"], []);
144
+ walk(book.endMatter, "end", ["endMatter"], []);
145
+ return sections;
146
+ }
77
147
  function isBookContents(entry) {
78
148
  return "kind" in entry && entry.kind === "contents";
79
149
  }
@@ -83,37 +153,32 @@ function isDesignedSection(entry) {
83
153
  function isTemplatedSection(entry) {
84
154
  return "kind" in entry && entry.kind === "templated";
85
155
  }
156
+ function isPlacedSection(entry) {
157
+ return "kind" in entry && entry.kind === "placed";
158
+ }
86
159
  function isChapter(entry) {
87
- return !isDesignedSection(entry) && !isTemplatedSection(entry);
160
+ return !isDesignedSection(entry) && !isTemplatedSection(entry) && !isPlacedSection(entry);
161
+ }
162
+ function pathLabel(path) {
163
+ return path.join(".");
88
164
  }
89
165
  function namedSections(book) {
90
- const front = book.frontMatter.map((entry, index) => {
91
- const path = ["frontMatter", index];
92
- return {
93
- label: entry.title ?? `frontMatter[${index}]`,
94
- path,
95
- parents: entry.parents,
96
- templated: isTemplatedSection(entry) ? entry : void 0
97
- };
98
- });
99
- const chapters = book.chapters.map((entry, index) => {
100
- const path = ["chapters", index];
166
+ return bookSections(book).map(({ entry, path }) => {
101
167
  if (isDesignedSection(entry) || isTemplatedSection(entry)) return {
102
- label: entry.title ?? `chapters[${index}]`,
168
+ label: entry.title ?? pathLabel(path),
103
169
  path,
104
170
  parents: entry.parents,
105
171
  templated: isTemplatedSection(entry) ? entry : void 0
106
172
  };
107
173
  return {
108
- label: entry.title,
174
+ label: entry.title ?? pathLabel(path),
109
175
  path,
110
176
  parents: entry.parents
111
177
  };
112
178
  });
113
- return [...front, ...chapters];
114
179
  }
115
180
  function hasKind(book, match) {
116
- return book.frontMatter.some(match) || book.chapters.some(match);
181
+ return bookSections(book).some(({ entry }) => match(entry));
117
182
  }
118
183
  function unknownParent(label, role, name, path) {
119
184
  return {
@@ -205,4 +270,4 @@ function bookParentIssues(book) {
205
270
  return issues;
206
271
  }
207
272
  //#endregion
208
- export { BookChapterEntry, BookContents, BookFrontMatterEntry, BookOpens, BookSection, BookSectionParents, BookTemplate, Chapter, DesignedPage, DesignedSection, REGION_NAME, TemplatedPage, TemplatedSection, bookParentIssues, isBookContents, isChapter, isDesignedSection, isTemplatedSection };
273
+ export { BookChapterEntry, BookContents, BookFrontMatterEntry, BookItem, BookOpens, BookSection, BookSectionParents, BookTemplate, Chapter, DesignedPage, DesignedSection, MAX_PART_DEPTH, Part, PlacedSection, REGION_NAME, TemplatedPage, TemplatedSection, bookParentIssues, bookSections, isBookContents, isChapter, isDesignedSection, isPart, isPlacedSection, isTemplatedSection };