Skip to content

RR-55: core 0.14 names, Findings in Review, fonts handle, core slide context (lockstep) - #116

Merged
michaeljgrimm merged 7 commits into
mainfrom
codex/rr-55-short-verb-api
Oct 7, 2026
Merged

michaeljgrimm merged 7 commits into
mainfrom
codex/rr-55-short-verb-api

Conversation

@michaeljgrimm

@michaeljgrimm michaeljgrimm commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Depends-On: OpenPresentation/opf#423
Depends-On: OpenPresentation/opf-render#150
Depends-On: OpenPresentation/opf-pptx#196

RR-55, the editor part, in lockstep with core 0.14, renderer 0.14 and PPTX 0.14. Old names are deleted: no aliases, no @deprecated, no shims.

Summary

  • One checker. Every edit runs validate(doc, { only: ["format"] }) (no layout is built); rejectInvalid follows valid. editor.validation and the validation of every change, event and snapshot are core's ValidationReport (valid, findings, counts). validateOpfDocument and the session's validate option are removed.
  • Review panel runs the full validate(doc) after 300 ms of quiet (never per keystroke), groups findings by category with severity, applies FindingFix (title, RFC 6902 patch) as one undoable edit, and takes an optional review(presentation, options) => Promise<FindingReport> hook whose findings merge with core's by Finding.source (hosted reviewers such as pptx.dev appear in the same list).
  • One slide context. composeSlide and paginateSlide use core's resolveSlideContext; the editor's own font and theme chain and resolveSlideFonts are deleted. Unknown layout, theme, colour scheme and font-scheme ids fall back and report unresolved-*; none throws.
  • One fonts handle. createCanvasEditor, exportDeck, composeSlide and paginateSlide take the renderer's loadFonts() handle as { fonts }; the font gate is the handle's pending/ensure.
  • PDF font licenses. The PDF now embeds the registry's faces (script faces included) under the same permissive-license rule as the SVG (OFL-1.1, Apache-2.0, MIT, UFL-1.0). A face that fails is given to neither and reported once as export-font-license; if that leaves the converter no face for some text the export rejects with export-fonts-unlicensed.
  • document is presentation in the editor's public API, as in core and PowerPoint.
  • New deckStats(editor) (core stats, neutral facts). Every typeof core.x === "function" feature detection is gone; test/core-features.mjs fails by name when a linked package lacks an import.

Old → new API

Before Now
validateOpfDocument(doc); session.validation = { valid, errors, warnings, result } validate(doc, { only: ["format"] }); session.validation is a ValidationReport (findings, counts)
createEditorSession(input, { validate }) removed ({ rejectInvalid } stays)
OPFEditorError.issues = validator errors = the error findings
runAudit, auditAvailable, getAuditOptions, ReviewReport.diagnostics, audit/<rule> validate from core, getValidateOptions, findings, opf/<rule>; new mergeFindingReports, groupFindings, sortFindings
ReviewFix.label FindingFix.title
resolveSlideFonts(doc, i) resolveSlideContext(doc, i).options.fontFamilies (core)
composeSlide/paginateSlide(i, { textMeasurement }) { fonts }
createFontGate(registry), fonts.run(...) the handle itself; whenFontsReady(fonts, ...)
exportDeck(deck, { renderOptions: { textMeasurement }, fonts: gate, registry }) exportDeck(deck, { fonts })
createCanvasEditor(el, { renderOptions: { textMeasurement }, fonts: gate }) createCanvasEditor(el, { fonts })
createDataContent; PatchError; applyPatchWithInverse().document; convert { document } importData; OPFPatchError; .presentation; { presentation }
checkPptxTypefaces(bytes, { fonts }) checkTypefaces(bytes, { families })
chartOptionsAvailable, numberingAvailable, templatesAvailable, supportsChartTableData, *-unavailable errors removed (a missing export fails at load)
editor.document, snapshot/change/prepare/transfer/restoreState .document, createCanvasEditor({ document }), onRender/onDraft { document }, renderPreview({ document }) presentation in each
autosave key opf-editor/v1/…, record document opf-editor/v2/…, record presentation (an old copy is never read)

Vetoable calls

  • The gate wrapper fontGate(handle) stays internal (non-throwing pending, fonts-unavailable, abort rethrown as is); createFontGate is removed.
  • The Review hook runs on its button unless autoReview: true (hosted reviews can be slow or metered); its findings stay listed, marked out of date, after an edit; an edit during a run drops that run.
  • Per-edit validation is the format category only; the schema inspector runs format + references.
  • Fix limits: any RFC 6902 op below the root, up to 20 operations; stale move/copy sources are refused.
  • The PDF rejects (export-fonts-unlicensed) rather than substituting silently when the license rule leaves no face; when only some faces drop, the PDF is written with the remaining face standing in and export-font-license reports it.
  • Left as is on purpose: the DOM document options (createTextInput, createCatalogSelect, installFindShortcuts, loadImagePixels, cropImagePixels), the missing-document error code, the storage name documents, the persistence option name key, the playground's document-bar/document-name ids, and prose in messages.
  • The pasted-JSON wrapper key accepted by unwrapOpf is now presentation (it was document).

Removed legacy

font-defaults.js (a local copy of core's default font scheme), the old-core test and fixture, all *Available/typeof core.x guards, "installed renderer predates" skip blocks in 5 tests, OPF_REQUIRE_FF08 in two workflows, the slideImageSupported/slideImageDrawn/lazyFaces probes, the dead "painted" mode of rich-input-browser, loadOfficeFontRegistry/loadBrowserFontRegistry calls in the playground build and tests.

Test evidence (local, Node 24, Edge channel)

  • npm test: 48 node tests pass (incl. check:runners, check:changes); npm run typecheck: 179 files, 0 failed; npm run validate: ready; node scripts/published-core-gate.mjs prints the skip notice.
  • scripts/quarantine.mjs run-suite playground: 20 tests pass; run-suite browser: 10 pass.
  • New tests: core-features, slide-context, deck-stats, review-hook-browser (grouping, debounce, hook merge by source, hosted fix undo, out-of-date marking, failing hook, dropped run), export-license-browser (real converter: permissive face embedded; all faces dropped gives export-fonts-unlicensed; bold dropped writes the PDF with regular standing in), plus the PDF license cases in test/export.mjs.
  • Geometry and SVG identity: composeSlide and renderSlideSvg over all 805 slides of the 126 bundled examples, origin/main with published packages vs this branch with the linked ones: 0 geometry differences, 0 SVG differences (48 slides of one Japanese deck fail identically on both: no Meiryo face).

What cannot pass before core 0.14 is published

npm run test:packed (the packed install against published dependencies) is skipped by the opf.requiresUnreleasedCore gate from #114; the field is deleted by the release-prep PR. npm audit and npm ci use the lockfile of 0.13 packages. Every linked-ecosystem step runs against the Depends-On PRs, so a red there is real; a red that needs @openpresentation/opf 0.14 from npm is expected until it is published.

🤖 Generated with Claude Code


Note

High Risk
Wide breaking API and behavioral changes across validation, fonts, export, and persistence; requires coordinated 0.14 ecosystem upgrades and breaks autosave v1 and prior integration patterns.

Overview
RR-55 is a breaking lockstep release with core/renderer/PPTX 0.14: old APIs are removed (no aliases). The editor public surface renames document → presentation everywhere (session, canvas, prepare helpers, autosave v2 keys), and per-edit validation goes through core validate(presentation, { only: ["format"] }) via new checks.js, replacing validateOpfDocument and the old { errors, warnings } shape with ValidationReport / Finding.

The Review panel switches from audit helpers to full validate on idle, applies core FindingFix patches, and optionally merges a hosted review() hook by Finding.source. Composition uses core resolveSlideContext (drops resolveSlideFonts; unresolved design ids diagnose instead of throwing).

Fonts unify on the renderer loadFonts() handle: canvas, export, compose/paginate take { fonts }; createFontGate and separate textMeasurement/registry export options are gone in favor of whenFontsReady. PDF export shares SVG license rules and can fail with export-fonts-unlicensed.

Docs (README, AGENTS.md), changes/rr-55-short-verb-api.md, and dist/ typings/implementations reflect the rename and dropped *Available runtime probes. CI drops OPF_REQUIRE_FF08 now that linked PPTX always runs checkTypefaces.

Reviewed by Cursor Bugbot for commit 572cf94. Configure here.

@cursor

cursor Bot commented Oct 7, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: a46284e7-8b6e-4365-821d-d88b4cf2116c)

michaeljgrimm and others added 7 commits October 7, 2026 00:49
… handle (lockstep with core 0.14)

Session validation runs validate(doc, { only: ["format"] }); the Review panel runs the full validate on a
debounce, groups findings by category and merges an optional hosted reviewer's FindingReport by source.
composeSlide/paginateSlide resolve the slide context with core's resolveSlideContext. createCanvasEditor,
exportDeck, composeSlide and paginateSlide take the renderer's loadFonts() handle as { fonts }; the font
gate is the handle's pending/ensure. Old names and every typeof-core feature detection are removed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
exportDeck gave the fonts handle to svgToPdf, which embeds every face the registry holds whatever its
license. It now gives the converter only the faces the SVG may embed (OFL-1.1, Apache-2.0, MIT, UFL-1.0), as
fontData. A dropped face is reported once as export-font-license; when none is left for some text the PDF
rejects with export-fonts-unlicensed (the converter's error is the cause).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
editor.presentation (was editor.document), the presentation of every snapshot, change, prepare result,
transfer and restoreState state, the presentation option of createCanvasEditor and the presentation handed
to onRender, onDraft, onCommit and the template preview. A DOM document option stays. The autosave record
holds presentation (record version 2, key prefix opf-editor/v2/).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… rule ids)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…urement only

- Test fixes for the FA tests under the RR-55 names (renderSlideSvg, /composition imports, full validate with rule ids for the
  content and layout rules, presentation fields); core-features also scans test imports.
- Remove the duplicate opf.requiresUnreleasedCore key FA already carries; fix two bare document references left in FA code.
- A preview (canvas, thumbnails, panel previews) hands the renderer only the fonts handle's text measurement: the full handle
  lists embeddedFonts, which the renderer writes into every SVG, and the playground's preview SVG grew from 2 KB to 12.7 MB
  (three times slower clicks, timeouts in the browser suites). test/preview-fonts.mjs covers it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@michaeljgrimm
michaeljgrimm force-pushed the codex/rr-55-short-verb-api branch from 3f89734 to 572cf94 Compare October 7, 2026 07:49
@cursor

cursor Bot commented Oct 7, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: add8732d-5e25-4ffc-9929-2bbd4244a971)

@michaeljgrimm
michaeljgrimm merged commit 7ed7ea5 into main Oct 7, 2026
5 checks passed
michaeljgrimm added a commit that referenced this pull request Oct 8, 2026
#132)

* RR-61: canvas and previews draw with the fonts handle and embedFonts: false

Closes #129. opf-render's RR-61 (opf-render#165) embeds only the faces
a slide draws and adds embedFonts: false. The canvas and the playground
previews now pass the full handle with embedFonts: false instead of the
internal previewFonts helper (measurement only, #116): the browser
handle already added the faces to the page, so the SVGs carry no
@font-face data. Exports keep the default and embed the faces each
slide draws. canvas-fonts-browser asserts the canvas SVG embeds no face.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* RR-61: rebuilt dist (canvas and font-gate without previewFonts)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

full-ci Also run the full CI matrix on this PR (macOS, Windows, Node 22 and 26 legs)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant