@openpresentation/opf 0.16.0 → 0.17.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/README.md +16 -2
  2. package/dist/{catalog-refs-_anZs-Qz.d.ts → catalog-refs-C4K4y-vh.d.ts} +1 -1
  3. package/dist/{catalog-schemas-BZCjgAxu.d.ts → catalog-schemas-g7RFQBdc.d.ts} +1 -1
  4. package/dist/catalog.d.ts +2 -2
  5. package/dist/catalog.js +3 -23712
  6. package/dist/{chart-data-BnNqgnC-.d.ts → chart-data-DTxdRRT1.d.ts} +1 -1
  7. package/dist/{chunk-FQSIIADJ.js → chunk-BIC3SWPK.js} +4 -4
  8. package/dist/{chunk-5PDN7BN6.js → chunk-CW7GEAV3.js} +151 -49
  9. package/dist/{chunk-NAWQR7MN.js → chunk-ESRYBYLY.js} +1 -1
  10. package/dist/chunk-IPW5BS3X.js +973 -0
  11. package/dist/{chunk-5UEUAW57.js → chunk-IS5H5JKH.js} +1 -1
  12. package/dist/{chunk-UM24JFUE.js → chunk-M4UR3NPN.js} +2 -2
  13. package/dist/{chunk-KINQFU6X.js → chunk-N4EVOFEA.js} +19 -12
  14. package/dist/{chunk-PX5AWL7Y.js → chunk-NLNYNBTS.js} +79 -10
  15. package/dist/{chunk-SMLMI6IZ.js → chunk-O263APNI.js} +1 -1
  16. package/dist/{chunk-BSYQDWT4.js → chunk-O2CX5NEH.js} +26 -14
  17. package/dist/{chunk-3XDRQYWZ.js → chunk-O3CVNJTL.js} +1 -1
  18. package/dist/{chunk-5TO6I3GB.js → chunk-PPROJP2E.js} +1 -1
  19. package/dist/{chunk-WEDGVC5W.js → chunk-RA64UQKI.js} +18 -42
  20. package/dist/{chunk-K4DQQIT4.js → chunk-TCD2FB2K.js} +5 -5
  21. package/dist/chunk-WCG3THTD.js +23712 -0
  22. package/dist/chunk-WWYWFVOI.js +793 -0
  23. package/dist/{chunk-6OR326EA.js → chunk-YT7FMQER.js} +1 -1
  24. package/dist/{composition-D4ADF5c-.d.ts → composition-BbZ_9C-c.d.ts} +152 -132
  25. package/dist/composition.d.ts +3 -3
  26. package/dist/composition.js +1 -1
  27. package/dist/conversion-SBpTOwdg.d.ts +444 -0
  28. package/dist/convert.d.ts +4 -4
  29. package/dist/convert.js +7 -7
  30. package/dist/data.d.ts +2 -2
  31. package/dist/data.js +2 -2
  32. package/dist/deck-report-Bx3naFlF.d.ts +40 -0
  33. package/dist/deck.d.ts +23 -53
  34. package/dist/deck.js +10 -10
  35. package/dist/diff.d.ts +1 -1
  36. package/dist/diff.js +5 -5
  37. package/dist/docs.js +29 -23
  38. package/dist/examples.d.ts +1 -1
  39. package/dist/examples.js +237 -237
  40. package/dist/{finding-CT_f_vbD.d.ts → finding-CDQ_wH8j.d.ts} +1 -1
  41. package/dist/format.js +2 -2
  42. package/dist/index.d.ts +42 -12
  43. package/dist/index.js +15 -807
  44. package/dist/markdown.d.ts +6 -6
  45. package/dist/markdown.js +7 -7
  46. package/dist/node-engine.d.ts +94 -0
  47. package/dist/node-engine.js +21 -0
  48. package/dist/node.d.ts +60 -0
  49. package/dist/node.js +54 -0
  50. package/dist/{pagination-DzZPFheM.d.ts → pagination-BhX4M48Y.d.ts} +21 -7
  51. package/dist/pagination.d.ts +4 -4
  52. package/dist/pagination.js +4 -4
  53. package/dist/patch.d.ts +1 -1
  54. package/dist/patch.js +4 -4
  55. package/dist/{presentation-COrFuj2g.d.ts → presentation-fb8CZmRq.d.ts} +12 -75
  56. package/dist/repo-readme.js +1 -1
  57. package/dist/schemas.js +1 -1
  58. package/dist/spec/catalogs/manifest.json +1 -1
  59. package/dist/spec/schemas/opf.schema.json +16 -37
  60. package/dist/types.d.ts +3 -3
  61. package/dist/{validation-types-HxIgJfKx.d.ts → validation-types-iZbXfES6.d.ts} +19 -8
  62. package/dist/validator.d.ts +8 -8
  63. package/dist/validator.js +3 -3
  64. package/dist/yaml.d.ts +6 -6
  65. package/dist/yaml.js +7 -7
  66. package/package.json +34 -1
@@ -1,5 +1,5 @@
1
1
  // src/generated/repo-readme.ts
2
- var repoReadmeRaw = '# Open Presentation Format (OPF)\n\n[![npm version](https://img.shields.io/npm/v/@openpresentation/opf?label=npm)](https://www.npmjs.com/package/@openpresentation/opf)\n[![npm downloads](https://img.shields.io/npm/dw/@openpresentation/opf)](https://www.npmjs.com/package/@openpresentation/opf)\n[![license](https://img.shields.io/npm/l/@openpresentation/opf)](./LICENSE)\n\nPublic npm package: [`@openpresentation/opf`](https://www.npmjs.com/package/@openpresentation/opf) (`npm install @openpresentation/opf`).\n\nOpen Presentation Format is the portable, human-readable JSON document format for slide decks.\n\nThis repository is the canonical home for the OPF **spec**, **JSON Schemas**, **catalog presets**, examples, generated developer types, local validation tooling, and integration docs for the render/edit/convert toolkit. OpenPresentation publishes open-source code and documentation only; it does not provide hosted APIs, hosted rendering functions, queues, storage, authentication, jobs, previews, SLAs, telemetry, or managed infrastructure.\n\nFor AI agents, use the [OPF skill set](docs/agent-skills.md) for authoring, layout, presets, editing, export, and schema inspection.\n\nPublished CLI 0.15.0 installs all six skills into your project with `npx @openpresentation/cli@0.15.0 skills install`. It uses local copies, preserves existing instructions and refuses to overwrite customized skills. See the [installation and update guide](docs/agent-skills.md) for personal or agent-specific targets and source development.\n\nFor a fresh Node 24 project that installs **published** packages (not this\ncheckout), follow the [developer quickstart](docs/quickstart.md) and the\n[compatibility matrix](docs/compatibility-matrix.md).\n\nFor LLM authoring, start with [the authoring guide](docs/llm-authoring.md), [dynamic composition](docs/dynamic-composition.md), and [local ecosystem verification](docs/ecosystem-development.md).\n\n## File naming\n\nOpen Presentation Format documents are JSON files. Use `*.opf.json` for complete OPF presentation documents, for example `board-review.opf.json` or `deck.opf.json`.\n\nAvoid using bare `*.opf` for OPF JSON. The `.opf` extension is already used by other document and project formats, while `.opf.json` keeps the OPF identity and still makes the underlying JSON format clear to editors, validators, agents, and version-control tooling.\n\n## Naming and reuse\n\nThe format name is **Open Presentation Format**. The schemas, catalogs, packages, and local tooling in this repository are free and open source under the MIT license, so third-party tools may read, write, validate, render, convert, and describe support for Open Presentation Format without adopting any product-specific branding.\n\n## Why OPF\n\n`.pptx` is a zipped bundle of XML. Humans can\'t diff it, LLMs can\'t read or write it reliably, and git can\'t track it meaningfully. Every change looks like a binary blob.\n\nOPF is plain JSON. A human can open it in an editor. A model can read and write it without guessing at schema-by-example. Decks live in git like the rest of your work.\n\nThat\'s the shift that lets LLMs actually *author* decks. When the format stops fighting them, models can do the work that matters \u2014 narrative structure, persuasive framing, data analysis, chart recommendations, ruthless revision passes \u2014 instead of wrestling with `<p:sp>` tags.\n\nAnd they don\'t start from a blank canvas. [pptx.gallery](https://pptx.gallery) is the human-browsable reference for OPF catalog presets: layouts, themes, color schemes, font schemes, chart types, narratives, audiences, purposes, tones, languages, and social platforms.\n\n## Start in three steps\n\n1. **Install the coordinated published packages** on Node 24. See [the developer quickstart](docs/quickstart.md) for the current pin set: core 0.15.1, renderer 0.15.0, editor 0.15.0, PPTX 0.15.0 and CLI 0.15.0.\n2. **Author, validate, paginate, preview and export.** Copy [`docs/quickstart/developer-quickstart.opf.json`](./docs/quickstart/developer-quickstart.opf.json) and run the commands in that guide. From code, `exportDeck(presentation, { format: "pdf" })` of `@openpresentation/cli/api` is the simple path to a PDF, PNG, SVG or PPTX file. `validate` / `opf validate` is one local checker for format, references, accessibility, layout and content ([guide](docs/validate.md)), not visual verification.\n3. **Know the limits.** The [compatibility matrix](docs/compatibility-matrix.md) lists shipped APIs versus renderer issue 24, native PowerPoint issue 87, and other deferred work. Browse presets at [pptx.gallery](https://pptx.gallery).\n\nYour deck can live in git from the first commit. After installing dependencies and supplying referenced assets, these commands run locally without a model provider, account or hosted OPF API.\n\n## JavaScript and TypeScript\n\nThe canonical JavaScript/TypeScript package is published at [`packages/javascript`](./packages/javascript) as [`@openpresentation/opf`](https://www.npmjs.com/package/@openpresentation/opf). The schema is pre-stable (0.x \u2014 expect breaking changes between minor versions until 1.0). Its responsibility is local and format-level only:\n\n- export the canonical schemas from [`spec/`](./spec)\n- export the pinned default catalog (the pptx.gallery snapshot in [`spec/catalogs/`](./spec/catalogs)) as the opt-in `@openpresentation/opf/catalog`, for hosts to register\n- export a typed raw spec file manifest for package-addressable `spec/` content\n- generate TypeScript types, with `Presentation` as the top-level type\n- validate OPF JSON and catalog records locally\n\nIt does not render `.pptx`, parse `.pptx`, generate content with AI, fetch remote catalogs, call hosted APIs, or provide managed services. Render/edit/convert packages live in separate MIT repos that depend on `@openpresentation/opf`. The format package also exposes pure composition geometry so those packages share layout behavior.\n\n## Toolkit libraries\n\nOPF is five packages. **Core** (`@openpresentation/opf`) reads and writes the text formats (JSON, YAML, Markdown) and validates. **The CLI package** (`@openpresentation/cli`) is the `opf` command and the library API `@openpresentation/cli/api`, which reads and writes files (`exportDeck`, `importDeck`). **Render** (`opf-render`) and **PPTX** (`opf-pptx`) are the engines behind them, installed as needed. **The editor** (`opf-editor`) is the headless editing layer. The engines and the editor live in sibling repositories. See [ecosystem development](docs/ecosystem-development.md) for coordinated builds and verification, and [dynamic composition](docs/dynamic-composition.md) for portable layout rules.\n\n| Repo | Role | Boundary |\n|---|---|---|\n| `cli` (`@openpresentation/cli`, this repository) | `opf` command; `cli/api`: `exportDeck`, `importDeck`, `readDeck` | Reads and writes files; calls the engines below as optional peers |\n| `opf-render` | OPF to SVG/PNG/PDF | Local and embeddable rendering library |\n| `opf-editor` | WYSIWYG bindings/components | Headless editor primitives plus optional UI components |\n| `opf-pptx` | OPF to PPTX and PPTX to OPF | Pure local import/export library for browser and server use where supported |\n\nThese repos provide OSS primitives only. Downstream applications own hosting, auth, storage, collaboration, queues, previews, analytics, support, and workflow UX.\n\n## Usage\n\nInstall from npm:\n\n```sh\npnpm add @openpresentation/opf\n# or: npm install @openpresentation/opf\n```\n\nTo work on the package itself, clone this repo and build the workspace:\n\n```sh\npnpm install\npnpm build\n```\n\nUse the format package from JavaScript or TypeScript:\n\n```ts\nimport { presentation, validate } from "@openpresentation/opf";\nimport { defaultCatalog } from "@openpresentation/opf/catalog";\n\nimport type { Presentation } from "@openpresentation/opf";\n\nconst deck: Presentation = {\n name: "Quarterly Review",\n slides: [{ title: "Quarterly Review", items: ["Revenue", "Product", "Hiring"] }],\n};\n\nconst report = validate(deck);\nconsole.log(report.valid); // no finding has severity "error"\nconsole.log(report.findings); // every finding: rule id, severity, category, JSON Pointer path, message, fixes\n// Core ships no catalog records in its main entry; a host registers the catalogs it trusts.\nconsole.log(validate({ ...deck, design: { theme: "classic" } }, { catalogs: [defaultCatalog] }).valid);\nconsole.log(Object.keys(defaultCatalog.audiences).length);\n```\n\nExport and import files from code with the CLI package\'s library API (the engines `@openpresentation/opf-render` and `@openpresentation/opf-pptx` are optional peers, installed as needed):\n\n```ts\nimport { readDeck, exportDeck, importDeck } from "@openpresentation/cli/api";\n\nconst { presentation } = readDeck(text, { filename: "deck.opf.md" }); // JSON, YAML or Markdown\nconst { files } = await exportDeck(presentation, { format: "pdf" }); // [{ name, type, bytes }]\nconst imported = await importDeck(pptxBytes); // PPTX to OPF\n```\n\nUse focused imports when you only need one surface:\n\n```ts\nimport { presentation } from "@openpresentation/opf/schemas";\nimport { defaultCatalog } from "@openpresentation/opf/catalog";\nimport { specFileEntries } from "@openpresentation/opf/spec-files";\nimport { validate } from "@openpresentation/opf/validator";\nimport type { Presentation } from "@openpresentation/opf/types";\n```\n\nUse raw JSON when an engine or resolver needs package-addressable files:\n\n```ts\nimport presentationSchema from "@openpresentation/opf/spec/schemas/opf.schema.json" with {\n type: "json",\n};\n```\n\nUse the [installable OPF CLI](./packages/cli/README.md) to create, validate, and edit files locally:\n\n```sh\npnpm --filter @openpresentation/cli build\nnode packages/cli/dist/index.js create deck.opf.json --title "Decision brief"\nnode packages/cli/dist/index.js validate deck.opf.json\nnode packages/cli/dist/index.js edit deck.opf.json --patch changes.json --in-place\n```\n\nSee [CSV and JSON data import](./docs/data-import.md) for editable tables and charts in the editor, CLI, and package API, and [content conversions](./docs/conversions.md) for the pure converters (`@openpresentation/opf/convert`) that change a block\'s kind, nest list items, restructure a slide and split or merge slides, and [Markdown and outlines](./docs/markdown.md) for the deterministic Markdown dialect (`@openpresentation/opf/markdown`, `opf from-md`, `opf to-md`) that reads and writes a whole deck as text.\n\n[OPF as YAML](./docs/yaml.md) describes the strict YAML form of a deck (`@openpresentation/opf/yaml`, `opf from-yaml`, `opf to-yaml`, `.opf.yaml` files in every command, editor autocomplete); JSON stays the canonical form. A deck can equally be a Markdown file, `deck.opf.md`: every command reads and writes it (see [Markdown decks in every command](./docs/markdown.md#markdown-decks-in-every-command)), and `readDeck` / `writeDeck` read and write a deck in JSON, YAML or Markdown with one call.\n\nSee [Templates and variables](./docs/templates-and-variables.md) for fillable OPF templates: typed variables, `{{id}}` tokens, `opf fill` and `resolveVariables`.\n\n## Layout\n\n| Path | Contents |\n|---|---|\n| [`spec/schemas/opf.schema.json`](./spec/schemas/opf.schema.json) | Canonical JSON Schema for top-level OPF `Presentation` documents. |\n| [`docs/how-opf-works.md`](./docs/how-opf-works.md) | Conceptual introduction: the document model, content shapes, catalog resolution, and the validation philosophy. Start here. |\n| [`docs/design-resolution.md`](./docs/design-resolution.md) | The design precedence algorithm (slide design \u2192 deck design \u2192 resolved theme \u2192 engine defaults) with worked examples. |\n| [`docs/schema-reference.md`](./docs/schema-reference.md) | Author-facing reference for top-level OPF fields and every presentation schema `$defs` object/type. |\n| [`docs/catalog-schema-reference.md`](./docs/catalog-schema-reference.md) | Author-facing reference for every companion catalog schema. |\n| [`docs/content-payloads.md`](./docs/content-payloads.md) | Author-facing notes for slide and region content payloads, including chart and table object shapes. |\n| [`docs/footnotes-citations-captions.md`](./docs/footnotes-citations-captions.md) | Citations (`cite`), inline footnotes, the deck `references` list, captions on images, charts, tables and videos, and how every engine draws them. |\n| [`docs/examples.md`](./docs/examples.md) | Guide to the expanded scenario-oriented examples under `examples/gallery/`. |\n| [`docs/live-editor.md`](./docs/live-editor.md) | Browser canvas, live OPF editing, font loading, published packages, and current fidelity limits. |\n| [`docs/release-process.md`](./docs/release-process.md) | Maintainer runbook for tagging, trusted npm publishing, verification, and GitHub release notes. |\n| [`spec/schemas/*.schema.json`](./spec/schemas) | Companion schemas for catalog records and sub-objects. |\n| [`spec/catalogs/<catalog-kind>/`](./spec/catalogs) | The pinned snapshot of the default catalog pptx.gallery publishes (shipped as `@openpresentation/opf/catalog`). |\n| [`spec/openapi.yaml`](./spec/openapi.yaml) | Optional reference OpenAPI contract for downstream services that choose to expose OPF over HTTP. OpenPresentation does not host this API. |\n| [`examples/technical/`](./examples/technical) | Focused OPF fixtures for validator, renderer, catalog-resolution, design, content-payload, and region behavior. |\n| [`examples/gallery/`](./examples/gallery) | Broader OPF example decks organized by industry, function, education, government, presentation type, international, and design/media scenarios. |\n| [`packages/javascript/`](./packages/javascript) | Public pre-stable source for `@openpresentation/opf`. |\n| [`packages/cli/`](./packages/cli) | Installable local CLI for creating, validating, editing, and inspecting OPF. |\n| [`legacy/`](./legacy) | Tombstone for service-specific clients, CLIs, tool integrations, and workflows removed from the OpenPresentation OSS repo. |\n\n## OpenPresentation Boundary\n\nOpenPresentation defines the format, bundled presets, local validation, examples, docs, and planned local render/edit/convert libraries. It does not provide hosted functions or managed product surfaces.\n\nFuture non-JavaScript OPF packages should follow the same local-first boundary: Python and Go packages should expose schemas, types/models, catalogs, validation, and package-addressable assets. Future toolkit packages should expose embeddable library APIs with no required network calls, hosted callbacks, hidden telemetry, or managed infrastructure assumptions.\n\nThe published JavaScript package copies package-addressable OPF schemas, catalogs, reference assets, and the optional reference `spec/openapi.yaml` from `spec/`. It intentionally remains `@openpresentation/opf` instead of introducing a separate `@openpresentation/opf-spec` package so downstream imports can advance by semver-pinning one canonical package.\n\n## License\n\nMIT. See [LICENSE](./LICENSE).\n';
2
+ var repoReadmeRaw = '# Open Presentation Format (OPF)\n\n[![npm version](https://img.shields.io/npm/v/@openpresentation/opf?label=npm)](https://www.npmjs.com/package/@openpresentation/opf)\n[![npm downloads](https://img.shields.io/npm/dw/@openpresentation/opf)](https://www.npmjs.com/package/@openpresentation/opf)\n[![license](https://img.shields.io/npm/l/@openpresentation/opf)](./LICENSE)\n\nPublic npm package: [`@openpresentation/opf`](https://www.npmjs.com/package/@openpresentation/opf) (`npm install @openpresentation/opf`).\n\nOpen Presentation Format is the portable, human-readable JSON document format for slide decks.\n\nThis repository is the canonical home for the OPF **spec**, **JSON Schemas**, **catalog presets**, examples, generated developer types, local validation tooling, and integration docs for the render/edit/convert toolkit. OpenPresentation publishes open-source code and documentation only; it does not provide hosted APIs, hosted rendering functions, queues, storage, authentication, jobs, previews, SLAs, telemetry, or managed infrastructure.\n\nFor AI agents, use the [OPF skill set](docs/agent-skills.md) for authoring, layout, presets, editing, export, and schema inspection.\n\nPublished CLI 0.16.0 installs all six skills into your project with `npx @openpresentation/cli@0.16.0 skills install`. It uses local copies, preserves existing instructions and refuses to overwrite customized skills. See the [installation and update guide](docs/agent-skills.md) for personal or agent-specific targets and source development.\n\nFor a fresh Node 24 project that installs **published** packages (not this\ncheckout), follow the [developer quickstart](docs/quickstart.md) and the\n[compatibility matrix](docs/compatibility-matrix.md).\n\nFor LLM authoring, start with [the authoring guide](docs/llm-authoring.md), [dynamic composition](docs/dynamic-composition.md), and [local ecosystem verification](docs/ecosystem-development.md).\n\n## File naming\n\nOpen Presentation Format documents are JSON files. Use `*.opf.json` for complete OPF presentation documents, for example `board-review.opf.json` or `deck.opf.json`.\n\nAvoid using bare `*.opf` for OPF JSON. The `.opf` extension is already used by other document and project formats, while `.opf.json` keeps the OPF identity and still makes the underlying JSON format clear to editors, validators, agents, and version-control tooling.\n\n## Naming and reuse\n\nThe format name is **Open Presentation Format**. The schemas, catalogs, packages, and local tooling in this repository are free and open source under the MIT license, so third-party tools may read, write, validate, render, convert, and describe support for Open Presentation Format without adopting any product-specific branding.\n\n## Why OPF\n\n`.pptx` is a zipped bundle of XML. Humans can\'t diff it, LLMs can\'t read or write it reliably, and git can\'t track it meaningfully. Every change looks like a binary blob.\n\nOPF is plain JSON. A human can open it in an editor. A model can read and write it without guessing at schema-by-example. Decks live in git like the rest of your work.\n\nThat\'s the shift that lets LLMs actually *author* decks. When the format stops fighting them, models can do the work that matters \u2014 narrative structure, persuasive framing, data analysis, chart recommendations, ruthless revision passes \u2014 instead of wrestling with `<p:sp>` tags.\n\nAnd they don\'t start from a blank canvas. [pptx.gallery](https://pptx.gallery) is the human-browsable reference for OPF catalog presets: layouts, themes, color schemes, font schemes, chart types, narratives, audiences, purposes, tones, languages, and social platforms.\n\n## Start in three steps\n\n1. **Install the coordinated published packages** on Node 24. See [the developer quickstart](docs/quickstart.md) for the current pin set: core 0.16.0, renderer 0.16.0, editor 0.16.0, PPTX 0.16.1 and CLI 0.16.0.\n2. **Author, validate, paginate, preview and export.** Copy [`docs/quickstart/developer-quickstart.opf.json`](./docs/quickstart/developer-quickstart.opf.json) and run the commands in that guide. From code, `convert("deck.opf.md", "deck.pdf")` of `@openpresentation/opf/node` is the simple path to a PDF, PNG, SVG or PPTX file. `validate` / `opf validate` is one local checker for format, references, accessibility, layout and content ([guide](docs/validate.md)), not visual verification.\n3. **Know the limits.** The [compatibility matrix](docs/compatibility-matrix.md) lists shipped APIs versus renderer issue 24, native PowerPoint issue 87, and other deferred work. Browse presets at [pptx.gallery](https://pptx.gallery).\n\nYour deck can live in git from the first commit. After installing dependencies and supplying referenced assets, these commands run locally without a model provider, account or hosted OPF API.\n\n## JavaScript and TypeScript\n\nThe canonical JavaScript/TypeScript package is published at [`packages/javascript`](./packages/javascript) as [`@openpresentation/opf`](https://www.npmjs.com/package/@openpresentation/opf). The schema is pre-stable (0.x \u2014 expect breaking changes between minor versions until 1.0). Its responsibility is local and format-level only:\n\n- export the canonical schemas from [`spec/`](./spec)\n- export the pinned default catalog (the pptx.gallery snapshot in [`spec/catalogs/`](./spec/catalogs)) as the opt-in `@openpresentation/opf/catalog`, for hosts to register\n- export a typed raw spec file manifest for package-addressable `spec/` content\n- generate TypeScript types, with `Presentation` as the top-level type\n- validate OPF JSON and catalog records locally\n\nIts Node-only `@openpresentation/opf/node` entry reads and writes files (`convert`, `open`, `save`) and draws them through the optional engines below; the root and every other entry run in a browser. It does not generate content with AI, fetch remote catalogs, call hosted APIs, or provide managed services. Render/edit/convert packages live in separate MIT repos that depend on `@openpresentation/opf`. The format package also exposes pure composition geometry so those packages share layout behavior.\n\n## Toolkit libraries\n\nOPF is five packages. **Core** (`@openpresentation/opf`) is the format and its API: it reads and writes the text formats (JSON, YAML, Markdown) and validates, and `@openpresentation/opf/node` reads and writes files. **The CLI** (`@openpresentation/cli`) is the `opf` command. **Render** (`opf-render`), **PPTX** (`opf-pptx`) and **the editor** (`opf-editor`) are the engines: drawing, PowerPoint and editing, installed as needed. The engines and the editor live in sibling repositories. See [ecosystem development](docs/ecosystem-development.md) for coordinated builds and verification, and [dynamic composition](docs/dynamic-composition.md) for portable layout rules.\n\n| Repo | Role | Boundary |\n|---|---|---|\n| `cli` (`@openpresentation/cli`, this repository) | `opf` command | Runs core\'s `/node` engine: reads and writes files and calls the engines below as optional peers |\n| `opf-render` | OPF to SVG/PNG/PDF | Local and embeddable rendering library |\n| `opf-editor` | WYSIWYG bindings/components | Headless editor primitives plus optional UI components |\n| `opf-pptx` | OPF to PPTX and PPTX to OPF | Pure local import/export library for browser and server use where supported |\n\nThese repos provide OSS primitives only. Downstream applications own hosting, auth, storage, collaboration, queues, previews, analytics, support, and workflow UX.\n\n## Usage\n\nInstall from npm:\n\n```sh\npnpm add @openpresentation/opf\n# or: npm install @openpresentation/opf\n```\n\nTo work on the package itself, clone this repo and build the workspace:\n\n```sh\npnpm install\npnpm build\n```\n\nUse the format package from JavaScript or TypeScript:\n\n```ts\nimport { presentation, validate } from "@openpresentation/opf";\nimport { defaultCatalog } from "@openpresentation/opf/catalog";\n\nimport type { Presentation } from "@openpresentation/opf";\n\nconst deck: Presentation = {\n name: "Quarterly Review",\n slides: [{ title: "Quarterly Review", items: ["Revenue", "Product", "Hiring"] }],\n};\n\nconst report = validate(deck);\nconsole.log(report.valid); // no finding has severity "error"\nconsole.log(report.findings); // every finding: rule id, severity, category, JSON Pointer path, message, fixes\n// Core ships no catalog records in its main entry; a host registers the catalogs it trusts.\nconsole.log(validate({ ...deck, design: { theme: "classic" } }, { catalogs: [defaultCatalog] }).valid);\nconsole.log(Object.keys(defaultCatalog.audiences).length);\n```\n\nConvert, open and save files in Node with `@openpresentation/opf/node` (the engines `@openpresentation/opf-render` and `@openpresentation/opf-pptx` are optional peers, installed as needed; see [OPF files in Node](docs/node.md)):\n\n```ts\nimport * as opf from "@openpresentation/opf/node";\n\nawait opf.convert("deck.opf.md", "deck.pdf");\nconst deck = await opf.open("deck.opf.md");\ndeck.slides.push({ title: "Q4" });\nawait opf.save(deck, "deck.opf.md");\nconst { files } = await opf.convert(deck, { format: "pptx" }); // bytes, nothing written\n```\n\nUse focused imports when you only need one surface:\n\n```ts\nimport { presentation } from "@openpresentation/opf/schemas";\nimport { defaultCatalog } from "@openpresentation/opf/catalog";\nimport { specFileEntries } from "@openpresentation/opf/spec-files";\nimport { validate } from "@openpresentation/opf/validator";\nimport type { Presentation } from "@openpresentation/opf/types";\n```\n\nUse raw JSON when an engine or resolver needs package-addressable files:\n\n```ts\nimport presentationSchema from "@openpresentation/opf/spec/schemas/opf.schema.json" with {\n type: "json",\n};\n```\n\nUse the [installable OPF CLI](./packages/cli/README.md) to create, validate, and edit files locally:\n\n```sh\npnpm --filter @openpresentation/cli build\nnode packages/cli/dist/index.js create deck.opf.json --title "Decision brief"\nnode packages/cli/dist/index.js validate deck.opf.json\nnode packages/cli/dist/index.js edit deck.opf.json --patch changes.json --in-place\n```\n\nSee [CSV and JSON data import](./docs/data-import.md) for editable tables and charts in the editor, CLI, and package API, and [content conversions](./docs/conversions.md) for the pure converters (`@openpresentation/opf/convert`) that change a block\'s kind, nest list items, restructure a slide and split or merge slides, and [Markdown and outlines](./docs/markdown.md) for the deterministic Markdown dialect (`@openpresentation/opf/markdown`, `opf from-md`, `opf to-md`) that reads and writes a whole deck as text.\n\n[OPF as YAML](./docs/yaml.md) describes the strict YAML form of a deck (`@openpresentation/opf/yaml`, `opf from-yaml`, `opf to-yaml`, `.opf.yaml` files in every command, editor autocomplete); JSON stays the canonical form. A deck can equally be a Markdown file, `deck.opf.md`: every command reads and writes it (see [Markdown decks in every command](./docs/markdown.md#markdown-decks-in-every-command)), and `parse` / `stringify` read and write a deck in JSON, YAML or Markdown with one call.\n\nSee [Templates and variables](./docs/templates-and-variables.md) for fillable OPF templates: typed variables, `{{id}}` tokens, `opf fill` and `resolveVariables`.\n\n## Layout\n\n| Path | Contents |\n|---|---|\n| [`spec/schemas/opf.schema.json`](./spec/schemas/opf.schema.json) | Canonical JSON Schema for top-level OPF `Presentation` documents. |\n| [`docs/how-opf-works.md`](./docs/how-opf-works.md) | Conceptual introduction: the document model, content shapes, catalog resolution, and the validation philosophy. Start here. |\n| [`docs/design-resolution.md`](./docs/design-resolution.md) | The design precedence algorithm (slide design \u2192 deck design \u2192 resolved theme \u2192 engine defaults) with worked examples. |\n| [`docs/schema-reference.md`](./docs/schema-reference.md) | Author-facing reference for top-level OPF fields and every presentation schema `$defs` object/type. |\n| [`docs/catalog-schema-reference.md`](./docs/catalog-schema-reference.md) | Author-facing reference for every companion catalog schema. |\n| [`docs/content-payloads.md`](./docs/content-payloads.md) | Author-facing notes for slide and region content payloads, including chart and table object shapes. |\n| [`docs/footnotes-citations-captions.md`](./docs/footnotes-citations-captions.md) | Citations (`cite`), inline footnotes, the deck `references` list, captions on images, charts, tables and videos, and how every engine draws them. |\n| [`docs/examples.md`](./docs/examples.md) | Guide to the expanded scenario-oriented examples under `examples/gallery/`. |\n| [`docs/live-editor.md`](./docs/live-editor.md) | Browser canvas, live OPF editing, font loading, published packages, and current fidelity limits. |\n| [`docs/release-process.md`](./docs/release-process.md) | Maintainer runbook for tagging, trusted npm publishing, verification, and GitHub release notes. |\n| [`spec/schemas/*.schema.json`](./spec/schemas) | Companion schemas for catalog records and sub-objects. |\n| [`spec/catalogs/<catalog-kind>/`](./spec/catalogs) | The pinned snapshot of the default catalog pptx.gallery publishes (shipped as `@openpresentation/opf/catalog`). |\n| [`spec/openapi.yaml`](./spec/openapi.yaml) | Optional reference OpenAPI contract for downstream services that choose to expose OPF over HTTP. OpenPresentation does not host this API. |\n| [`examples/technical/`](./examples/technical) | Focused OPF fixtures for validator, renderer, catalog-resolution, design, content-payload, and region behavior. |\n| [`examples/gallery/`](./examples/gallery) | Broader OPF example decks organized by industry, function, education, government, presentation type, international, and design/media scenarios. |\n| [`packages/javascript/`](./packages/javascript) | Public pre-stable source for `@openpresentation/opf`. |\n| [`packages/cli/`](./packages/cli) | Installable local CLI for creating, validating, editing, and inspecting OPF. |\n| [`legacy/`](./legacy) | Tombstone for service-specific clients, CLIs, tool integrations, and workflows removed from the OpenPresentation OSS repo. |\n\n## OpenPresentation Boundary\n\nOpenPresentation defines the format, bundled presets, local validation, examples, docs, and planned local render/edit/convert libraries. It does not provide hosted functions or managed product surfaces.\n\nFuture non-JavaScript OPF packages should follow the same local-first boundary: Python and Go packages should expose schemas, types/models, catalogs, validation, and package-addressable assets. Future toolkit packages should expose embeddable library APIs with no required network calls, hosted callbacks, hidden telemetry, or managed infrastructure assumptions.\n\nThe published JavaScript package copies package-addressable OPF schemas, catalogs, reference assets, and the optional reference `spec/openapi.yaml` from `spec/`. It intentionally remains `@openpresentation/opf` instead of introducing a separate `@openpresentation/opf-spec` package so downstream imports can advance by semver-pinning one canonical package.\n\n## License\n\nMIT. See [LICENSE](./LICENSE).\n';
3
3
 
4
4
  // src/repo-readme.ts
5
5
  var repoReadme = repoReadmeRaw;
package/dist/schemas.js CHANGED
@@ -1 +1 @@
1
- export { audience, chartType, colorScheme, fontScheme, language, layout, narrative, presentation, purpose, schemaEntries, schemaNames, schemas, socialPlatform, theme, tone } from './chunk-WEDGVC5W.js';
1
+ export { audience, chartType, colorScheme, fontScheme, language, layout, narrative, presentation, purpose, schemaEntries, schemaNames, schemas, socialPlatform, theme, tone } from './chunk-RA64UQKI.js';
@@ -4,7 +4,7 @@
4
4
  "publisher": "https://www.pptx.gallery",
5
5
  "source": {
6
6
  "repository": "https://github.com/Data-Advantage/pptx-gallery",
7
- "commit": "db31c09e35d7e4c7a12072d6f95ece36336f5dfa",
7
+ "commit": "cce9b8eec0b30c7d9f7a6aa004e8fe11782af245",
8
8
  "path": "public"
9
9
  },
10
10
  "kinds": {
@@ -36,7 +36,7 @@
36
36
  "minItems": 1
37
37
  }
38
38
  ],
39
- "description": "Organization associated with the presentation, usually the presenting company. Array form supports hosts, partners, clients, and sponsors. The primary organization (Organization.role 'primary', else the first item) supplies the default deck logo, the 'organization' and 'socials' header/footer fields and the 'organization.<field>' built-in variables; the others are available by id as 'organization.<id>.<field>' and are not drawn automatically."
39
+ "description": "Organization associated with the presentation, usually the presenting company. Array form supports hosts, partners, clients, and sponsors. The primary organization (Organization.role 'primary', else the first item) supplies the default deck logo, the 'socials' header/footer field and the 'organization.<field>' built-in variables; the others are available by id as 'organization.<id>.<field>' and are not drawn automatically."
40
40
  },
41
41
  "speaker": {
42
42
  "oneOf": [
@@ -47,7 +47,7 @@
47
47
  "minItems": 1
48
48
  }
49
49
  ],
50
- "description": "Person presenting the deck. Array form supports panels and multi-speaker decks. The first speaker is the primary speaker: the built-in variables 'speaker.<field>' and the 'speaker' header/footer field read it, 'speakers' lists every name, and 'speaker.<id>.<field>' addresses one by id. A speaker is drawn nowhere else."
50
+ "description": "Person presenting the deck. Array form supports panels and multi-speaker decks. The first speaker is the primary speaker: the built-in variables 'speaker.<field>' read it, 'speakers' lists every name, and 'speaker.<id>.<field>' addresses one by id. A speaker is drawn nowhere else."
51
51
  },
52
52
  "author": {
53
53
  "oneOf": [
@@ -494,7 +494,7 @@
494
494
  },
495
495
  "Organization": {
496
496
  "type": "object",
497
- "description": "An organization associated with the presentation, typically the presenting company, but also hosts, partners, clients, or sponsors. The primary organization (role 'primary', else the first one) supplies the default deck logo (unless design.logo overrides it), the 'organization' header/footer field (its name) and the 'socials' field (its socials). Every field is also a built-in variable ('{{organization.name}}', 'var:organization.logo', 'organization.<id>.<field>'). Nothing else about an organization is drawn automatically. See docs/templates-and-variables.md.",
497
+ "description": "An organization associated with the presentation, typically the presenting company, but also hosts, partners, clients, or sponsors. The primary organization (role 'primary', else the first one) supplies the default deck logo (unless design.logo overrides it) and the 'socials' header/footer field (its socials). Every field is also a built-in variable ('{{organization.name}}', 'var:organization.logo', 'organization.<id>.<field>'). Nothing else about an organization is drawn automatically. See docs/templates-and-variables.md.",
498
498
  "required": ["id", "name"],
499
499
  "properties": {
500
500
  "id": {
@@ -505,7 +505,7 @@
505
505
  },
506
506
  "name": {
507
507
  "type": "string",
508
- "description": "Display name. Drawn by the 'organization' header/footer field for the primary organization; the built-in variable 'organization.name' (or 'organization.<id>.name') carries it into any string.",
508
+ "description": "Display name. The built-in variable 'organization.name' (primary organization) or 'organization.<id>.name' carries it into any string, such as a header or footer text of '{{organization.name}}'.",
509
509
  "examples": ["Acme Corp", "DevConf 2026", "Beta Industries"]
510
510
  },
511
511
  "legalName": {
@@ -547,7 +547,7 @@
547
547
  "role": {
548
548
  "type": "string",
549
549
  "enum": ["primary", "partner", "client", "sponsor", "host"],
550
- "description": "Role of the organization relative to the presentation. Only 'primary' has behavior: it selects the primary organization (deck logo, 'organization' and 'socials' header/footer fields, and the 'organization.<field>' built-ins). When no organization has role 'primary', the first one is primary. 'partner', 'client', 'sponsor' and 'host' are descriptive labels that change nothing."
550
+ "description": "Role of the organization relative to the presentation. Only 'primary' has behavior: it selects the primary organization (deck logo, the 'socials' header/footer field, and the 'organization.<field>' built-ins). When no organization has role 'primary', the first one is primary. 'partner', 'client', 'sponsor' and 'host' are descriptive labels that change nothing."
551
551
  },
552
552
  "socials": {
553
553
  "$ref": "#/$defs/Socials",
@@ -557,7 +557,7 @@
557
557
  },
558
558
  "Speaker": {
559
559
  "type": "object",
560
- "description": "A person presenting the deck. A speaker is drawn only through built-in variables ('{{speaker.name}}' inside any string, 'var:speaker.photo' as a whole image field) and the 'speaker' header/footer field (the first speaker's name and title). No layout, cover or bio slide places a speaker on its own. See docs/templates-and-variables.md.",
560
+ "description": "A person presenting the deck. A speaker is drawn only through built-in variables ('{{speaker.name}}' inside any string, a header or footer text included, and 'var:speaker.photo' as a whole image field). No layout, cover or bio slide places a speaker on its own. See docs/templates-and-variables.md.",
561
561
  "required": ["id", "name"],
562
562
  "properties": {
563
563
  "id": {
@@ -568,12 +568,12 @@
568
568
  },
569
569
  "name": {
570
570
  "type": "string",
571
- "description": "Display name. Built-in variable 'speaker.name' (first speaker) or 'speaker.<id>.name'; the first speaker's name is also drawn by the 'speaker' header/footer field and every name is listed by 'speakers'.",
571
+ "description": "Display name. Built-in variable 'speaker.name' (first speaker) or 'speaker.<id>.name'; every name is listed by 'speakers'.",
572
572
  "examples": ["Alice Chen", "Bob Lee", "Dr. Carla Diaz"]
573
573
  },
574
574
  "title": {
575
575
  "type": "string",
576
- "description": "Role or title. Built-in variable 'speaker.title'; the 'speaker' header/footer field draws it after the name ('Alice Chen, VP of Engineering').",
576
+ "description": "Role or title. Built-in variable 'speaker.title' (or 'speaker.<id>.title'), for example in a footer text of '{{speaker.name}}, {{speaker.title}}'.",
577
577
  "examples": ["VP of Engineering", "Founder & CEO", "Chief Product Officer", "Senior Staff Engineer"]
578
578
  },
579
579
  "photo": {
@@ -715,7 +715,7 @@
715
715
  { "$ref": "#/$defs/HeaderFooter" }
716
716
  ],
717
717
  "description": "Repeated header furniture rendered outside the main slide content. Use false to suppress an inherited header.",
718
- "examples": [false, { "left": { "section": true }, "right": { "image": "asset:acme-logo" } }]
718
+ "examples": [false, { "left": { "text": "{{slide.section}}" }, "right": { "image": "asset:acme-logo" } }]
719
719
  },
720
720
  "footer": {
721
721
  "oneOf": [
@@ -725,7 +725,7 @@
725
725
  "description": "Repeated footer furniture rendered outside the main slide content. Use false to suppress an inherited footer.",
726
726
  "examples": [
727
727
  false,
728
- { "left": { "image": "asset:acme-logo" }, "center": { "text": "Confidential" }, "right": { "slideNumber": true } }
728
+ { "left": { "image": "asset:acme-logo" }, "center": { "text": "Confidential" }, "right": { "text": "{{slide.number}}" } }
729
729
  ]
730
730
  },
731
731
  "titleAlignment": {
@@ -1027,7 +1027,7 @@
1027
1027
  "additionalProperties": {
1028
1028
  "$ref": "#/$defs/Variable"
1029
1029
  },
1030
- "description": "Named variables, keyed by stable kebab-case id. A variable is a typed, named value the deck declares once and uses in many places: a color ('var:<id>' in color fields, the original use), or content that fills a template (text, number, date, image, url, list). Content is referenced inline as '{{<id>}}' inside any string, or whole as 'var:<id>' in a field of the matching type; '\\{{' writes a literal '{{'. A hex string is shorthand for a color variable. A variable with no 'value' is unfilled: expected in a template (root 'template': true), an error in a normal deck. Engines resolve variables with resolveVariables() before composing, rendering or exporting, so a template plus its values previews and exports exactly like the equivalent hand-written deck. Read-only built-in variables come from the deck's own metadata and use dotted names that a user id can never take: 'deck.name', 'deck.description', 'deck.author', 'speaker.name|title|email|phone|bio|photo' (first speaker), 'speakers' (every speaker's name, a list), 'organization.name|legalName|tagline|domain|email|phone|logo' (primary organization), and 'speaker.<id>.<field>' / 'organization.<id>.<field>' by id. They are written the same two ways ('{{speaker.name}}', 'var:speaker.photo'), are never declared, and an unknown built-in path is a validation error; a known one with no source value resolves to nothing with a warning. The id 'speakers' is reserved. See docs/templates-and-variables.md.",
1030
+ "description": "Named variables, keyed by stable kebab-case id. A variable is a typed, named value the deck declares once and uses in many places: a color ('var:<id>' in color fields, the original use), or content that fills a template (text, number, date, image, url, list). Content is referenced inline as '{{<id>}}' inside any string, or whole as 'var:<id>' in a field of the matching type; '\\{{' writes a literal '{{'. A hex string is shorthand for a color variable. A variable with no 'value' is unfilled: expected in a template (root 'template': true), an error in a normal deck. Engines resolve variables with resolveVariables() before composing, rendering or exporting, so a template plus its values previews and exports exactly like the equivalent hand-written deck. Read-only built-in variables come from the deck's own metadata and use dotted names that a user id can never take: 'deck.name', 'deck.description', 'deck.author', 'speaker.name|title|email|phone|bio|photo' (first speaker), 'speakers' (every speaker's name, a list), 'organization.name|legalName|tagline|domain|email|phone|logo' (primary organization), and 'speaker.<id>.<field>' / 'organization.<id>.<field>' by id. They are written the same two ways ('{{speaker.name}}', 'var:speaker.photo'), are never declared, and an unknown built-in path is a validation error; a known one with no source value resolves to nothing with a warning. The id 'speakers' is reserved. Three built-ins are slide-scoped and written only as inline tokens: '{{slide.number}}' (the displayed slide number after pagination), '{{slide.section}}' (the slide's section) and '{{deck.slideCount}}' (the number of slides after pagination). resolveVariables() leaves them as written; they resolve per slide as it is composed (resolveSlideVariables(), and header/footer text in layoutFurniture()), so every 'slide.' name is reserved and 'var:slide.*' or 'var:deck.slideCount' is a validation error. See docs/templates-and-variables.md.",
1031
1031
  "examples": [
1032
1032
  {
1033
1033
  "risk": "#B42318",
@@ -1835,7 +1835,8 @@
1835
1835
  },
1836
1836
  "HeaderFooterItem": {
1837
1837
  "type": "object",
1838
- "description": "One header/footer zone. Every configured field renders; fields in one zone stack top to bottom in the order logo, image, text, organization, speaker, socials, section, slide number, date. Put a date and a slide number in different zones to keep each on the zone's single line.",
1838
+ "description": "One header/footer zone. Every configured field renders; fields in one zone stack top to bottom in the order logo, image, text, socials, date. Generated values such as the slide number, the slide count, the section, the organization or the speaker are variables inside text ('{{slide.number}} / {{deck.slideCount}}', '{{organization.name}}'), so one text writes several values in the author's order; a line break is '\\n'. Put a date and a slide number in different zones to keep each on the zone's single line. See docs/templates-and-variables.md.",
1839
+ "additionalProperties": false,
1839
1840
  "properties": {
1840
1841
  "logo": {
1841
1842
  "type": "boolean",
@@ -1843,24 +1844,14 @@
1843
1844
  },
1844
1845
  "text": {
1845
1846
  "type": "string",
1846
- "description": "Literal text rendered in this zone.",
1847
- "examples": ["Confidential", "Q4 Business Review"]
1847
+ "description": "Text rendered in this zone. Variables resolve inside it like any string: deck-wide ones ('{{organization.name}}', '{{speaker.name}}, {{speaker.title}}', '{{customer}}') before composition, and the slide-scoped built-ins '{{slide.number}}', '{{slide.section}}' and '{{deck.slideCount}}' for each slide as it is laid out. Each '{{slide.number}}' is a live slide-number field: PPTX export writes it as a native field when its value fits within one accepted text line, and as static text with a diagnostic otherwise. '{{deck.slideCount}}' is fixed text, because PowerPoint has no slide-count field. Write '\\{{' for literal braces.",
1848
+ "examples": ["Confidential", "Q4 Business Review", "{{slide.number}} / {{deck.slideCount}}", "{{organization.name}}\n{{slide.section}}"]
1848
1849
  },
1849
1850
  "image": {
1850
1851
  "$ref": "#/$defs/Asset",
1851
1852
  "description": "Generic image rendered in this zone, such as a logo, partner mark, certification badge, or icon.",
1852
1853
  "examples": ["asset:acme-logo", "./assets/footer-badge.svg"]
1853
1854
  },
1854
- "slideNumber": {
1855
- "type": "boolean",
1856
- "description": "Whether to render the current slide number in this zone. PPTX export writes a native slide-number field when its value fits within one accepted text line; a value split across lines exports as static text with a diagnostic."
1857
- },
1858
- "slideNumberFormat": {
1859
- "type": "string",
1860
- "pattern": "[{]current[}]",
1861
- "description": "Template for the slide number when slideNumber is true. {current} is the displayed slide number (a native PPTX field when its value fits within one accepted text line); {total} is the number of slides in the rendered or exported deck, written as fixed text because PowerPoint has no slide-count field. Other characters are literal. Defaults to \"{current}\".",
1862
- "examples": ["{current}", "{current} / {total}", "A-{current}", "Page {current} of {total}"]
1863
- },
1864
1855
  "date": {
1865
1856
  "oneOf": [
1866
1857
  { "type": "boolean" },
@@ -1875,18 +1866,6 @@
1875
1866
  "description": "Date pattern for date. Tokens: yyyy (2026), yy (26), MMMM (April), MMM (Apr), MM (04), M (4), dd (09), d (9), EEEE (Thursday), EEE (Thu). Text in single quotes and other non-letter characters are literal. Month and weekday names are English, independent of host locale. Defaults to \"M/d/yyyy\" for a current date. PPTX export writes a native current-date field only when its complete value fits within one accepted text line and the pattern matches a PowerPoint en-US date field ('M/d/yyyy'; 'EEEE, MMMM d, yyyy'; 'd MMMM yyyy'; 'MMMM d, yyyy'; 'd-MMM-yy'; 'MMMM yy'; 'MMM-yy'). Other patterns and wrapped fields export as static text with a diagnostic. Full provenance can recover generated-date intent from unchanged supported wrapped dates on OPF reimport; the existing PPTX text remains static.",
1876
1867
  "examples": ["MMM d, yyyy", "yyyy-MM-dd", "MMM yyyy", "MMMM d, yyyy"]
1877
1868
  },
1878
- "organization": {
1879
- "type": "boolean",
1880
- "description": "Whether to render the primary organization's name from organization (role 'primary', else the first organization)."
1881
- },
1882
- "speaker": {
1883
- "type": "boolean",
1884
- "description": "Whether to render the primary (first) speaker's name and title from speaker, joined as 'Ada Lovelace, CTO' (just the name when the speaker has no title). It is generated text: without a named speaker the engine reports unresolved-content at this field. PPTX export writes it as static text and import restores the flag from the file's furniture provenance."
1885
- },
1886
- "section": {
1887
- "type": "boolean",
1888
- "description": "Whether to render the current slide section label."
1889
- },
1890
1869
  "socials": {
1891
1870
  "type": "boolean",
1892
1871
  "description": "Whether to render the primary organization's social profiles from organization.socials, one line per platform in key order. A handle is formatted through the platform's socialPlatforms record (companyUrlPattern, else profileUrlPattern, else baseUrl, with handlePrefix stripped) and shown as that profile URL without its 'https://' scheme; a value that is already a URL is shown without an 'https://' scheme; an unknown platform key shows the raw value. Exporters link each line to its full URL when one exists. Speaker socials are not rendered by this field."
@@ -2187,7 +2166,7 @@
2187
2166
  },
2188
2167
  "section": {
2189
2168
  "type": "string",
2190
- "description": "PowerPoint-style slide section label. Consecutive slides with the same value belong to the same section in presenter view, outlines, and PowerPoint section-aware exports.",
2169
+ "description": "PowerPoint-style slide section label. Consecutive slides with the same value belong to the same section in presenter view, outlines, and PowerPoint section-aware exports. Also the slide-scoped built-in variable '{{slide.section}}', for example in a header text.",
2191
2170
  "examples": ["Intro", "Problem", "Solution", "Ask", "Appendix"]
2192
2171
  },
2193
2172
  "hidden": {
package/dist/types.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- export { P as Presentation } from './presentation-COrFuj2g.js';
2
- export { a as CatalogKind } from './catalog-refs-_anZs-Qz.js';
1
+ export { P as Presentation } from './presentation-fb8CZmRq.js';
2
+ export { c as CatalogKind } from './catalog-refs-C4K4y-vh.js';
3
3
  export { SchemaName } from './schemas.js';
4
- export { a as Finding, d as FindingCategory, e as FindingFix, f as FindingFocus, b as FindingLocation, F as FindingReport, c as FindingSeverity, g as FindingSuggestion, J as JsonPatchOperation, V as ValidationIssue } from './finding-CT_f_vbD.js';
4
+ export { F as Finding, a as FindingCategory, b as FindingFix, c as FindingFocus, d as FindingLocation, e as FindingReport, f as FindingSeverity, g as FindingSuggestion, J as JsonPatchOperation, V as ValidationIssue } from './finding-CDQ_wH8j.js';
5
5
  import './json-BFSdESOE.js';
6
6
 
7
7
  /**
@@ -1,6 +1,6 @@
1
- import { C as Catalog } from './catalog-refs-_anZs-Qz.js';
2
- import { T as TextMeasurement } from './composition-D4ADF5c-.js';
3
- import { c as FindingSeverity, F as FindingReport } from './finding-CT_f_vbD.js';
1
+ import { b as Catalog } from './catalog-refs-C4K4y-vh.js';
2
+ import { T as TextMeasurement } from './composition-BbZ_9C-c.js';
3
+ import { f as FindingSeverity, e as FindingReport } from './finding-CDQ_wH8j.js';
4
4
  import { J as JsonPrimitive } from './json-BFSdESOE.js';
5
5
 
6
6
  /**
@@ -134,9 +134,18 @@ interface BuiltinVariableInfo {
134
134
  kind: VariableKind;
135
135
  /** Short label for pickers, such as "Speaker name". */
136
136
  label: string;
137
- /** The value the document gives it, when it has one (a string, an Asset or the list of names). */
137
+ /**
138
+ * `deck` for a value read once from the document; `slide` for `slide.number`, `slide.section` and
139
+ * `deck.slideCount`, which vary per slide and resolve as each slide is composed (inline tokens only).
140
+ */
141
+ scope: "deck" | "slide";
142
+ /** The value the document gives it, when it has one (a string, an Asset or the list of names). Never set for a slide-scoped built-in. */
138
143
  value?: unknown;
139
- /** True when the document has a source value for it. Unavailable built-ins resolve to nothing. */
144
+ /**
145
+ * True when the document has a source value for it. Unavailable built-ins resolve to nothing. A slide-scoped
146
+ * built-in is available when every slide gives it a value: always for `slide.number` and `deck.slideCount`, and
147
+ * for `slide.section` when at least one slide has a section.
148
+ */
140
149
  available: boolean;
141
150
  /** Every place the document uses it. */
142
151
  uses: VariableUse[];
@@ -144,7 +153,8 @@ interface BuiltinVariableInfo {
144
153
  /**
145
154
  * The built-in variables of a deck, for pickers and agents: the generic names (`deck.*`, `speaker.*`, `speakers`,
146
155
  * `organization.*`) first, then the id-addressed ones (`speaker.<id>.*`, `organization.<id>.*`) of each speaker and
147
- * organization that has an id. Each carries its kind, current source value and where the document uses it.
156
+ * organization that has an id, then the slide-scoped `slide.number`, `slide.section` and `deck.slideCount` (scope
157
+ * `slide`, no value). Each carries its kind, current source value and where the document uses it.
148
158
  */
149
159
  declare function listBuiltinVariables(presentation: unknown): BuiltinVariableInfo[];
150
160
 
@@ -203,7 +213,8 @@ interface Contract {
203
213
  /**
204
214
  * What the layout rules read from a fonts handle (the object `loadFonts()` of the renderer returns): the host's
205
215
  * measured text widths. Without one, composition uses core's portable estimate. A function receives the zero-based
206
- * slide index, so a host can supply a script-aware measurement per slide.
216
+ * slide index, so a host can supply a script-aware measurement per slide. A measurement with `forScripts` (a script
217
+ * planner, such as the renderer's) is asked for each slide's script-aware measurement, the one the engines measure with.
207
218
  */
208
219
  interface ValidateFonts {
209
220
  textMeasurement?: TextMeasurement | ((slideIndex: number) => TextMeasurement | undefined);
@@ -273,4 +284,4 @@ interface ValidationReport extends FindingReport {
273
284
  unfilledVariables?: string[];
274
285
  }
275
286
 
276
- export { variableDeclarations as A, type BuiltinVariableInfo as B, type Contract as C, DEFAULT_VARIABLE_DATE_FORMAT as D, OPFVariableError as O, type ResolveVariablesOptions as R, type ValidateOptions as V, type ValidationReport as a, type ResolveVariablesResult as b, VARIABLE_KINDS as c, type ValidateFonts as d, type ValidationCategory as e, type ValidationChecks as f, type ValidationRuleCost as g, type ValidationRuleInfo as h, type ValidationThresholds as i, type VariableDeclaration as j, type VariableDiagnostic as k, type VariableDiagnosticCode as l, type VariableDiagnosticSeverity as m, type VariableInfo as n, type VariableKind as o, type VariableUse as p, type VariableUseForm as q, type VariableValues as r, coerceVariableValue as s, formatVariableNumber as t, hasContentVariables as u, isTemplate as v, listBuiltinVariables as w, listVariables as x, resolveVariables as y, validationCategories as z };
287
+ export { variableDeclarations as A, type BuiltinVariableInfo as B, type Contract as C, DEFAULT_VARIABLE_DATE_FORMAT as D, OPFVariableError as O, type ResolveVariablesOptions as R, VARIABLE_KINDS as V, type ResolveVariablesResult as a, type ValidateFonts as b, type ValidateOptions as c, type ValidationCategory as d, type ValidationChecks as e, type ValidationReport as f, type ValidationRuleCost as g, type ValidationRuleInfo as h, type ValidationThresholds as i, type VariableDeclaration as j, type VariableDiagnostic as k, type VariableDiagnosticCode as l, type VariableDiagnosticSeverity as m, type VariableInfo as n, type VariableKind as o, type VariableUse as p, type VariableUseForm as q, type VariableValues as r, coerceVariableValue as s, formatVariableNumber as t, hasContentVariables as u, isTemplate as v, listBuiltinVariables as w, listVariables as x, resolveVariables as y, validationCategories as z };
@@ -1,13 +1,13 @@
1
- import { a as CatalogRecordKind } from './catalog-schemas-BZCjgAxu.js';
2
- import { a as Finding } from './finding-CT_f_vbD.js';
3
- import { P as Presentation } from './presentation-COrFuj2g.js';
4
- import { i as ValidationThresholds, h as ValidationRuleInfo, a as ValidationReport, V as ValidateOptions } from './validation-types-HxIgJfKx.js';
5
- export { C as Contract, d as ValidateFonts, e as ValidationCategory, f as ValidationChecks, g as ValidationRuleCost, z as validationCategories } from './validation-types-HxIgJfKx.js';
6
- import './catalog-refs-_anZs-Qz.js';
1
+ import { a as CatalogRecordKind } from './catalog-schemas-g7RFQBdc.js';
2
+ import { F as Finding } from './finding-CDQ_wH8j.js';
3
+ import { P as Presentation } from './presentation-fb8CZmRq.js';
4
+ import { i as ValidationThresholds, h as ValidationRuleInfo, f as ValidationReport, c as ValidateOptions } from './validation-types-iZbXfES6.js';
5
+ export { C as Contract, b as ValidateFonts, d as ValidationCategory, e as ValidationChecks, g as ValidationRuleCost, z as validationCategories } from './validation-types-iZbXfES6.js';
6
+ import './catalog-refs-C4K4y-vh.js';
7
7
  import './schemas.js';
8
8
  import './json-BFSdESOE.js';
9
- import './composition-D4ADF5c-.js';
10
- import './chart-data-BnNqgnC-.js';
9
+ import './composition-BbZ_9C-c.js';
10
+ import './chart-data-DTxdRRT1.js';
11
11
 
12
12
  /**
13
13
  * The series palette opf-render and opf-pptx draw charts with (`CHART_COLORS`), in series order. A host with
package/dist/validator.js CHANGED
@@ -1,5 +1,5 @@
1
- export { DEFAULT_CHART_PALETTE, DEFAULT_VALIDATION_THRESHOLDS, OPFValidationError, assertValid, assertValidCatalogRecord, findValidationRule, validate, validateCatalogRecord, validationCategories, validationRules } from './chunk-PX5AWL7Y.js';
2
- export { promotedRegionKeys } from './chunk-5PDN7BN6.js';
1
+ export { DEFAULT_CHART_PALETTE, DEFAULT_VALIDATION_THRESHOLDS, OPFValidationError, assertValid, assertValidCatalogRecord, findValidationRule, validate, validateCatalogRecord, validationCategories, validationRules } from './chunk-NLNYNBTS.js';
2
+ export { promotedRegionKeys } from './chunk-CW7GEAV3.js';
3
3
  import './chunk-TRDXRRQK.js';
4
4
  import './chunk-SPFV27O5.js';
5
- import './chunk-WEDGVC5W.js';
5
+ import './chunk-RA64UQKI.js';
package/dist/yaml.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { C as Catalog } from './catalog-refs-_anZs-Qz.js';
2
- import { P as Presentation } from './presentation-COrFuj2g.js';
3
- import { V as ValidateOptions, a as ValidationReport } from './validation-types-HxIgJfKx.js';
4
- import { a as Finding, b as FindingLocation } from './finding-CT_f_vbD.js';
5
- import './composition-D4ADF5c-.js';
6
- import './chart-data-BnNqgnC-.js';
1
+ import { b as Catalog } from './catalog-refs-C4K4y-vh.js';
2
+ import { P as Presentation } from './presentation-fb8CZmRq.js';
3
+ import { c as ValidateOptions, f as ValidationReport } from './validation-types-iZbXfES6.js';
4
+ import { F as Finding, d as FindingLocation } from './finding-CDQ_wH8j.js';
5
+ import './composition-BbZ_9C-c.js';
6
+ import './chart-data-DTxdRRT1.js';
7
7
  import './json-BFSdESOE.js';
8
8
 
9
9
  /** A finding located in the YAML source: `yaml/<rule>` syntax and dialect errors (category `format`) and the OPF findings of the parsed deck. */
package/dist/yaml.js CHANGED
@@ -1,9 +1,9 @@
1
- export { OPFYamlError, YAML_SCHEMA_URL, fromYaml, parseYamlData, scanYamlComments, toYaml } from './chunk-K4DQQIT4.js';
2
- import './chunk-5UEUAW57.js';
3
- import './chunk-6OR326EA.js';
4
- import './chunk-5TO6I3GB.js';
5
- import './chunk-PX5AWL7Y.js';
6
- import './chunk-5PDN7BN6.js';
1
+ export { OPFYamlError, YAML_SCHEMA_URL, fromYaml, parseYamlData, scanYamlComments, toYaml } from './chunk-TCD2FB2K.js';
2
+ import './chunk-IS5H5JKH.js';
3
+ import './chunk-YT7FMQER.js';
4
+ import './chunk-PPROJP2E.js';
5
+ import './chunk-NLNYNBTS.js';
6
+ import './chunk-CW7GEAV3.js';
7
7
  import './chunk-TRDXRRQK.js';
8
8
  import './chunk-SPFV27O5.js';
9
- import './chunk-WEDGVC5W.js';
9
+ import './chunk-RA64UQKI.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openpresentation/opf",
3
- "version": "0.16.0",
3
+ "version": "0.17.0",
4
4
  "description": "Canonical Open Presentation Format schemas, TypeScript types, local validation and composition; the pinned default catalog ships as the opt-in @openpresentation/opf/catalog.",
5
5
  "license": "MIT",
6
6
  "author": "Open Presentation",
@@ -115,6 +115,14 @@
115
115
  "./convert": {
116
116
  "types": "./dist/convert.d.ts",
117
117
  "import": "./dist/convert.js"
118
+ },
119
+ "./node": {
120
+ "types": "./dist/node.d.ts",
121
+ "import": "./dist/node.js"
122
+ },
123
+ "./node/engine": {
124
+ "types": "./dist/node-engine.d.ts",
125
+ "import": "./dist/node-engine.js"
118
126
  }
119
127
  },
120
128
  "files": [
@@ -142,9 +150,34 @@
142
150
  "yaml": "^2.9.1"
143
151
  },
144
152
  "devDependencies": {
153
+ "@expo-google-fonts/arimo": "0.4.3",
154
+ "@expo-google-fonts/caladea": "0.4.2",
155
+ "@expo-google-fonts/cousine": "0.4.3",
156
+ "@expo-google-fonts/gelasio": "0.4.1",
157
+ "@expo-google-fonts/noto-sans": "0.4.2",
158
+ "@expo-google-fonts/roboto": "0.4.3",
159
+ "@expo-google-fonts/roboto-mono": "0.4.2",
160
+ "@expo-google-fonts/tinos": "0.4.2",
161
+ "@openpresentation/opf-pptx": "0.16.1",
162
+ "@openpresentation/opf-render": "0.16.0",
163
+ "@resvg/resvg-js": "2.6.2",
145
164
  "@types/node": "^24.13.4",
146
165
  "json-schema-to-typescript": "^16.0.0",
166
+ "pdf-lib": "1.17.1",
167
+ "sharp": "0.35.5",
147
168
  "tsup": "^8.5.1",
148
169
  "typescript": "~5.9.3"
170
+ },
171
+ "peerDependencies": {
172
+ "@openpresentation/opf-pptx": "^0.17.0",
173
+ "@openpresentation/opf-render": "^0.17.0"
174
+ },
175
+ "peerDependenciesMeta": {
176
+ "@openpresentation/opf-pptx": {
177
+ "optional": true
178
+ },
179
+ "@openpresentation/opf-render": {
180
+ "optional": true
181
+ }
149
182
  }
150
183
  }