@openpresentation/opf-pptx 0.24.1 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -322,7 +322,7 @@ LibreOffice is not a runtime dependency. When it is installed in CI or a local v
322
322
  Public npm package publication is handled by `.github/workflows/release.yml` through npm Trusted Publishing (GitHub Actions OIDC) with npm provenance; no npm token is stored. The owner authorized agents to prepare and publish npm releases whenever a release is required (2026-09-29). This authorization does not waive any gate.
323
323
 
324
324
  1. Open a release-prep PR containing only the version bump, `CHANGELOG.md` (assembled from `changes/` with `node scripts/changelog-fragments.mjs assemble --version X.Y.Z`), dependency ranges, lockfile and current-instruction docs. Publish in dependency order (core, then renderer, then PPTX, then editor): refresh this repo's lockfile only after the required `@openpresentation/opf` and `@openpresentation/opf-render` versions are on the registry (`npm install --package-lock-only`), then run `npm run test:packed` against them.
325
- 2. Merge after CI is green, then publish by pushing the git tag `opf-pptx-v<version>` (or `@openpresentation/opf-pptx@v<version>`) at the merge commit. The workflow verifies that the tag matches `package.json` and reruns audit, typecheck, validate, tests, packed and browser checks before `npm publish --access public --provenance`. A manual `workflow_dispatch` runs the same job without the tag check and is a fallback only.
325
+ 2. Merge after CI is green, then publish by pushing the git tag `opf-pptx-v<version>` (or `@openpresentation/opf-pptx@v<version>`) at the merge commit. The workflow verifies that the tag matches `package.json`, that the push-to-`main` run of `ci.yml` on exactly the tagged commit succeeded (`scripts/ci-evidence.mjs`; it fails closed and re-runs no test, RR-100), and the artifact itself (audit, the packed install, `npm pack --dry-run`) before `npm publish --access public --provenance`. A tag pushed while CI still runs fails at the evidence step; re-run the failed job once CI is green. A manual `workflow_dispatch` runs the same job without the tag check and is a fallback only.
326
326
  3. Verify with `npm view @openpresentation/opf-pptx@<version> version gitHead dist.attestations` and, from the core repo, `node scripts/test-pptx-publication.mjs <version> <release-commit> <this-checkout>`. Never republish an existing version.
327
327
 
328
328
  ## Shared dynamic composition
@@ -25,7 +25,7 @@
25
25
  // `layout-changed`). A block read from a placeholder of a region gets a `region` pin when plain binding would put it
26
26
  // elsewhere; content that document provenance restored is never pinned.
27
27
 
28
- import {composeLayoutAreas, composeSlide, layoutTemplate, bindRegions, regionAccepts} from '@openpresentation/opf/composition';
28
+ import {composeLayoutAreas, composeSlide, isLayoutTemplate, layoutTemplate, bindRegions, regionAccepts} from '@openpresentation/opf/composition';
29
29
  import {validateCatalogRecord, catalogRecords, resolveReference} from '@openpresentation/opf';
30
30
  import {gallery} from '@openpresentation/gallery';
31
31
  import {decodeTextTag, encodeTextTag} from './code-provenance.js';
@@ -38,7 +38,7 @@ const LAYOUT_TYPE = 'application/vnd.openxmlformats-officedocument.presentationm
38
38
  const TAGS_TYPE = 'application/vnd.openxmlformats-officedocument.presentationml.tags+xml';
39
39
  const EMU = 9525;
40
40
  // Region placeholder indexes (coordinator decisions on RR-81): a base per placeholder kind plus the region's position among the
41
- // layout's regions of that kind, in the record's `regions` order: `obj` 100, `body` 300, `pic` 500, `chart` 700, `tbl` 900,
41
+ // layout's regions of that kind, in the record's `regions` order (core's reading order of the region list): `obj` 100, `body` 300, `pic` 500, `chart` 700, `tbl` 900,
42
42
  // `media` 1100 (so the first chart region of every layout is 700, its second 701). PowerPoint's Change Layout pairs a slide's
43
43
  // placeholders with the new layout's by `idx`, so only regions of one kind pair (Pillars to Text keeps `obj` with `obj`; a chart
44
44
  // bound to Chart beside's `chart` region never lands in Table beside's `tbl` region, as it did with one sequence for every kind).
@@ -85,7 +85,7 @@ export const bindsObject = (type, object) => (BINDS[type] ?? []).includes(object
85
85
  export function regionIndexes(record, nativeBodyRegion) {
86
86
  const regions = new Map(layoutTemplate(record).regions.map(region => [region.name, region]));
87
87
  const counts = {};
88
- const indexes = Object.fromEntries(Object.keys(record?.regions ?? {}).filter(name => regions.has(name)).map(name => {
88
+ const indexes = Object.fromEntries([...regions.keys()].map(name => {
89
89
  const type = placeholderType(regions.get(name));
90
90
  counts[type] = (counts[type] ?? -1) + 1;
91
91
  return [name, REGION_IDX_BASE[type] + counts[type]];
@@ -119,7 +119,7 @@ export function recordHash(record) {
119
119
  */
120
120
  export function slideTemplate(core) {
121
121
  const record = core?.resolved?.layout, provenance = core?.resolved?.provenance?.layout;
122
- if (!record || !provenance || !Object.hasOwn(record, 'areas')) return undefined;
122
+ if (!record || !provenance || !isLayoutTemplate(record)) return undefined;
123
123
  try { layoutTemplate(record); } catch { return undefined; }
124
124
  return {record, id: provenance.id, group: provenance.group, ...(provenance.source !== undefined ? {source: provenance.source} : {}), reference: provenance.reference, origin: provenance.origin,
125
125
  key: templateKey(provenance)};
@@ -127,7 +127,7 @@ export function slideTemplate(core) {
127
127
 
128
128
  const templateKey = ({group, id, source}) => `${group}\u0000${id}\u0000${source ?? ''}`;
129
129
  function isTemplate(record) {
130
- if (record === null || typeof record !== 'object' || !Object.hasOwn(record, 'areas')) return false;
130
+ if (record === null || typeof record !== 'object' || !isLayoutTemplate(record)) return false;
131
131
  try { layoutTemplate(record); return true; } catch { return false; }
132
132
  }
133
133
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openpresentation/opf-pptx",
3
- "version": "0.24.1",
3
+ "version": "0.25.0",
4
4
  "description": "Pure local OPF to PPTX export and PPTX to OPF import tooling.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -65,8 +65,8 @@
65
65
  },
66
66
  "dependencies": {
67
67
  "@node-projects/jszip": "4.3.0",
68
- "@openpresentation/gallery": "^4.0.0",
69
- "@openpresentation/opf": "^0.24.0",
68
+ "@openpresentation/gallery": "^5.0.0",
69
+ "@openpresentation/opf": "^0.25.0",
70
70
  "@rgrove/parse-xml": "4.2.3",
71
71
  "fast-xml-parser": "^5.8.0",
72
72
  "fflate": "^0.8.3",
@@ -74,7 +74,7 @@
74
74
  "sharp": "0.35.5"
75
75
  },
76
76
  "peerDependencies": {
77
- "@openpresentation/opf-render": "^0.24.1"
77
+ "@openpresentation/opf-render": "^0.25.0"
78
78
  },
79
79
  "peerDependenciesMeta": {
80
80
  "@openpresentation/opf-render": {
@@ -98,7 +98,7 @@
98
98
  "@expo-google-fonts/roboto": "0.4.3",
99
99
  "@expo-google-fonts/roboto-mono": "0.4.2",
100
100
  "@expo-google-fonts/tinos": "0.4.2",
101
- "@openpresentation/opf-render": "0.24.1",
101
+ "@openpresentation/opf-render": "0.25.0",
102
102
  "@resvg/resvg-js": "2.6.2",
103
103
  "esbuild": "0.28.2",
104
104
  "playwright": "1.64.0"