@openpresentation/opf 0.16.0 → 0.18.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.
Files changed (63) hide show
  1. package/README.md +16 -2
  2. package/dist/browser.js +38 -0
  3. package/dist/{catalog-refs-_anZs-Qz.d.ts → catalog-refs-BSfGELpt.d.ts} +1 -1
  4. package/dist/{catalog-schemas-BZCjgAxu.d.ts → catalog-schemas-CinPh5WA.d.ts} +1 -1
  5. package/dist/catalog.d.ts +2 -2
  6. package/dist/catalog.js +3 -23712
  7. package/dist/{chunk-BSYQDWT4.js → chunk-64YSJZDH.js} +28 -15
  8. package/dist/{chunk-WEDGVC5W.js → chunk-6WW2EDUW.js} +108 -108
  9. package/dist/{chunk-5UEUAW57.js → chunk-CJPDTLGD.js} +1 -1
  10. package/dist/{chunk-FQSIIADJ.js → chunk-DBYZI75U.js} +30 -5
  11. package/dist/{chunk-PX5AWL7Y.js → chunk-JT3QXA22.js} +99 -29
  12. package/dist/{chunk-6OR326EA.js → chunk-JXVS7BJK.js} +1 -1
  13. package/dist/chunk-KXBZ6ZSB.js +991 -0
  14. package/dist/{chunk-5PDN7BN6.js → chunk-MBU42S5Y.js} +427 -167
  15. package/dist/{chunk-K4DQQIT4.js → chunk-NS3VYB57.js} +5 -5
  16. package/dist/chunk-QLFWWHRF.js +919 -0
  17. package/dist/{chunk-5TO6I3GB.js → chunk-RAKEVM52.js} +1 -1
  18. package/dist/{chunk-NAWQR7MN.js → chunk-VCGRMNY2.js} +1 -1
  19. package/dist/chunk-WCG3THTD.js +23712 -0
  20. package/dist/{chunk-UM24JFUE.js → chunk-YWXB4XAT.js} +2 -2
  21. package/dist/{chunk-3XDRQYWZ.js → chunk-YZXTXX2D.js} +1 -1
  22. package/dist/{chunk-SMLMI6IZ.js → chunk-ZCFSDSUX.js} +3 -3
  23. package/dist/{chunk-KINQFU6X.js → chunk-ZOHFLP3O.js} +19 -12
  24. package/dist/{composition-D4ADF5c-.d.ts → composition-C-OoqvAr.d.ts} +227 -167
  25. package/dist/composition.d.ts +2 -2
  26. package/dist/composition.js +1 -1
  27. package/dist/conversion-C5foedh6.d.ts +502 -0
  28. package/dist/conversion-KGDVJM75.js +21 -0
  29. package/dist/convert.d.ts +3 -3
  30. package/dist/convert.js +7 -7
  31. package/dist/data.d.ts +6 -6
  32. package/dist/data.js +2 -2
  33. package/dist/deck-report-wszX7uo8.d.ts +40 -0
  34. package/dist/deck.d.ts +21 -51
  35. package/dist/deck.js +10 -10
  36. package/dist/diff.js +5 -5
  37. package/dist/docs.js +33 -27
  38. package/dist/examples.d.ts +1 -1
  39. package/dist/examples.js +418 -451
  40. package/dist/format.js +2 -2
  41. package/dist/index.d.ts +179 -16
  42. package/dist/index.js +51 -796
  43. package/dist/markdown.d.ts +10 -6
  44. package/dist/markdown.js +7 -7
  45. package/dist/node-engine.d.ts +114 -0
  46. package/dist/node-engine.js +44 -0
  47. package/dist/{pagination-DzZPFheM.d.ts → pagination-BaUjDrTz.d.ts} +25 -8
  48. package/dist/pagination.d.ts +3 -3
  49. package/dist/pagination.js +4 -4
  50. package/dist/patch.js +4 -4
  51. package/dist/{presentation-COrFuj2g.d.ts → presentation-HondgJ3l.d.ts} +278 -454
  52. package/dist/repo-readme.js +1 -1
  53. package/dist/schemas.d.ts +4 -2
  54. package/dist/schemas.js +1 -1
  55. package/dist/spec/catalogs/manifest.json +1 -1
  56. package/dist/spec/schemas/opf.schema.json +74 -100
  57. package/dist/types.d.ts +2 -2
  58. package/dist/{validation-types-HxIgJfKx.d.ts → validation-types-PbGDrNUr.d.ts} +23 -7
  59. package/dist/validator.d.ts +6 -6
  60. package/dist/validator.js +3 -3
  61. package/dist/yaml.d.ts +4 -4
  62. package/dist/yaml.js +7 -7
  63. package/package.json +37 -2
@@ -1,7 +1,7 @@
1
- import { promotedRegionKeys, VARIABLE_KINDS, resolveChartData, chartPaletteForFill, imageBackground, tableGrid, timelineTextColor, visitContentPayloads, readingRows, visualReadingOrder, intrinsicImageSize, textWidthMeasurer, normalizeHexColor, resolveColorRef, resolveDesignRecords, resolveColorRoles, resolveFontFamilies, resolveCanvasDimensions, defaultSlideBackground, isRecord, hasContentVariables, isTemplate, instantiateForValidation, unusedDatasets, MAX_COMPOSITION_DEPTH, datasetDiagnostics, pathFor, collectCitations, numberingFindings, walkCitationRuns, resolveTableData, resolveChartOptions, chartOptionTarget, codeHighlightLines, chartNumberFixesByCell, MAX_PLACEHOLDER_GROUP_DEPTH, OPFCompositionError, composeSlide, resolveScriptFonts } from './chunk-5PDN7BN6.js';
1
+ import { promotedRegionKeys, VARIABLE_KINDS, resolveChartData, chartPaletteForFill, imageBackground, tableGrid, timelineTextColor, LOGO_SHAPES, visitContentPayloads, readingRows, visualReadingOrder, intrinsicImageSize, textWidthMeasurer, normalizeHexColor, resolveColorRef, resolveDesignRecords, resolveFontFamilies, resolveColorRoles, resolveCanvasDimensions, resolveSlideVariables, defaultSlideBackground, isRecord, hasContentVariables, isTemplate, instantiateForValidation, resolveScriptFonts, unusedDatasets, MAX_COMPOSITION_DEPTH, datasetDiagnostics, pathFor, collectCitations, numberingFindings, walkCitationRuns, resolveTableData, resolveChartOptions, chartOptionTarget, codeHighlightLines, chartNumberFixesByCell, MAX_PLACEHOLDER_GROUP_DEPTH, OPFCompositionError, composeSlide } from './chunk-MBU42S5Y.js';
2
2
  import { catalogSchemaNames } from './chunk-TRDXRRQK.js';
3
3
  import { resolveReference, checkCatalogsOption, provenanceOf, unresolvedReference, OPFUnresolvedReferenceError, catalogReferenceSites, parseReference, catalogGroupDeclared, pointerPath, catalogRecords, catalogKinds, catalogGroupSource, registeredCatalog } from './chunk-SPFV27O5.js';
4
- import { schemaEntries, schemas } from './chunk-WEDGVC5W.js';
4
+ import { schemaEntries, schemas } from './chunk-6WW2EDUW.js';
5
5
  import Ajv2020 from 'ajv/dist/2020.js';
6
6
  import addFormats from 'ajv-formats';
7
7
  import { parseTree, printParseErrorCode, getNodePath } from 'jsonc-parser';
@@ -1364,26 +1364,20 @@ var sourceOfAsset = (value) => {
1364
1364
  const source = typeof value === "string" ? value : rec(value).src;
1365
1365
  return typeof source === "string" ? source : void 0;
1366
1366
  };
1367
- var LOGO_VARIANTS = ["default", "light", "dark", "stacked", "stackedLight", "stackedDark", "icon", "iconLight", "iconDark", "wordmark", "wordmarkLight", "wordmarkDark"];
1367
+ var isLogoReference = (value) => typeof value === "string" && value.startsWith("var:organization.");
1368
1368
  function assetRefs(document, slide, slidePath, includeDeck) {
1369
1369
  const out = [];
1370
1370
  for (const payload of slidePayloads(slide, slidePath)) {
1371
1371
  const at2 = (...tail) => pointer2(...splitPointer(payload.path), ...tail);
1372
- if (payload.node.image !== void 0) out.push({ path: at2("image"), value: payload.node.image, kind: "image" });
1372
+ if (payload.node.image !== void 0 && !isLogoReference(payload.node.image)) out.push({ path: at2("image"), value: payload.node.image, kind: "image" });
1373
1373
  if (payload.node.video !== void 0) out.push({ path: at2("video"), value: payload.node.video, kind: "video" });
1374
1374
  if (rec(payload.node.quote).photo !== void 0) out.push({ path: at2("quote", "photo"), value: rec(payload.node.quote).photo, kind: "quote-photo" });
1375
1375
  }
1376
1376
  const designRefs = (design, base) => {
1377
- const logo = design.logo;
1378
- if (typeof logo === "string" || logo && typeof logo.src === "string") out.push({ path: `${base}/logo`, value: logo, kind: "logo" });
1379
- else if (logo && typeof logo === "object") {
1380
- for (const variant of LOGO_VARIANTS)
1381
- if (logo[variant] !== void 0) out.push({ path: `${base}/logo/${variant}`, value: logo[variant], kind: "logo" });
1382
- }
1383
1377
  for (const kind of ["header", "footer"])
1384
1378
  for (const zone of ["left", "center", "right"]) {
1385
1379
  const item = rec(rec(design[kind])[zone]);
1386
- if (item.image !== void 0) out.push({ path: `${base}/${kind}/${zone}/image`, value: item.image, kind: "furniture" });
1380
+ if (item.image !== void 0 && !isLogoReference(item.image)) out.push({ path: `${base}/${kind}/${zone}/image`, value: item.image, kind: "furniture" });
1387
1381
  }
1388
1382
  };
1389
1383
  designRefs(rec(slide.design), `${slidePath}/design`);
@@ -1391,12 +1385,19 @@ function assetRefs(document, slide, slidePath, includeDeck) {
1391
1385
  designRefs(rec(document.design), "/design");
1392
1386
  const organizations = Array.isArray(document.organization) ? document.organization : document.organization ? [document.organization] : [];
1393
1387
  organizations.forEach((organization, index) => {
1394
- if (organization?.logo !== void 0)
1395
- out.push({
1396
- path: Array.isArray(document.organization) ? `/organization/${index}/logo` : "/organization/logo",
1397
- value: organization.logo,
1398
- kind: "organization"
1399
- });
1388
+ const logo = organization?.logo;
1389
+ if (logo === void 0) return;
1390
+ const base = Array.isArray(document.organization) ? `/organization/${index}/logo` : "/organization/logo";
1391
+ if (typeof logo === "string" || logo && typeof logo === "object" && "src" in logo) {
1392
+ out.push({ path: base, value: logo, kind: "organization" });
1393
+ return;
1394
+ }
1395
+ for (const shape of LOGO_SHAPES) {
1396
+ const entry = rec(logo)[shape];
1397
+ if (entry === void 0) continue;
1398
+ if (typeof entry === "string" || entry && typeof entry === "object" && "src" in entry) out.push({ path: `${base}/${shape}`, value: entry, kind: "organization" });
1399
+ else for (const tone of ["onLight", "onDark"]) if (rec(entry)[tone] !== void 0) out.push({ path: `${base}/${shape}/${tone}`, value: rec(entry)[tone], kind: "organization" });
1400
+ }
1400
1401
  });
1401
1402
  const speakers = Array.isArray(document.speaker) ? document.speaker : document.speaker ? [document.speaker] : [];
1402
1403
  speakers.forEach((speaker, index) => {
@@ -1601,7 +1602,7 @@ var altRule = rule(
1601
1602
  'People using a screen reader get nothing for a picture without alternative text. A picture that is purely decorative should say so with an empty alt (alt: ""), which is an explicit, reviewed choice instead of an omission.',
1602
1603
  {
1603
1604
  standard: "WCAG 2.2 SC 1.1.1 Non-text Content, level A",
1604
- approximations: "Checks the alt field of images (image blocks, Slide.image and region images, placed or not), video, logos (design.logo and each LogoSet variant, organization.logo), header/footer images, quote photos and speaker photos, following asset: references to the assets registry. Whether the text describes the picture well is not judged here (see opf/poor-alt-text). Charts carry `chart.alt` and are checked by opf/chart-text-alternative. Picture backgrounds are decorative unless they carry their own alt, and watermarks are decorative, so neither is checked."
1605
+ approximations: "Checks the alt field of images (image blocks, Slide.image and region images, placed or not), video, organization logos (each shape and background), header/footer images (a logo reference such as var:organization.logo.icon is checked on the organization), quote photos and speaker photos, following asset: references to the assets registry. Whether the text describes the picture well is not judged here (see opf/poor-alt-text). Charts carry `chart.alt` and are checked by opf/chart-text-alternative. Picture backgrounds are decorative unless they carry their own alt, and watermarks are decorative, so neither is checked."
1605
1606
  }
1606
1607
  );
1607
1608
  var poorAltRule = rule(
@@ -1615,7 +1616,7 @@ var poorAltRule = rule(
1615
1616
  var GENERIC_ALT = /^(image|picture|photo|photograph|graphic|img|icon|figure|screenshot|untitled|alt|alt text|logo)$/i;
1616
1617
  var FILE_ALT = /(\.(png|jpe?g|gif|svg|webp|bmp|tiff?|heic|avif)$)|^(img|dsc|image|screenshot|screen shot|photo|pic)[ _-]?\d+/i;
1617
1618
  var GENERIC_CHART_ALT = /^((a|an|the)\s+)?([a-z-]+\s+){0,2}(chart|graph|plot|diagram|figure)$/i;
1618
- var kindLabel = (kind) => ({ chart: "Chart", image: "Image", video: "Video", logo: "Logo", furniture: "Header/footer image", speaker: "Speaker photo", "quote-photo": "Quote photo", organization: "Organization logo" })[kind] ?? "Picture";
1619
+ var kindLabel = (kind) => ({ chart: "Chart", image: "Image", video: "Video", furniture: "Header/footer image", speaker: "Speaker photo", "quote-photo": "Quote photo", organization: "Organization logo" })[kind] ?? "Picture";
1619
1620
  function altFixes(path, value) {
1620
1621
  const decorative = typeof value === "string" ? { id: "mark-decorative", title: "Mark as decorative (empty alt)", kind: "patch", safe: false, patch: [{ op: "replace", path, value: { src: value, alt: "" } }] } : { id: "mark-decorative", title: "Mark as decorative (empty alt)", kind: "patch", safe: false, patch: [{ op: "add", path: `${path}/alt`, value: "" }] };
1621
1622
  return [{ id: "focus-alt", title: "Write alt text", kind: "focus", safe: true, focus: { path, field: "alt", value } }, decorative];
@@ -1634,12 +1635,12 @@ var altRules = [
1634
1635
  if (alt !== void 0 && alt.trim() !== "") continue;
1635
1636
  if (alt === "") continue;
1636
1637
  const hasText = alt !== void 0;
1637
- const organization = ref.kind === "organization" || ref.kind === "logo" ? rec(Array.isArray(context.document.organization) ? context.document.organization[0] : context.document.organization).name : void 0;
1638
+ const organization = ref.kind === "organization" ? rec(Array.isArray(context.document.organization) ? context.document.organization[0] : context.document.organization).name : void 0;
1638
1639
  context.report(altRule, {
1639
1640
  path: ref.path,
1640
1641
  slide: ref.path.startsWith("/slides/") ? slide : void 0,
1641
1642
  message: `${kindLabel(ref.kind)} has ${hasText ? "blank" : "no"} alt text.`,
1642
- help: `Describe what the ${ref.kind === "logo" || ref.kind === "organization" ? "logo shows" : "picture shows or why it is here"}${typeof organization === "string" ? ` (for a logo, the organization name, ${organization}, is usually right)` : ""}, or set alt to "" if it is purely decorative.`,
1643
+ help: `Describe what the ${ref.kind === "organization" ? "logo shows" : "picture shows or why it is here"}${typeof organization === "string" ? ` (for a logo, the organization name, ${organization}, is usually right)` : ""}, or set alt to "" if it is purely decorative.`,
1643
1644
  fixes: altFixes(ref.path, ref.value)
1644
1645
  });
1645
1646
  }
@@ -2421,7 +2422,7 @@ var formatRules = [
2421
2422
  rule("chart-mapping-unknown-column", "format", "error", "A chart mapping names a column the data does not have.", "The series cannot be built from a column that is not there.", { standard: SCHEMA }),
2422
2423
  rule("number-format-invalid", "format", "error", "A number format cannot be read.", "A format code that no engine can parse is drawn as the plain number or fails to export.", { standard: "Excel number format codes, as far as OPF supports them" }),
2423
2424
  rule("variable-invalid-value", "format", "error", "A variable value does not match its declared type.", "A number variable given text, or a date given a non-date, cannot be filled into the deck.", { standard: SCHEMA }),
2424
- rule("variable-unknown-builtin", "format", "error", "A token names a built-in variable that does not exist.", "The `deck.`, `speaker.` and `organization.` names (and `speakers`) are reserved for built-in variables; a name under them that is not a built-in can never be filled, so the token would show literally.", { standard: SCHEMA }),
2425
+ rule("variable-unknown-builtin", "format", "error", "A token names a built-in variable that does not exist.", "The `deck.`, `speaker.`, `organization.` and `slide.` names (and `speakers`) are reserved for built-in variables; a name under them that is not a built-in can never be filled, so the token would show literally. The slide-scoped `slide.number`, `slide.section` and `deck.slideCount` are inline tokens only, so `var:slide.*` and `var:deck.slideCount` are reported too; organization logos are whole-field references only (`var:organization.logo.icon`), so a `{{organization.logo}}` token, an unknown logo shape or an unknown organization id is reported.", { standard: SCHEMA }),
2425
2426
  rule("chart-highlight-unknown-name", "format", "error", "A chart highlight names a series or category the chart does not have.", "`chart.highlight` emphasises marks by name; a name that matches no series or category in the chart data highlights nothing, so the chart is not drawn as authored.", { standard: SCHEMA }),
2426
2427
  rule("variable-format", "format", "error", "A variable cannot be formatted.", "A number or date format that does not apply to the value leaves the token unreadable.", { standard: SCHEMA }),
2427
2428
  rule(
@@ -2505,7 +2506,7 @@ var dataRules = [
2505
2506
  rule("chart-highlight-adapted", "content", "warning", "A chart highlight is adapted by the chart type.", "A highlight the chart type cannot show as authored (a category highlight on a chart without categories, for example) is adapted by every engine, so the emphasis is not exactly what was written.", { standard: SCHEMA }),
2506
2507
  rule("code-highlight-out-of-range", "content", "warning", "A code highlight marks a line the code does not have.", "Marked lines count from 1 by line break in code.source; an entry past the last line marks nothing.", { standard: SCHEMA }),
2507
2508
  rule("code-highlight-range-reversed", "content", "warning", "A code highlight range ends before it starts.", "A range written end before start marks nothing; write the smaller line number first.", { standard: SCHEMA }),
2508
- rule("variable-builtin-missing", "content", "warning", "A built-in variable has no value in this document.", "A `{{deck.*}}`, `{{speaker.*}}` or `{{organization.*}}` token whose field the document does not set resolves to nothing, so the text shows a gap.", { standard: SCHEMA }),
2509
+ rule("variable-builtin-missing", "content", "warning", "A built-in variable has no value in this document.", "A `{{deck.*}}`, `{{speaker.*}}` or `{{organization.*}}` token whose field the document does not set resolves to nothing, so the text shows a gap; a `var:organization.logo` reference to an organization without a logo draws no image. `{{slide.section}}` is checked per slide: a slide without a `section` that uses it, in its own text or in the header or footer it inherits, is reported at that slide.", { standard: SCHEMA }),
2509
2510
  rule("duration-outside-narrative", "content", "warning", "The target duration is outside the range the narrative suits.", "A narrative records the talk lengths it suits. A deck whose duration is outside that range probably needs a different narrative or a different length; nothing is drawn or exported differently.", { standard: SCHEMA }),
2510
2511
  rule("narrative-duration-range", "content", "warning", "An inline narrative duration range has min greater than max.", "A range with its bounds swapped matches no duration, so the duration check cannot help.", { standard: "spec/schemas/narrative.schema.json" })
2511
2512
  ];
@@ -3245,6 +3246,67 @@ function parseSource(source) {
3245
3246
  };
3246
3247
  }
3247
3248
 
3249
+ // src/script-measurement.ts
3250
+ function scriptProfile(presentation, slideIndex, options, language) {
3251
+ let resolved;
3252
+ try {
3253
+ resolved = resolveScriptFonts(presentation, { slideIndex, ...options.catalogs !== void 0 ? { catalogs: options.catalogs } : {}, ...language === void 0 ? {} : { language } });
3254
+ } catch {
3255
+ resolved = void 0;
3256
+ }
3257
+ const slots = (role) => {
3258
+ const latin = options.fontFamilies[role];
3259
+ const slot = (key) => !resolved || resolved.sources[key] === "latin" || resolved.sources[key] === "schemeFamily" ? latin : resolved[role][key] ?? latin;
3260
+ return { latin, eastAsian: slot("eastAsian"), complexScript: slot("complexScript") };
3261
+ };
3262
+ return {
3263
+ heading: slots("heading"),
3264
+ body: slots("body"),
3265
+ ...resolved?.supplement ? { supplement: resolved.supplement } : {},
3266
+ script: resolved?.script ?? "Zzzz",
3267
+ ...resolved ? { scriptRole: resolved.scriptRole, bcp47: resolved.bcp47, lang: resolved.lang, languageSource: resolved.languageSource, direction: resolved.direction } : {},
3268
+ rtl: resolved?.rtl === true,
3269
+ serif: options.serif
3270
+ };
3271
+ }
3272
+ function slideScriptMeasurement(presentation, slideIndex, measurement, options) {
3273
+ const forScripts = measurement.forScripts;
3274
+ if (typeof forScripts !== "function") return measurement;
3275
+ const deckProfile = scriptProfile(presentation, slideIndex, options);
3276
+ const deck = forScripts.call(measurement, deckProfile);
3277
+ const languages = /* @__PURE__ */ new Map();
3278
+ const forLanguage = (lang) => {
3279
+ if (typeof lang !== "string" || !lang) return void 0;
3280
+ if (!languages.has(lang)) {
3281
+ let own2;
3282
+ try {
3283
+ const profile = scriptProfile(presentation, slideIndex, options, lang);
3284
+ own2 = profile.languageSource === "option" && profile.bcp47?.toLowerCase() !== deckProfile.bcp47?.toLowerCase() ? forScripts.call(measurement, profile) : void 0;
3285
+ } catch {
3286
+ own2 = void 0;
3287
+ }
3288
+ languages.set(lang, own2);
3289
+ }
3290
+ return languages.get(lang);
3291
+ };
3292
+ const pick = (style) => forLanguage(style?.lang) ?? deck;
3293
+ const scripted = { ...deck, measure: (text, size, style) => pick(style).measure(text, size, style) };
3294
+ if (typeof deck.resolveStyle === "function") scripted.resolveStyle = (style) => deck.resolveStyle.call(deck, style);
3295
+ if (typeof deck.outlineBounds === "function")
3296
+ scripted.outlineBounds = (text, size, style) => {
3297
+ const own2 = pick(style);
3298
+ return typeof own2.outlineBounds === "function" ? own2.outlineBounds(text, size, style) : deck.outlineBounds.call(deck, text, size, style);
3299
+ };
3300
+ return scripted;
3301
+ }
3302
+ function resolveSlideScriptMeasurement(presentation, slideIndex, measurement, options = {}) {
3303
+ if (typeof measurement.forScripts !== "function") return measurement;
3304
+ const { fontScheme } = resolveDesignRecords(presentation, slideIndex, options.catalogs !== void 0 ? { catalogs: options.catalogs } : {});
3305
+ const resolved = resolveFontFamilies(fontScheme);
3306
+ const fontFamilies = { heading: options.fontFamilies?.heading ?? resolved.heading, body: options.fontFamilies?.body ?? resolved.body };
3307
+ return slideScriptMeasurement(presentation, slideIndex, measurement, { ...options.catalogs !== void 0 ? { catalogs: options.catalogs } : {}, fontFamilies, serif: fontScheme.type === "serif" });
3308
+ }
3309
+
3248
3310
  // src/slide-context.ts
3249
3311
  var rec2 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
3250
3312
  function resolveSlideContext(presentation, index, options = {}) {
@@ -3280,7 +3342,8 @@ function resolveSlideContext(presentation, index, options = {}) {
3280
3342
  ...options.fonts?.textMeasurement ? { textMeasurement: options.fonts.textMeasurement } : {},
3281
3343
  ...options.date !== void 0 ? { date: options.date } : {}
3282
3344
  };
3283
- return { options: composeOptions, diagnostics, resolved: { theme, colorScheme, fontScheme, fontSchemePath: records.fontSchemePath, ...layout ? { layout } : {}, provenance: { ...layoutProvenance ? { layout: layoutProvenance } : {}, ...records.provenance } } };
3345
+ const resolvedSlide = resolveSlideVariables(slide, { slideNumber: composeOptions.slideNumber, slideCount: composeOptions.slideCount, presentation, darkBackground: composeOptions.darkBackground === true });
3346
+ return { slide: resolvedSlide, options: composeOptions, diagnostics, resolved: { theme, colorScheme, fontScheme, fontSchemePath: records.fontSchemePath, ...layout ? { layout } : {}, provenance: { ...layoutProvenance ? { layout: layoutProvenance } : {}, ...records.provenance } } };
3284
3347
  }
3285
3348
 
3286
3349
  // src/rule-slides.ts
@@ -3316,10 +3379,17 @@ function buildSlides(document, options) {
3316
3379
  const slides = Array.isArray(document.slides) ? document.slides : [];
3317
3380
  return slides.map((slide, index) => {
3318
3381
  const path = pointer2("slides", index);
3319
- const measurement = lazy(() => measurementFor(options, index));
3382
+ const baseContext = lazy(() => resolveSlideContext(document, index, { catalogs: options.catalogs, date: "2000-01-01" }));
3383
+ const measurement = lazy(() => {
3384
+ const host = measurementFor(options, index);
3385
+ if (!host) return void 0;
3386
+ const { resolved: resolved2 } = baseContext();
3387
+ return slideScriptMeasurement(document, index, host, { catalogs: options.catalogs, fontFamilies: resolveFontFamilies(resolved2.fontScheme), serif: resolved2.fontScheme.type === "serif" });
3388
+ });
3320
3389
  const resolved = lazy(() => {
3321
3390
  const textMeasurement = measurement();
3322
- return resolveSlideContext(document, index, { catalogs: options.catalogs, ...textMeasurement ? { fonts: { textMeasurement } } : {}, date: "2000-01-01" });
3391
+ const slideContext = baseContext();
3392
+ return textMeasurement ? { ...slideContext, options: { ...slideContext.options, textMeasurement } } : slideContext;
3323
3393
  });
3324
3394
  const design = lazy(() => resolveDesign(document, index, resolved()));
3325
3395
  const layout = lazy(() => resolved().options.layout);
@@ -3327,14 +3397,14 @@ function buildSlides(document, options) {
3327
3397
  const result = { layoutDiagnostics: [] };
3328
3398
  const compose = (input, withLayout) => composeSlide(input, { ...resolved().options, layout: withLayout });
3329
3399
  try {
3330
- result.composition = compose(slide, layout());
3400
+ result.composition = compose(resolved().slide, layout());
3331
3401
  result.layoutDiagnostics.push(...result.composition.diagnostics.map((diagnostic) => ({ diagnostic, strict: false })));
3332
3402
  } catch (error) {
3333
3403
  if (error instanceof OPFCompositionError) {
3334
3404
  result.layoutDiagnostics.push(...error.diagnostics.map((diagnostic) => ({ diagnostic, strict: true })));
3335
3405
  try {
3336
3406
  const relaxedLayout = layout();
3337
- result.composition = compose(relax(slide), relaxedLayout ? relax(relaxedLayout) : void 0);
3407
+ result.composition = compose(relax(resolved().slide), relaxedLayout ? relax(relaxedLayout) : void 0);
3338
3408
  } catch (second) {
3339
3409
  result.layoutError = second instanceof Error ? second.message : String(second);
3340
3410
  }
@@ -3640,4 +3710,4 @@ function assertValidCatalogRecord(kind, value) {
3640
3710
  if (!report2.valid) throw new OPFValidationError(report2);
3641
3711
  }
3642
3712
 
3643
- export { DEFAULT_CHART_PALETTE, DEFAULT_VALIDATION_THRESHOLDS, OPFValidationError, assertValid, assertValidCatalogRecord, findValidationRule, parseSource, resolveSlideContext, validate, validateCatalogRecord, validationCategories, validationRules };
3713
+ export { DEFAULT_CHART_PALETTE, DEFAULT_VALIDATION_THRESHOLDS, OPFValidationError, assertValid, assertValidCatalogRecord, findValidationRule, parseSource, resolveSlideContext, resolveSlideScriptMeasurement, validate, validateCatalogRecord, validationCategories, validationRules };
@@ -1,4 +1,4 @@
1
- import { presentation } from './chunk-WEDGVC5W.js';
1
+ import { presentation } from './chunk-6WW2EDUW.js';
2
2
 
3
3
  // src/format.ts
4
4
  var OPFFormatError = class extends Error {