@openpresentation/cli 0.8.0 → 0.8.1

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/index.js CHANGED
@@ -8149,13 +8149,13 @@ import path2 from "path";
8149
8149
  // ../javascript/dist/index.js
8150
8150
  init_define_OPF_SKILLS();
8151
8151
 
8152
- // ../javascript/dist/chunk-NPOKUFEX.js
8152
+ // ../javascript/dist/chunk-EWJNRHXA.js
8153
8153
  init_define_OPF_SKILLS();
8154
8154
 
8155
- // ../javascript/dist/chunk-GCB6LGJM.js
8155
+ // ../javascript/dist/chunk-ZIL7MGZU.js
8156
8156
  init_define_OPF_SKILLS();
8157
8157
 
8158
- // ../javascript/dist/chunk-BAWLYSUN.js
8158
+ // ../javascript/dist/chunk-PQJRDNA6.js
8159
8159
  init_define_OPF_SKILLS();
8160
8160
  var record = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
8161
8161
  function tableGrid(value, path3 = "table") {
@@ -8263,8 +8263,105 @@ var headings = /* @__PURE__ */ new Set(["title", "subtitle", "tag"]);
8263
8263
  var rows = ["top", "middle", "bottom"];
8264
8264
  var columns = ["left", "center", "right"];
8265
8265
  var record2 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
8266
- var kind = (field) => field === "items" || field === "bullets" ? "list" : field;
8266
+ var kind = (field) => field === "items" ? "list" : field === "bullets" ? "text" : field;
8267
8267
  var round = (value) => Math.round(value * 1e6) / 1e6 || value;
8268
+ function layoutFurniture(input, options = {}) {
8269
+ const slide = record2(input), width = options.width ?? 1280, height = options.height ?? 720, scale = Math.min(width, height) / 720;
8270
+ const settings = { ...record2(record2(options.layout).composition), ...record2(slide.composition) };
8271
+ assertComposition(settings);
8272
+ const minimum = (settings.minFontSize ?? 16) * scale, size = Math.max(13 * scale, minimum), padding = (options.textRasterPadding ?? 2) * scale;
8273
+ if (![width, height, scale, minimum, padding].every(Number.isFinite) || width <= 0 || height <= 0 || minimum <= 0 || padding < 0) throw new RangeError("Furniture requires finite positive dimensions and nonnegative raster padding.");
8274
+ const number = options.slideNumber ?? (options.slideIndex ?? 0) + 1;
8275
+ if (!Number.isSafeInteger(number) || number < 1) throw new RangeError("Displayed slide number must be a positive safe integer.");
8276
+ const outlines = options.textMeasurement?.outlineBounds !== void 0, parts2 = [], diagnostics = [];
8277
+ const sourceRoot = `slides.${options.slideIndex ?? 0}`, organizations = Array.isArray(options.presentation?.organization) ? options.presentation.organization : [options.presentation?.organization];
8278
+ const primaryIndex = organizations.findIndex((item) => record2(item).role === "primary"), organizationIndex = primaryIndex >= 0 ? primaryIndex : organizations.findIndex(Boolean);
8279
+ const organization = record2(organizations[organizationIndex]), organizationPath = Array.isArray(options.presentation?.organization) ? `organization.${organizationIndex}.name` : "organization.name";
8280
+ const fontFamily = options.fonts?.body ?? "sans-serif";
8281
+ let headerBottom = 0, footerTop = height, configured = false;
8282
+ const error = (path3, message, code = "text-overflow") => diagnostics.push({ code, path: path3, message });
8283
+ for (const kind2 of ["header", "footer"]) {
8284
+ const local = record2(slide.design)[kind2] !== void 0, value = local ? record2(slide.design)[kind2] : options.presentation?.design?.[kind2];
8285
+ if (value === void 0 || value === false) continue;
8286
+ const root = local ? `${sourceRoot}.design.${kind2}` : `design.${kind2}`;
8287
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError("Header/footer content must be an object or false.");
8288
+ configured = true;
8289
+ const zones = [];
8290
+ for (const [index2, zone] of ["left", "center", "right"].entries()) {
8291
+ const content = record2(record2(value)[zone]), path3 = `${root}.${zone}`, x = width * (0.07 + index2 * 0.3), zoneWidth = width * 0.26, zoneParts = [];
8292
+ let y = 0;
8293
+ const add = (field, text, generated = false, sourcePath) => {
8294
+ if (text === void 0) return;
8295
+ if (typeof text !== "string") throw new TypeError(`Furniture field ${path3}.${field} requires string content.`);
8296
+ const partPath = `${path3}.${field}`, style = resolveTextStyle({ fontFamily, fontWeight: 400, italic: false, path: partPath }, options.textMeasurement);
8297
+ const fit = fitText(text, { width: Math.max(Number.MIN_VALUE, zoneWidth - (outlines ? 2 * padding : 0)), height: Number.MAX_VALUE }, size, size, textWidthMeasurer(style, options.textMeasurement));
8298
+ const ink = fit.sourceLines.map((line, index22) => {
8299
+ let outline = null;
8300
+ if (outlines) {
8301
+ for (const segment of line.segments) if (segment.kind === "text") {
8302
+ const bounds = measureTextOutline(text.slice(segment.start, segment.end), size, style, options.textMeasurement);
8303
+ if (bounds) {
8304
+ const next = { ...bounds, x: bounds.x + segment.x };
8305
+ if (!outline) outline = next;
8306
+ else {
8307
+ const right = Math.max(outline.x + outline.width, next.x + next.width), bottom = Math.max(outline.y + outline.height, next.y + next.height);
8308
+ outline.x = Math.min(outline.x, next.x);
8309
+ outline.y = Math.min(outline.y, next.y);
8310
+ outline.width = right - outline.x;
8311
+ outline.height = bottom - outline.y;
8312
+ }
8313
+ }
8314
+ }
8315
+ }
8316
+ return { width: line.width, y: index22 * fit.lineHeight, baseline: size + index22 * fit.lineHeight, height: fit.lineHeight, outline };
8317
+ });
8318
+ const natural = outlines ? placeTextLines(ink, { x, y, width: zoneWidth, height: Number.MAX_VALUE }, zone, padding) : void 0;
8319
+ const partHeight = natural?.height ?? fit.sourceLines.length * fit.lineHeight;
8320
+ if (!Number.isFinite(partHeight)) throw new RangeError("Furniture exceeds finite layout coordinates.");
8321
+ const box = { x, y, width: zoneWidth, height: Math.max(scale, partHeight) }, placement = outlines ? placeTextLines(ink, box, zone, padding) : void 0;
8322
+ const accepted = { ...fit, ...placement ? { placement } : {}, overflow: fit.overflow || !!placement?.overflow };
8323
+ zoneParts.push({ type: "text", kind: kind2, zone, field, path: partPath, sourcePath: sourcePath ?? (!generated ? partPath : void 0), generated, text, style, requestedFontSize: 13 * scale, minFontSize: minimum, box, alignment: zone, fit: accepted });
8324
+ if (accepted.overflow) error(partPath, "Repeated text exceeds its zone at the selected readability floor; change the furniture or slide design.");
8325
+ y += box.height;
8326
+ };
8327
+ if (content.image !== void 0) {
8328
+ const box = { x, y, width: zoneWidth, height: Math.max(32 * scale, Math.min(height * 0.05, 72 * scale)) };
8329
+ zoneParts.push({ type: "image", kind: kind2, zone, field: "image", path: `${path3}.image`, sourcePath: `${path3}.image`, generated: false, image: content.image, box, alignment: zone });
8330
+ y += box.height;
8331
+ }
8332
+ add("text", content.text);
8333
+ if (content.organization === true) {
8334
+ if (typeof organization.name === "string") add("organization", organization.name, true, organizationPath);
8335
+ else error(`${path3}.organization`, "Generated organization name needs a named organization in the presentation.", "unresolved-content");
8336
+ }
8337
+ if (content.section === true) {
8338
+ if (typeof slide.section === "string") add("section", slide.section, true, `${sourceRoot}.section`);
8339
+ else error(`${path3}.section`, "Generated section needs a literal slide section.", "unresolved-content");
8340
+ }
8341
+ if (content.slideNumber === true) add("slideNumber", String(number), true);
8342
+ if (content.date === true) error(`${path3}.date`, "Use a literal date string for deterministic header/footer content.", "unresolved-content");
8343
+ else if (typeof content.date === "string") add("date", content.date);
8344
+ zones.push(zoneParts);
8345
+ }
8346
+ const tallest = Math.max(0, ...zones.map((zone) => zone.reduce((sum, part) => sum + part.box.height, 0)));
8347
+ if (!tallest) continue;
8348
+ const top = kind2 === "header" ? height * 0.025 : Math.max(height * 0.025, height - height * 0.04 - tallest);
8349
+ if (kind2 === "header") headerBottom = top + tallest;
8350
+ else footerTop = top;
8351
+ for (const zone of zones) for (const part of zone) {
8352
+ part.box.y += top;
8353
+ if (part.type === "text" && part.fit.placement) for (const line of part.fit.placement.lines) {
8354
+ line.y += top;
8355
+ line.baseline += top;
8356
+ if (line.outline) line.outline.y += top;
8357
+ }
8358
+ if (part.box.y + part.box.height > height - height * 0.04 + 0.01) error(part.path, "Repeated header/footer content extends beyond the usable slide height. Change its content or design before pagination.");
8359
+ parts2.push(part);
8360
+ }
8361
+ }
8362
+ if (headerBottom > footerTop + 0.01) error(parts2.find((part) => part.kind === "footer")?.path ?? sourceRoot, "Header and footer content overlap; repeated content cannot be repaired by splitting body content.");
8363
+ return { algorithm: "furniture-flow-v2", configured, textMeasurement: options.textMeasurement ? "provided" : "estimated", textOutlines: outlines ? "provided" : "unavailable", parts: parts2, headerBottom, footerTop, diagnostics, overflow: diagnostics.length > 0 };
8364
+ }
8268
8365
  var textSegments = new Intl.Segmenter("und", { granularity: "grapheme" });
8269
8366
  function measureText(text, fontSize) {
8270
8367
  let units = 0;
@@ -9192,7 +9289,11 @@ function composeSlide(input, options = {}) {
9192
9289
  const fitContent = (field, value, text, box, size, minimum, path22) => field === "text" ? fitPlacedText(field, value, text, box, size, minimum, path22) : field === "items" || field === "bullets" ? fitList(value, box, size, minimum, { style: styleFor(field, path22), textMeasurement: options.textMeasurement }) : fitText(text, box, size, minimum, widthFor(field, path22));
9193
9290
  const path3 = `slides.${options.slideIndex ?? 0}`;
9194
9291
  const items = [], diagnostics = [];
9195
- let y = padding;
9292
+ const measuredFurniture = layoutFurniture(slide, options);
9293
+ const furniture = measuredFurniture.configured || measuredFurniture.diagnostics.length ? measuredFurniture : void 0;
9294
+ if (furniture) diagnostics.push(...furniture.diagnostics);
9295
+ const bodyBottom = Math.min(height - padding, furniture && furniture.footerTop < height ? furniture.footerTop - gap * 0.5 : height - padding);
9296
+ let y = Math.max(padding, furniture?.headerBottom ? furniture.headerBottom + gap * 0.5 : padding);
9196
9297
  for (const field of ["tag", "title", "subtitle"]) {
9197
9298
  if (!slide[field]) continue;
9198
9299
  const requested = (field === "title" ? 54 : field === "tag" ? 16 : 25) * scale;
@@ -9200,11 +9301,12 @@ function composeSlide(input, options = {}) {
9200
9301
  const box = { x: padding, y, width: width - padding * 2, height: maxHeight };
9201
9302
  const text = fitPlacedText(field, slide[field], String(slide[field]), box, requested, minSize, `${path3}.${field}`);
9202
9303
  box.height = Math.min(maxHeight, Math.max(text.lines.length * text.lineHeight, text.placement?.height ?? 0));
9304
+ if (furniture && box.y + box.height > bodyBottom + 0.01) diagnostics.push({ code: "text-overflow", path: `${path3}.${field}`, message: "Repeated furniture leaves too little room for this heading. Change the header/footer or slide design." });
9203
9305
  items.push({ path: `${path3}.${field}`, field, type: "text", value: slide[field], payload: { text: slide[field] }, box, text, textStyle: styleFor(field, `${path3}.${field}`), composition });
9204
9306
  y += box.height + gap * 0.5;
9205
9307
  }
9206
9308
  if (items.length) y += gap * 0.5;
9207
- const contentBox = { x: padding, y, width: width - padding * 2, height: Math.max(scale, height - padding - y) };
9309
+ const contentBox = { x: padding, y, width: width - padding * 2, height: Math.max(scale, bodyBottom - y) };
9208
9310
  const collect = (host, basePath, depth = 0, ancestors = []) => {
9209
9311
  if (Array.isArray(host.blocks)) {
9210
9312
  if (depth >= MAX_COMPOSITION_DEPTH || ancestors.includes(host)) throw new RangeError(`Content groups must be acyclic and nest at most ${MAX_COMPOSITION_DEPTH} levels.`);
@@ -9399,6 +9501,7 @@ function composeSlide(input, options = {}) {
9399
9501
  for (const group of groups) for (const box of [group.box, group.contentBox]) for (const key of ["x", "y", "width", "height"]) box[key] = round(box[key]);
9400
9502
  const strictPaths = new Set(items.filter((item) => item.composition.overflow === "error").map((item) => item.path));
9401
9503
  const failures = diagnostics.filter((diagnostic) => {
9504
+ if (composition.overflow === "error") return true;
9402
9505
  let path22 = diagnostic.path;
9403
9506
  while (path22) {
9404
9507
  if (strictPaths.has(path22)) return true;
@@ -9409,7 +9512,7 @@ function composeSlide(input, options = {}) {
9409
9512
  return false;
9410
9513
  });
9411
9514
  const explanation = decisions ? {
9412
- algorithm: "grid-score-v8",
9515
+ algorithm: "grid-score-v9",
9413
9516
  textMeasurement: options.textMeasurement ? "provided" : "estimated",
9414
9517
  textOutlines: options.textMeasurement?.outlineBounds ? "provided" : "unavailable",
9415
9518
  textRasterPadding: rasterPadding,
@@ -9417,7 +9520,7 @@ function composeSlide(input, options = {}) {
9417
9520
  unmeasuredPayloads: items.filter((item) => !headings.has(item.field) && !item.quoteLayout && !item.codeLayout && !item.metricLayout && !item.timelineLayout && !["text", "items", "bullets", "table"].includes(item.field)).map((item) => item.path)
9418
9521
  } : void 0;
9419
9522
  if (failures.length) throw new OPFCompositionError(failures, explanation);
9420
- return { width, height, contentBox, items, groups, flows, diagnostics, composition, ...explanation ? { explanation } : {} };
9523
+ return { width, height, contentBox, items, groups, flows, diagnostics, composition, ...furniture ? { furniture } : {}, ...explanation ? { explanation } : {} };
9421
9524
  }
9422
9525
  function resolveCanvasDimensions(input) {
9423
9526
  const presets = {
@@ -9437,7 +9540,7 @@ function resolveCanvasDimensions(input) {
9437
9540
  return { width, height };
9438
9541
  }
9439
9542
 
9440
- // ../javascript/dist/chunk-GQSK3T7X.js
9543
+ // ../javascript/dist/chunk-D3GQIREP.js
9441
9544
  init_define_OPF_SKILLS();
9442
9545
  var presentation = {
9443
9546
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -14313,9 +14416,15 @@ var layout = {
14313
14416
  "List",
14314
14417
  "Image",
14315
14418
  "Number",
14316
- "Chart"
14419
+ "Metric",
14420
+ "Chart",
14421
+ "Table",
14422
+ "Code",
14423
+ "Video",
14424
+ "Quote",
14425
+ "Timeline"
14317
14426
  ],
14318
- "description": "Primary kind of content the layout holds. Drives pickers and AI placement decisions."
14427
+ "description": "Primary kind of content the layout holds. Drives pickers and AI placement decisions. Metric is the canonical numeric/KPI category; Number remains an accepted legacy label."
14319
14428
  },
14320
14429
  "contentMultiple": {
14321
14430
  "type": "string",
@@ -14523,6 +14632,9 @@ var layout = {
14523
14632
  "subtitle",
14524
14633
  "tag",
14525
14634
  "text",
14635
+ "metric",
14636
+ "quote",
14637
+ "timeline",
14526
14638
  "list",
14527
14639
  "chart",
14528
14640
  "picture",
@@ -14531,7 +14643,7 @@ var layout = {
14531
14643
  "diagram",
14532
14644
  "code"
14533
14645
  ],
14534
- "description": "OPF placeholder kind. 'text' and 'list' are flexible textual content regions. The named kinds describe a specific content role used by pickers, AI generation, and engine defaulting."
14646
+ "description": "OPF placeholder kind. 'text' and 'list' are flexible textual content regions. 'metric' is a numeric/KPI content region filled by a metric payload, including its optional label, description, unit, delta, and trend. The named kinds describe a specific content role used by pickers, AI generation, and engine defaulting. 'picture' and legacy 'diagram' use image payloads; 'media' uses video. Quote and timeline use their corresponding payload fields."
14535
14647
  }
14536
14648
  }
14537
14649
  },
@@ -15311,7 +15423,7 @@ var narrative = {
15311
15423
  "quote",
15312
15424
  "timeline"
15313
15425
  ],
15314
- "description": "Default content kind for the beat's slide. Mirrors ContentPayload.type and helps engines choose a sensible layout when only the beat is specified."
15426
+ "description": "Default content kind for the beat's slide. Uses ContentPayload.type names to help engines choose a layout. The legacy shape value is retained for compatibility and requests an image representation; it is not a native ContentPayload type."
15315
15427
  },
15316
15428
  "layoutHint": {
15317
15429
  "type": "string",
@@ -16113,7 +16225,7 @@ var schemaEntries = [
16113
16225
  { name: "fontScheme", file: "schemas/font-scheme.schema.json", schema: fontScheme }
16114
16226
  ];
16115
16227
 
16116
- // ../javascript/dist/chunk-TWMRZ43O.js
16228
+ // ../javascript/dist/chunk-TU7I3KSB.js
16117
16229
  init_define_OPF_SKILLS();
16118
16230
  var audiences = [
16119
16231
  {
@@ -17293,7 +17405,7 @@ var layouts = [
17293
17405
  "type": "title"
17294
17406
  },
17295
17407
  {
17296
- "type": "text"
17408
+ "type": "metric"
17297
17409
  }
17298
17410
  ]
17299
17411
  },
@@ -17306,10 +17418,10 @@ var layouts = [
17306
17418
  "type": "title"
17307
17419
  },
17308
17420
  {
17309
- "type": "text"
17421
+ "type": "metric"
17310
17422
  },
17311
17423
  {
17312
- "type": "text"
17424
+ "type": "metric"
17313
17425
  }
17314
17426
  ],
17315
17427
  "composition": {
@@ -17325,13 +17437,13 @@ var layouts = [
17325
17437
  "type": "title"
17326
17438
  },
17327
17439
  {
17328
- "type": "text"
17440
+ "type": "metric"
17329
17441
  },
17330
17442
  {
17331
- "type": "text"
17443
+ "type": "metric"
17332
17444
  },
17333
17445
  {
17334
- "type": "text"
17446
+ "type": "metric"
17335
17447
  }
17336
17448
  ],
17337
17449
  "composition": {
@@ -17347,16 +17459,16 @@ var layouts = [
17347
17459
  "type": "title"
17348
17460
  },
17349
17461
  {
17350
- "type": "text"
17462
+ "type": "metric"
17351
17463
  },
17352
17464
  {
17353
- "type": "text"
17465
+ "type": "metric"
17354
17466
  },
17355
17467
  {
17356
- "type": "text"
17468
+ "type": "metric"
17357
17469
  },
17358
17470
  {
17359
- "type": "text"
17471
+ "type": "metric"
17360
17472
  }
17361
17473
  ],
17362
17474
  "composition": {
@@ -17373,19 +17485,19 @@ var layouts = [
17373
17485
  "type": "title"
17374
17486
  },
17375
17487
  {
17376
- "type": "text"
17488
+ "type": "metric"
17377
17489
  },
17378
17490
  {
17379
- "type": "text"
17491
+ "type": "metric"
17380
17492
  },
17381
17493
  {
17382
- "type": "text"
17494
+ "type": "metric"
17383
17495
  },
17384
17496
  {
17385
- "type": "text"
17497
+ "type": "metric"
17386
17498
  },
17387
17499
  {
17388
- "type": "text"
17500
+ "type": "metric"
17389
17501
  }
17390
17502
  ],
17391
17503
  "composition": {
@@ -17402,22 +17514,22 @@ var layouts = [
17402
17514
  "type": "title"
17403
17515
  },
17404
17516
  {
17405
- "type": "text"
17517
+ "type": "metric"
17406
17518
  },
17407
17519
  {
17408
- "type": "text"
17520
+ "type": "metric"
17409
17521
  },
17410
17522
  {
17411
- "type": "text"
17523
+ "type": "metric"
17412
17524
  },
17413
17525
  {
17414
- "type": "text"
17526
+ "type": "metric"
17415
17527
  },
17416
17528
  {
17417
- "type": "text"
17529
+ "type": "metric"
17418
17530
  },
17419
17531
  {
17420
- "type": "text"
17532
+ "type": "metric"
17421
17533
  }
17422
17534
  ],
17423
17535
  "composition": {
@@ -17425,6 +17537,19 @@ var layouts = [
17425
17537
  "columns": 3
17426
17538
  }
17427
17539
  },
17540
+ {
17541
+ "$schema": "https://openpresentation.org/schema/opf-layout/v1",
17542
+ "id": "quote-1x",
17543
+ "name": "Quote 1x",
17544
+ "placeholders": [
17545
+ {
17546
+ "type": "title"
17547
+ },
17548
+ {
17549
+ "type": "quote"
17550
+ }
17551
+ ]
17552
+ },
17428
17553
  {
17429
17554
  "$schema": "https://openpresentation.org/schema/opf-layout/v1",
17430
17555
  "id": "table-1x",
@@ -17498,6 +17623,19 @@ var layouts = [
17498
17623
  "mode": "row"
17499
17624
  }
17500
17625
  },
17626
+ {
17627
+ "$schema": "https://openpresentation.org/schema/opf-layout/v1",
17628
+ "id": "timeline-1x",
17629
+ "name": "Timeline 1x",
17630
+ "placeholders": [
17631
+ {
17632
+ "type": "title"
17633
+ },
17634
+ {
17635
+ "type": "timeline"
17636
+ }
17637
+ ]
17638
+ },
17501
17639
  {
17502
17640
  "$schema": "https://openpresentation.org/schema/opf-layout/v1",
17503
17641
  "id": "title",
@@ -31678,6 +31816,11 @@ var catalogIndexes = {
31678
31816
  "name": "Number 6x",
31679
31817
  "file": "number-6x.json"
31680
31818
  },
31819
+ {
31820
+ "id": "quote-1x",
31821
+ "name": "Quote 1x",
31822
+ "file": "quote-1x.json"
31823
+ },
31681
31824
  {
31682
31825
  "id": "table-1x",
31683
31826
  "name": "Table 1x",
@@ -31698,6 +31841,11 @@ var catalogIndexes = {
31698
31841
  "name": "Text 3x",
31699
31842
  "file": "text-3x.json"
31700
31843
  },
31844
+ {
31845
+ "id": "timeline-1x",
31846
+ "name": "Timeline 1x",
31847
+ "file": "timeline-1x.json"
31848
+ },
31701
31849
  {
31702
31850
  "id": "title",
31703
31851
  "name": "Title",
@@ -34347,10 +34495,12 @@ var catalogEntries = [
34347
34495
  "number-4x.json",
34348
34496
  "number-5x.json",
34349
34497
  "number-6x.json",
34498
+ "quote-1x.json",
34350
34499
  "table-1x.json",
34351
34500
  "text-1x.json",
34352
34501
  "text-2x.json",
34353
34502
  "text-3x.json",
34503
+ "timeline-1x.json",
34354
34504
  "title.json",
34355
34505
  "title-subtitle.json"
34356
34506
  ], records: layouts, index: catalogIndexes.layouts },
@@ -34689,7 +34839,7 @@ var catalogEntries = [
34689
34839
  ], records: fontSchemes, index: catalogIndexes.fontSchemes }
34690
34840
  ];
34691
34841
 
34692
- // ../javascript/dist/chunk-GCB6LGJM.js
34842
+ // ../javascript/dist/chunk-ZIL7MGZU.js
34693
34843
  var import__ = __toESM(require__(), 1);
34694
34844
  var import_ajv_formats = __toESM(require_dist(), 1);
34695
34845
  var catalogIds = {
@@ -34754,10 +34904,12 @@ var catalogIds = {
34754
34904
  "number-4x",
34755
34905
  "number-5x",
34756
34906
  "number-6x",
34907
+ "quote-1x",
34757
34908
  "table-1x",
34758
34909
  "text-1x",
34759
34910
  "text-2x",
34760
34911
  "text-3x",
34912
+ "timeline-1x",
34761
34913
  "title",
34762
34914
  "title-subtitle"
34763
34915
  ],
@@ -36695,7 +36847,7 @@ function printParseErrorCode(code) {
36695
36847
  return "<unknown ParseErrorCode>";
36696
36848
  }
36697
36849
 
36698
- // ../javascript/dist/chunk-NPOKUFEX.js
36850
+ // ../javascript/dist/chunk-EWJNRHXA.js
36699
36851
  var own = (value, key) => Object.hasOwn(value, key);
36700
36852
  var object = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
36701
36853
  var primitive = (value) => value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value);
@@ -37430,7 +37582,7 @@ function createDataContent(input, options) {
37430
37582
  return { chart: { type: options.chartType ?? "column", data: { columns: names, rows: rows2 } } };
37431
37583
  }
37432
37584
 
37433
- // ../javascript/dist/chunk-TK3QHM3U.js
37585
+ // ../javascript/dist/chunk-FHGJX5QK.js
37434
37586
  init_define_OPF_SKILLS();
37435
37587
  var OPFPaginationError = class extends Error {
37436
37588
  constructor(message, diagnostics = []) {
@@ -37512,14 +37664,23 @@ function paginateSlide(input, options = {}) {
37512
37664
  };
37513
37665
  source = withReadability(source);
37514
37666
  let evaluations = 0;
37515
- const geometry = (slide) => {
37667
+ const geometry = (slide, pageIndex = 0) => {
37516
37668
  if (++evaluations > 2e4) throw new OPFPaginationError("Pagination exceeded its layout evaluation limit. Split the input into smaller sections.");
37517
- return composeSlide(withReadability(slide, true), options);
37669
+ return composeSlide(withReadability(slide, true), { ...options, slideNumber: (options.slideNumber ?? sourceIndex + 1) + pageIndex });
37518
37670
  };
37519
37671
  const initial = geometry(source);
37520
- if (!initial.diagnostics.length) return { slides: [source], pages: [{ slideIndex: sourceIndex, mappings: initial.items.map((item) => ({ sourcePath: item.path, outputPath: item.path })) }] };
37521
- const headerIssues = initial.diagnostics.filter((issue) => headingFields.has(issue.path.slice(sourceBase.length + 1)));
37522
- if (headerIssues.length) throw new OPFPaginationError("The repeated heading does not fit. Shorten it or change the slide design before pagination.", headerIssues);
37672
+ const repeatedMappings = (pageIndex) => {
37673
+ if (!initial.furniture) return [];
37674
+ const paths = new Set(initial.items.filter((item) => headingFields.has(item.field)).map((item) => item.path));
37675
+ for (const part of initial.furniture?.parts ?? []) {
37676
+ paths.add(part.path);
37677
+ if (part.sourcePath) paths.add(part.sourcePath);
37678
+ }
37679
+ return [...paths].map((sourcePath) => ({ sourcePath, outputPath: sourcePath.startsWith(`${sourceBase}.`) ? `slides.${sourceIndex + pageIndex}${sourcePath.slice(sourceBase.length)}` : sourcePath }));
37680
+ };
37681
+ if (!initial.diagnostics.length) return { slides: [source], pages: [{ slideIndex: sourceIndex, mappings: initial.items.map((item) => ({ sourcePath: item.path, outputPath: item.path })), ...initial.furniture ? { repeatedMappings: repeatedMappings(0) } : {} }] };
37682
+ const headerIssues = initial.diagnostics.filter((issue) => headingFields.has(issue.path.slice(sourceBase.length + 1)) || initial.furniture?.diagnostics.includes(issue));
37683
+ if (headerIssues.length) throw new OPFPaginationError("Repeated headings or header/footer content cannot fit or resolve. Change the repeated content or slide design before pagination.", headerIssues);
37523
37684
  const leaves = initial.items.filter((item) => !headingFields.has(item.field)).map((item) => leafFor(item.path, item.field, item.value));
37524
37685
  const leafPaths = new Set(leaves.map((leaf) => leaf.path));
37525
37686
  const slides = [], pages = [];
@@ -37564,11 +37725,13 @@ function paginateSlide(input, options = {}) {
37564
37725
  if (pageIndex > 0) delete slide.notes;
37565
37726
  return { slide, mappings };
37566
37727
  };
37567
- const diagnosticsFor = (portions) => geometry(project(portions, slides.length).slide).diagnostics;
37728
+ const diagnosticsFor = (portions) => geometry(project(portions, slides.length).slide, slides.length).diagnostics;
37568
37729
  const finish = () => {
37569
37730
  if (!selected.size) return;
37570
37731
  if (slides.length >= maxSlides) throw new OPFPaginationError(`Pagination needs more than ${maxSlides} slides. No partial result was returned.`);
37571
37732
  const { slide, mappings } = project(selected, slides.length);
37733
+ const issues = geometry(slide, slides.length).diagnostics;
37734
+ if (issues.length) throw new OPFPaginationError("A continuation page does not fit at its final page number. No partial result was returned.", issues);
37572
37735
  if (slides.length && typeof source.id === "string") {
37573
37736
  let suffix = slides.length + 1, id = `${source.id}--${suffix}`;
37574
37737
  while (reservedIds.has(id)) id = `${source.id}--${++suffix}`;
@@ -37577,7 +37740,7 @@ function paginateSlide(input, options = {}) {
37577
37740
  }
37578
37741
  assertValidPresentation({ slides: [slide] });
37579
37742
  slides.push(slide);
37580
- pages.push({ slideIndex: sourceIndex + slides.length - 1, mappings });
37743
+ pages.push({ slideIndex: sourceIndex + slides.length - 1, mappings, ...initial.furniture ? { repeatedMappings: repeatedMappings(slides.length - 1) } : {} });
37581
37744
  selected = /* @__PURE__ */ new Map();
37582
37745
  };
37583
37746
  for (const leaf of leaves) {
@@ -37647,10 +37810,11 @@ function paginatePresentation(input, options = {}) {
37647
37810
  const fontReference = design.fontScheme ?? theme2.fontScheme ?? "roboto";
37648
37811
  const fontScheme2 = typeof fontReference === "string" ? resolve2("fontSchemes", fontReference) : { ...resolve2("fontSchemes", fontReference.id), ...fontReference };
37649
37812
  const fonts = resolveFontFamilies(fontScheme2);
37650
- const result = paginateSlide(slide, { ...resolveCanvasDimensions(design.dimensions ?? theme2.dimensions), layout: layout2, fonts, contentAlignment: design.contentAlignment, titleAlignment: design.titleAlignment, contentBox: design.contentBox, textMeasurement: options.textMeasurement, textRasterPadding: options.textRasterPadding, ...overrides, slideIndex: index2, maxSlides: maxSlides - output.length, minFontSize: options.minFontSize, reservedIds });
37813
+ const result = paginateSlide(slide, { ...resolveCanvasDimensions(design.dimensions ?? theme2.dimensions), layout: layout2, fonts, contentAlignment: design.contentAlignment, titleAlignment: design.titleAlignment, contentBox: design.contentBox, textMeasurement: options.textMeasurement, textRasterPadding: options.textRasterPadding, ...overrides, presentation: presentation2, slideIndex: index2, slideNumber: output.length + 1, maxSlides: maxSlides - output.length, minFontSize: options.minFontSize, reservedIds });
37651
37814
  const outputStart = output.length;
37652
37815
  result.pages.forEach((page, pageIndex) => {
37653
- pages.push({ sourceSlideIndex: index2, slideIndex: outputStart + pageIndex, mappings: page.mappings.map((mapping) => ({ ...mapping, outputPath: mapping.outputPath.replace(/^slides\.\d+/, `slides.${outputStart + pageIndex}`) })) });
37816
+ const remap = (mapping) => ({ ...mapping, outputPath: mapping.outputPath.replace(/^slides\.\d+/, `slides.${outputStart + pageIndex}`) });
37817
+ pages.push({ sourceSlideIndex: index2, slideIndex: outputStart + pageIndex, mappings: page.mappings.map(remap), ...page.repeatedMappings ? { repeatedMappings: page.repeatedMappings.map(remap) } : {} });
37654
37818
  });
37655
37819
  output.push(...result.slides);
37656
37820
  reservedIds.push(...result.slides.map((slide2) => slide2.id).filter(Boolean));
@@ -38157,7 +38321,7 @@ async function main(argv) {
38157
38321
  return;
38158
38322
  }
38159
38323
  if (argv.length === 1 && argv[0] === "--version") {
38160
- print({ cli: "0.8.0", opf: "0.10.0" });
38324
+ print({ cli: "0.8.1", opf: "0.10.1" });
38161
38325
  return;
38162
38326
  }
38163
38327
  const [command, ...args] = argv;
@@ -38168,7 +38332,7 @@ async function main(argv) {
38168
38332
  if (command === "skills") {
38169
38333
  const { positional, options } = parse2(args, ["agent", "global", "directory"]);
38170
38334
  arity(positional, 1);
38171
- print(await manageSkills(positional[0], define_OPF_SKILLS_default, "0.8.0", { agent: options.agent, global: !!options.global, directory: options.directory }));
38335
+ print(await manageSkills(positional[0], define_OPF_SKILLS_default, "0.8.1", { agent: options.agent, global: !!options.global, directory: options.directory }));
38172
38336
  return;
38173
38337
  }
38174
38338
  if (command === "create") {
@@ -38203,7 +38367,7 @@ async function main(argv) {
38203
38367
  print({
38204
38368
  ...result,
38205
38369
  sha256: hash(raw),
38206
- opfVersion: "0.10.0",
38370
+ opfVersion: "0.10.1",
38207
38371
  ...config ? { context: { file: path2.resolve(String(options.config)), sha256: hash(config.raw) } } : {}
38208
38372
  });
38209
38373
  if (!result.valid || options.strict && result.counts.warning) process.exitCode = 1;