From 288af8c19ac0649d2e65e4e54b9df7cbdcf8eec5 Mon Sep 17 00:00:00 2001 From: Caio Pizzol <97641911+caio-pizzol@users.noreply.github.com> Date: Tue, 7 Jul 2026 19:21:40 -0300 Subject: [PATCH 1/8] feat(oss-sync): direct-merge community PR lane with Orbit backflow (#367) * feat(oss-sync): direct-merge community PR lane with Orbit backflow * fix: address PR review comments on #367 * fix: address PR review comments on #367 * fix: address PR review comments on #367 * fix: address PR review comments on #367 * fix: address PR review comments on #367 * feat(oss-sync): direct-merge community PR lane with Orbit backflow * fix: address PR review comments on #367 * fix(oss-sync): reject multi-parent commits in community provenance merge_commit_sha is set for merge-commit and rebase landings too, so it cannot prove a squash. A multi-parent commit now fails the community provenance check before any API lookup, closing the case where a PR whose branch commits carry allowlisted bot emails would ingest wholesale through the email check. * fix(oss-sync): fail closed when community commit parent shape is unknown classifyOssCommits is exported; a caller that omits parents must not skip the squash-shape guard and fall through to PR verification. Note: this ports only the public subtree changes from a mixed source commit (1 public path, 6 non-public paths ignored). Ported-From-Source-Repo: superdoc/orbit Ported-From-Source-Commit: cf57303e95dfe17a533ee35586036e29de6e5ba2 Ported-Public-Prefix: superdoc/public --- .../workflows/dispatch-oss-push-to-orbit.yml | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 .github/workflows/dispatch-oss-push-to-orbit.yml diff --git a/.github/workflows/dispatch-oss-push-to-orbit.yml b/.github/workflows/dispatch-oss-push-to-orbit.yml new file mode 100644 index 0000000000..7c1318d7a0 --- /dev/null +++ b/.github/workflows/dispatch-oss-push-to-orbit.yml @@ -0,0 +1,46 @@ +name: "SuperDoc: Dispatch OSS Push To Orbit" + +on: + push: + branches: [main] + +permissions: + contents: read + +concurrency: + group: superdoc-oss-push-orbit-dispatch-${{ github.ref_name }} + cancel-in-progress: false + +jobs: + dispatch: + name: Dispatch OSS push backflow to Orbit + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Create Orbit dispatch App token + id: orbit-token + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ secrets.ORBIT_DISPATCH_APP_ID }} + private-key: ${{ secrets.ORBIT_DISPATCH_APP_PRIVATE_KEY }} + owner: superdoc + repositories: orbit + + - name: Dispatch OSS backflow to Orbit + env: + AFTER_SHA: ${{ github.sha }} + GH_TOKEN: ${{ steps.orbit-token.outputs.token }} + run: | + set -euo pipefail + gh api repos/superdoc/orbit/dispatches \ + -f event_type=superdoc-oss-backflow \ + -F client_payload[repository]="$GITHUB_REPOSITORY" \ + -F client_payload[ref]="$GITHUB_REF_NAME" \ + -F client_payload[after]="$AFTER_SHA" + + { + echo "### Orbit OSS push backflow dispatched" + echo "" + echo "- ref: \`$GITHUB_REF_NAME\`" + echo "- after: \`$AFTER_SHA\`" + } >> "$GITHUB_STEP_SUMMARY" From 276e0a9f3adbd4fe3f5dd550a91844d8ebe96794 Mon Sep 17 00:00:00 2001 From: Dmitro Bilukha Date: Wed, 8 Jul 2026 02:51:41 +0300 Subject: [PATCH 2/8] fix(super-editor): declare full namespace set on freshly-created numbering.xml (#3792) * fix(super-editor): declare full namespace set on freshly-created numbering.xml (GH #3773) Importing a docx with no word/numbering.xml and then adding the first numbered list produced a numbering part missing xmlns:w16cid (and other w16* namespaces), so Word refused to open/repair the exported file. numbering-part-descriptor.ts's ensurePart() hand-maintained a 3-key namespace map (xmlns:w/w15/mc) instead of reusing DEFAULT_DOCX_DEFS, the full namespace + mc:Ignorable map that document.xml, comments.xml, footnotes.xml, and people.xml already apply unconditionally. Since every numbering-part creation goes through this ensurePart() (mutateNumbering -> mutatePart -> executeMutate), the legacy SuperConverter#exportNumberingFile baseNumbering fallback never runs for this path - the part descriptor's own map has to be complete on its own. Reuses DEFAULT_DOCX_DEFS instead of hand-picking namespaces one bug report at a time. Adds a unit test on ensurePart() and an end-to-end regression test (import numbering-less blank-doc.docx -> toggleOrderedList -> export -> assert namespace-complete root). Relaxes one templates-adapter.integration.test.ts assertion that hardcoded the old narrow mc:Ignorable merge result to match the sibling styles.xml test's existing flexible pattern. Co-Authored-By: Claude Sonnet 5 * docs(super-editor): correct w16cid provenance in numbering root attrs comment --------- Co-authored-by: d.bilukcha Co-authored-by: Claude Sonnet 5 Co-authored-by: Caio Pizzol <97641911+caio-pizzol@users.noreply.github.com> --- .../numbering-part-descriptor.test.ts | 12 +++++ .../adapters/numbering-part-descriptor.ts | 20 ++++---- .../templates-adapter.integration.test.ts | 2 +- .../numbering-namespace-on-first-list.test.js | 51 +++++++++++++++++++ 4 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 packages/super-editor/src/editors/v1/tests/import-export/numbering-namespace-on-first-list.test.js diff --git a/packages/super-editor/src/editors/v1/core/parts/adapters/numbering-part-descriptor.test.ts b/packages/super-editor/src/editors/v1/core/parts/adapters/numbering-part-descriptor.test.ts index 0c96028ea6..407815b93a 100644 --- a/packages/super-editor/src/editors/v1/core/parts/adapters/numbering-part-descriptor.test.ts +++ b/packages/super-editor/src/editors/v1/core/parts/adapters/numbering-part-descriptor.test.ts @@ -13,6 +13,18 @@ describe('numberingPartDescriptor.ensurePart', () => { expect(root.attributes['xmlns:mc']).toBe('http://schemas.openxmlformats.org/markup-compatibility/2006'); expect(root.attributes['mc:Ignorable']).toContain('w15'); }); + + it('declares xmlns:w16cid so freshly-created numbering parts are namespace-valid (GH #3773)', () => { + const part = numberingPartDescriptor.ensurePart() as { + elements: Array<{ attributes: Record }>; + }; + const root = part.elements[0]; + + expect(root.attributes['xmlns:w16cid']).toBe('http://schemas.microsoft.com/office/word/2016/wordml/cid'); + expect(root.attributes['xmlns:w14']).toBe('http://schemas.microsoft.com/office/word/2010/wordml'); + expect(root.attributes['xmlns:r']).toBe('http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + expect(root.attributes['mc:Ignorable']).toContain('w16cid'); + }); }); describe('syncNumberingToXmlTree', () => { diff --git a/packages/super-editor/src/editors/v1/core/parts/adapters/numbering-part-descriptor.ts b/packages/super-editor/src/editors/v1/core/parts/adapters/numbering-part-descriptor.ts index 8805691c80..9a50e27cce 100644 --- a/packages/super-editor/src/editors/v1/core/parts/adapters/numbering-part-descriptor.ts +++ b/packages/super-editor/src/editors/v1/core/parts/adapters/numbering-part-descriptor.ts @@ -13,6 +13,7 @@ import type { Editor } from '../../Editor.js'; import type { PartDescriptor } from '../types.js'; import { translator as wAbstractNumTranslator } from '../../super-converter/v3/handlers/w/abstractNum/index.js'; import { translator as wNumTranslator } from '../../super-converter/v3/handlers/w/num/index.js'; +import { DEFAULT_DOCX_DEFS } from '../../super-converter/exporter-docx-defs.js'; import { isPartCacheStale, clearPartCacheStale } from '../cache-staleness.js'; const NUMBERING_PART_ID = 'word/numbering.xml' as const; @@ -20,16 +21,17 @@ const NUMBERING_PART_ID = 'word/numbering.xml' as const; /** * Namespace attributes for the `` root element. * - * Includes `xmlns:w15` because base list definitions use - * `w15:restartNumberingAfterBreak` — without this declaration the - * numbering part is namespace-invalid and Word shows a repair prompt. + * Reuses the same full namespace + `mc:Ignorable` map that document.xml, + * comments.xml, footnotes.xml, and people.xml apply unconditionally + * (`DEFAULT_DOCX_DEFS`), instead of hand-picking a subset. A prior version + * of this map declared only `xmlns:w`/`xmlns:w15`/`xmlns:mc`, which was + * enough for `w15:restartNumberingAfterBreak` but omitted `xmlns:w16cid` + * (used by the seeded base numbering definitions, e.g. `w16cid:durableId` + * on `w:num`) — Word flagged any docx where this part was freshly created + * (i.e. the source docx had no numbering.xml before the user added their + * first list) as unreadable and forced a repair pass. See GH #3773. */ -const NUMBERING_ROOT_ATTRS: Record = { - 'xmlns:w': 'http://schemas.openxmlformats.org/wordprocessingml/2006/main', - 'xmlns:w15': 'http://schemas.microsoft.com/office/word/2012/wordml', - 'xmlns:mc': 'http://schemas.openxmlformats.org/markup-compatibility/2006', - 'mc:Ignorable': 'w15', -}; +const NUMBERING_ROOT_ATTRS: Record = { ...DEFAULT_DOCX_DEFS }; // --------------------------------------------------------------------------- // Converter shape (minimal interface to avoid importing SuperConverter) diff --git a/packages/super-editor/src/editors/v1/document-api-adapters/templates/templates-adapter.integration.test.ts b/packages/super-editor/src/editors/v1/document-api-adapters/templates/templates-adapter.integration.test.ts index 7f7a657625..cda30a3e8d 100644 --- a/packages/super-editor/src/editors/v1/document-api-adapters/templates/templates-adapter.integration.test.ts +++ b/packages/super-editor/src/editors/v1/document-api-adapters/templates/templates-adapter.integration.test.ts @@ -278,7 +278,7 @@ describe('templates.apply adapter integration', () => { expect(numberingXml).toContain('xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml"'); expect(numberingXml).toContain('xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid"'); expect(numberingXml).toContain('xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"'); - expect(numberingXml).toContain('mc:Ignorable="w15 w14 w16cid"'); + expect(numberingXml).toMatch(/mc:Ignorable="[^"]*\bw16cid\b/); expect(numberingXml).toContain('w15:restartNumberingAfterBreak="0"'); expect(numberingXml).toContain('w16cid:durableId="123456789"'); }); diff --git a/packages/super-editor/src/editors/v1/tests/import-export/numbering-namespace-on-first-list.test.js b/packages/super-editor/src/editors/v1/tests/import-export/numbering-namespace-on-first-list.test.js new file mode 100644 index 0000000000..4767759ff8 --- /dev/null +++ b/packages/super-editor/src/editors/v1/tests/import-export/numbering-namespace-on-first-list.test.js @@ -0,0 +1,51 @@ +import { describe, it, expect } from 'vitest'; +import { dirname, join } from 'path'; +import { fileURLToPath } from 'node:url'; +import { promises as fs } from 'fs'; +import { Editor } from '@core/Editor.js'; +import DocxZipper from '@core/DocxZipper.js'; +import { parseXmlToJson } from '@converter/v2/docxHelper.js'; +import { initTestEditor } from '../helpers/helpers.js'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +const findNumberingRoot = (json) => { + if (!json?.elements?.length) return null; + if (json.elements[0]?.name === 'w:numbering') return json.elements[0]; + return json.elements.find((el) => el?.name === 'w:numbering') || null; +}; + +// GH #3773: a docx imported with no `word/numbering.xml` (blank-doc.docx has none — +// see the SD-2911 P2 sanity test) that then gets its first numbered list added via +// `toggleOrderedList` must still export a namespace-complete `` root. +// The part is created on-the-fly by the parts system (numbering-part-descriptor.ts) +// mid-session, so the legacy `baseNumbering` export-time fallback never runs for it — +// the part descriptor's own namespace map has to be complete on its own. +describe('numbering.xml namespaces when the first list is added to a numbering-less doc (GH #3773)', () => { + it('emits the full namespace set (including xmlns:w16cid) on the freshly-created numbering part', async () => { + const docxPath = join(__dirname, '../data', 'blank-doc.docx'); + const docxBuffer = await fs.readFile(docxPath); + + const [docx, media, mediaFiles, fonts] = await Editor.loadXmlData(docxBuffer, true); + const { editor } = await initTestEditor({ content: docx, media, mediaFiles, fonts, isHeadless: true }); + + editor.commands.insertContent('First item'); + editor.commands.toggleOrderedList(); + + const exportedBuffer = await editor.exportDocx({ isFinalDoc: false }); + const exportedZipper = new DocxZipper(); + const exportedFiles = await exportedZipper.getDocxData(exportedBuffer, true); + const exportedNumberingEntry = exportedFiles.find((entry) => entry.name === 'word/numbering.xml'); + + expect(exportedNumberingEntry, 'export must contain word/numbering.xml').toBeDefined(); + + const exportedRoot = findNumberingRoot(parseXmlToJson(exportedNumberingEntry.content)); + + expect(exportedRoot.attributes['xmlns:w16cid']).toBe('http://schemas.microsoft.com/office/word/2016/wordml/cid'); + expect(exportedRoot.attributes['xmlns:w14']).toBe('http://schemas.microsoft.com/office/word/2010/wordml'); + expect(exportedRoot.attributes['xmlns:r']).toBe( + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships', + ); + expect(exportedRoot.attributes['mc:Ignorable']).toContain('w16cid'); + }); +}); From 1e1559c697678d9c38718a8573e142f416eebdf2 Mon Sep 17 00:00:00 2001 From: "superdoc-bot[bot]" <235763992+superdoc-bot[bot]@users.noreply.github.com> Date: Tue, 7 Jul 2026 21:02:54 -0300 Subject: [PATCH 3/8] docs: add MIt9 to community contributors (#3810) Co-authored-by: github-actions[bot] --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1247e22d5a..dcdfbac66d 100644 --- a/README.md +++ b/README.md @@ -186,6 +186,7 @@ Special thanks to these community members who have contributed code to SuperDoc: wookieb xy200303 garhm +MIt9 Want to see your avatar here? Check the [Contributing Guide](CONTRIBUTING.md) to get started. From cfa9f9dd5d90950d6d40c7eab18a8aaf020e4234 Mon Sep 17 00:00:00 2001 From: Caio Pizzol <97641911+caio-pizzol@users.noreply.github.com> Date: Tue, 7 Jul 2026 21:24:46 -0300 Subject: [PATCH 4/8] fix(oss-ci): install bun in React workflow Install Bun in the public React CI workflow so SDK contract generation can run during type checks. Note: this ports only the public subtree changes from a mixed source commit (1 public path, 1 non-public path ignored). Ported-From-Source-Repo: superdoc/orbit Ported-From-Source-Commit: ac0394983c4c153163d3ca1baa54e056aa59da2b Ported-Public-Prefix: superdoc/public --- .github/workflows/ci-react.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci-react.yml b/.github/workflows/ci-react.yml index 19dc952bd9..dc5e884c9a 100644 --- a/.github/workflows/ci-react.yml +++ b/.github/workflows/ci-react.yml @@ -27,6 +27,10 @@ jobs: node-version-file: .nvmrc cache: pnpm + - uses: oven-sh/setup-bun@v2 + with: + bun-version: 1.3.13 + - name: Install dependencies run: pnpm install From 1b51f77a5f3860379491f3b29bca980a52db6439 Mon Sep 17 00:00:00 2001 From: "superdoc-bot[bot]" <235763992+superdoc-bot[bot]@users.noreply.github.com> Date: Tue, 7 Jul 2026 21:34:05 -0300 Subject: [PATCH 5/8] =?UTF-8?q?=F0=9F=94=84=20Sync=20stable=20=E2=86=92=20?= =?UTF-8?q?main=20(#3809)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(cli): 0.17.0 [skip ci] Based on the commit messages, here are the release notes: ### What's New - **Textbox editing** — Edit text content inside VML and DrawingML textboxes with full interaction support; clicks map to content positions. - **Font family combobox** — Browse and select fonts directly from the toolbar. - **Font size options** — UI API exposes font size choices for custom toolbars. - **Comments API expansion** — `ui.comments.setActive()` highlights a comment without scrolling; pending-comments-update event carries `pendingSelection`. - **Viewport scroll container** — `ui.viewport.getScrollContainer()` returns the editor's resolved scroll element. - **Text range viewport geometry** — `ui.viewport.getRect()` now accepts Document API text addresses and targets. - **Sidebar viewport observation** — `ui.viewport.observe` fires when comments rail opens or closes. - **Zoom modes** — Manual and fit-width zoom with observable transitions, viewport metrics, `useSuperDocZoom` React hook, and toolbar command. - **Table of contents hover** — Hovering TOC entries highlights corresponding sections. ### Improvements - **Multi-column section balancing** — Continuous sections balance correctly with explicit per-column widths preserved throughout layout. - **Column spacing precision** — Per-column gaps drive separator positions per ECMA-376; unequal-width columns honor per-column `w:space`. - **Font substitutes** — Metric-compatible fallbacks load for Calibri, Cambria, Arial, Times New Roman, and Courier New before measurement. - **Tracked table changes** — Inline cell edits consolidate into single review items instead of separate entries. ### Fixes - Paragraphs with pageBreakBefore style no longer add blank pages when directly following explicit page breaks. - Textbox text alignment matches Word when tables are inside textboxes. - Table cell selection highlights appear over empty space; multiline selection interior lines render at full width. - Plan engine recovers from stale block identities on recompile without crashes. - Tab carets anchor to line top instead of bottom; soft-break continuation carets position alignment-aware at line start. - DOCX export preserves generated line breaks as `` elements instead of raw newlines. - Font toolbar no longer races on editor handoff; combobox selection flow handles edge cases. - Viewport geometry invalidates on sidebar toggle without px-level jitter. - Zoom state — PDF documents contribute to viewport metrics; mode-only transitions emit correctly. - TOC anchor navigation preserves bookmark start/end order. - Image alpha modifiers process correctly on import and export. - Font picker keyboard behavior consistent across selection modes. - Formatting preserved when typing text over toolbar font selections. * chore(sdk): 1.16.0 [skip ci] ### What's New - **Textbox editing** — Edit text content inside VML and DrawingML textboxes; clicks map to content positions with full interaction support. - **Font family combobox** — Browse and select fonts directly from the toolbar. - **Font size options** — UI API exposes font size choices for custom toolbars. - **Comments API: activate-only highlight** — `ui.comments.setActive()` marks a comment active without scrolling. - **Pending selection on comments event** — `pending-comments-update` event carries `pendingSelection` captured before the live selection clears. - **Scroll container getter** — `ui.viewport.getScrollContainer()` returns the editor's resolved scroll element for overlay consumers. - **Text range viewport geometry** — `ui.viewport.getRect()` accepts Document API text addresses and targets, not just entities. - **Sidebar viewport observation** — `ui.viewport.observe` fires when the comments rail opens or closes. - **Zoom modes** — Manual and fit-width zoom with observable mode transitions, viewport metrics, `useSuperDocZoom` React hook, and toolbar command. - **Table of contents hover** — Hovering TOC entries highlights corresponding sections in the document. ### Improvements - **Multi-column section balancing** — Continuous sections balance correctly with explicit per-column widths preserved throughout layout. - **Column spacing precision** — Per-column gaps drive separator positions per ECMA-376; unequal-width columns honor per-column `w:space`. - **Font substitutes** — Metric-compatible fallbacks load for Calibri, Cambria, Arial, Times New Roman, and Courier New before measurement; no reflow. - **Tracked table changes** — Inline cell edits consolidate into single review items instead of separate entries. ### Fixes - Paragraphs with `pageBreakBefore` style no longer add blank pages when directly following explicit page breaks. - Textbox text alignment now matches Word when tables are inside textboxes. - Table cell selection highlights appear over empty space; multiline selection interior lines render at full width. - Plan engine recovers from stale block identities on recompile without crashes. - Tab carets anchor to line top instead of bottom; soft-break continuation carets position alignment-aware at line start. - DOCX export preserves generated line breaks as `` elements instead of raw newlines. - Font toolbar no longer races on editor handoff; combobox selection flow handles edge cases. - Viewport geometry invalidates on sidebar toggle without px-level jitter. - Zoom state — PDF documents contribute to viewport metrics; mode-only transitions emit correctly. - TOC anchor navigation preserves bookmark start/end order. - Image alpha modifiers process correctly on import and export. - Font picker keyboard behavior consistent across selection modes. - Formatting preserved when typing text over toolbar font selections. * chore(mcp): 0.12.0 [skip ci] ### What's New - **Textbox editing** — Click, type, and select text directly inside VML and DrawingML textboxes; full caret and selection support. - **Font family combobox** — Browse and select fonts from the toolbar; font selection flows through custom UI. - **Font size API** — `ui.viewport` exposes available font sizes for custom toolbars and programmatic queries. - **Comments API: activate-only highlight** — `ui.comments.setActive()` marks a comment active without scrolling or moving selection. - **Pending selection on comment events** — `pending-comments-update` event carries `pendingSelection` captured before the live DOM selection clears. - **Scroll container access** — `ui.viewport.getScrollContainer()` returns the editor's resolved scroll element for overlay consumers. - **Text range viewport geometry** — `ui.viewport.getRect()` now accepts Document API text addresses and targets, not just entities. - **Sidebar viewport observation** — `ui.viewport.observe` fires when the comments rail opens or closes. - **Zoom modes** — Manual and fit-width zoom modes with observable transitions, viewport metrics, `useSuperDocZoom` React hook, and toolbar command. - **Table of contents hover** — Hovering TOC entries highlights corresponding document sections. ### Improvements - **Multi-column section balancing** — Continuous sections now balance correctly; explicit per-column widths preserved throughout layout. - **Column spacing precision** — Per-column gaps drive separator positions per ECMA-376; unequal-width columns honor per-column `w:space` values. - **Font substitutes load before measurement** — Metric-compatible fallbacks for Calibri, Cambria, Arial, Times New Roman, and Courier New load upfront; no reflow. - **Tracked table changes consolidation** — Inline cell edits fold into a single review item instead of separate entries; one decision applies to the whole table. ### Fixes - Paragraphs styled with `pageBreakBefore` no longer insert blank pages when directly following explicit page breaks. - Textbox text alignment now matches Word behavior when tables are nested inside textboxes. - Table cell selection highlights render over empty space; multiline selections show full-width interior lines. - Plan engine recovers from stale block identities on recompile without crashes. - Tab carets anchor to line top (not bottom); soft-break continuation carets position at line start with alignment-aware offset. - DOCX export preserves generated line breaks as `` elements instead of raw newlines. - Font toolbar no longer races on editor handoff; combobox selection handles edge cases correctly. - Viewport geometry invalidates on sidebar toggle without pixel-level jitter. - Zoom state — PDF documents contribute to viewport metrics; mode-only transitions emit correctly. - TOC anchor navigation preserves `bookmarkStart`/`bookmarkEnd` order. - Image alpha modifiers process correctly on import and export. - Font picker keyboard behavior consistent across selection modes. - Formatting is preserved when typing text over a toolbar font selection. * chore(release): 1.40.0 [skip ci] Now I have enough context. Let me write the release notes based on the actual changes: ### What's New - **Textbox content editing** — Click, type, and edit text inside VML and DrawingML textboxes. Selection, caret rendering, and text updates work across body, header/footer, and table cell contexts. - **Zoom modes and fit-width** — Set zoom as `manual` or `fit-width` (auto-fit to container). `ui.zoom` exposes mode, value, calculated fit-zoom, bounds, and viewport metrics; PDF documents measure at their rendered scale. - **Viewport metrics and responsive layout events** — `viewport-change` event fires on container resize with measurements (document width, available width, fit-zoom). Consume viewport metrics from `getViewportMetrics()` to implement responsive zoom without polling. - **Font family combobox** — Typeahead-enabled font picker in toolbar with per-document font options and substitution evidence (metric-safe vs. visual-only); dropdown stays in viewport. - **Comments API expansion** — `ui.comments.setActive()` highlights a comment without scrolling; `pendingSelection` on pending comment events gives consumers the captured selection to pass to comment creation APIs. - **Text range viewport targets** — `ui.viewport.getRect()` now accepts Document API text targets (addresses and segments), resolving to painted DOM rects for custom overlay and floating-UI anchoring. - **Scroll container exposure** — `ui.viewport.getScrollContainer()` returns the actual scrollable ancestor (or null for document/window scroll), letting overlay consumers attach scroll listeners to the right element. - **Sidebar geometry signals** — `ui.viewport.observe` fires when the comments rail opens/closes, invalidating cached viewport geometry. - **TOC interactions** — Hover highlighting and section-link navigation for table of contents. ### Improvements - **Column balancing at continuous breaks** — Multi-column sections now balance correctly at continuous section breaks, matching Word's layout. Explicit column widths (equal or unequal) and per-column spacing extract accurately. - **Tracked change granularity** — Inline cell changes within a whole-table tracked change consolidate into one logical change in the review API (groupTrackedChanges), mirroring the comments containment rule. - **Line break handling in mutations** — Generated newlines in text-mode mutations serialize as Word-native `` elements; read model treats lineBreak nodes as `\n` so search/query/rewrite stay consistent. - **Caret geometry for tabs and soft breaks** — Tab carets anchor to line top; soft-break continuation carets position at line start with alignment-aware offset instead of the page right edge. - **Page break suppression** — Style-driven pageBreakBefore directly after an explicit page break no longer renders a redundant blank page, matching Word's structural rule. - **Textbox table content rendering** — Tables inside textboxes render with correct alignment and text flow. - **Plan-engine block identity repair** — Runtime self-healing of duplicate block identities on compile, preventing stale cross-document references. - **Font substitution evidence** — Font reports carry per-face evidence (metric-safe, visual-only, glyph exceptions) from the docfonts registry, giving consumers the fidelity detail behind each substitution. ### Fixes - **Table cell selection collapse** — Dragging a body selection into an empty table cell no longer collapses the selection; prosemirror-tables normalization guard keeps the extended range. - **Multiline selection rendering** — Interior lines of multi-line selections now render the full width highlight instead of slivers; per-line rect computation handles absolutely-positioned `.superdoc-line` elements across browsers. - **Empty cell geometry** — Empty table cell paragraphs (no runs) resolve to their PM start instead of null, preventing frozen selections during active drags. - **Image alpha export** — Process alphaModFix for images on export, preserving transparency properties. - **Text selection in generated lineBreak contexts** — Search and offset resolution now treat lineBreak nodes as `\n`, so a match spanning text+lineBreak+text coalesces to one contiguous range. - **Font toolbar updates** — Document font toolbar rebuilds and layout re-renders on fonts-changed events; dropdown state persists through editor handoff. - **UV-deprecated legacy visual testing infrastructure** — Removed `/devtools/visual-testing`; layout validation now runs in the standard test suite. * chore(react): 1.11.0 [skip ci] ### What's New - **Textbox content editing** — Click to edit text inside textboxes in body, headers, footers, and table cells with full selection and caret support. - **Zoom modes and fit-width** — Choose zoom mode (`manual` or `fit-width` for auto-fit) and read state, calculations, bounds, and viewport metrics from `ui.zoom`. - **Viewport change events** — Listen for `viewport-change` when the container resizes to receive document width, available width, and calculated fit-zoom. - **Font family combobox** — Search for fonts in the toolbar by name and see per-document options with substitution evidence. - **Comments activation API** — Highlight comments without scrolling using `ui.comments.setActive()`, and access the captured selection from pending comment events. - **Text range viewport rects** — Pass Document API text targets to `ui.viewport.getRect()` to get painted rects for overlay positioning. - **Scroll container access** — Call `ui.viewport.getScrollContainer()` to find the element that actually scrolls, or null for window scroll. - **Sidebar geometry updates** — `ui.viewport.observe` fires when the comments rail opens or closes. - **TOC interactions** — Hover highlights sections in the table of contents, and click navigates to them. ### Improvements - **Column balancing** — Multi-column sections balance at continuous section breaks, matching Word's behavior. - **Grouped tracked changes** — Inline cell changes inside a whole-table tracked change now group as one review item. - **Line break serialization** — Newlines in text mutations serialize as `` and round-trip without loss. - **Tab and soft-break carets** — Tab carets anchor to line top, and soft-break carets position at line start with alignment awareness. - **Page break suppression** — Removed blank pages when `pageBreakBefore` appears directly after an explicit page break. - **Textbox table rendering** — Tables inside textboxes render with correct alignment and text flow. - **Block identity repair** — Duplicate block identities fix automatically on compile. - **Font substitution evidence** — Font reports carry per-face evidence (metric-safe, visual-only, glyph exceptions). ### Fixes - **Empty table cell selection** — Dragging a selection into an empty cell no longer collapses. - **Multiline selection rendering** — Interior lines of multi-line selections render full-width highlights. - **Empty cell geometry** — Empty cell paragraphs resolve to a valid position for interaction. - **Image alpha on export** — Images with transparency now preserve alpha on DOCX export. - **Linebreak text selection** — Search spans and selections spanning text+linebreak+text now coalesce correctly. - **Font toolbar updates** — Toolbar rebuilds when document fonts change or editor switches. * chore(vscode): 2.12.0 [skip ci] ### What's New - **Textbox content editing** — Click, type, and edit text inside VML and DrawingML textboxes. Selection, caret rendering, and text updates work across body, header/footer, and table cell contexts. - **Zoom modes and fit-width** — Set zoom as `manual` or `fit-width` (auto-fit to container). `ui.zoom` exposes mode, value, calculated fit-zoom, bounds, and viewport metrics; PDF documents measure at their rendered scale. - **Viewport metrics and responsive layout events** — `viewport-change` event fires on container resize with measurements (document width, available width, fit-zoom). Consume viewport metrics from `getViewportMetrics()` to implement responsive zoom without polling. - **Font family combobox** — Typeahead-enabled font picker in toolbar with per-document font options and substitution evidence (metric-safe vs. visual-only); dropdown stays in viewport. - **Comments API expansion** — `ui.comments.setActive()` highlights a comment without scrolling; `pendingSelection` on pending comment events gives consumers the captured selection to pass to comment creation APIs. - **Text range viewport targets** — `ui.viewport.getRect()` now accepts Document API text targets (addresses and segments), resolving to painted DOM rects for custom overlay and floating-UI anchoring. - **Scroll container exposure** — `ui.viewport.getScrollContainer()` returns the actual scrollable ancestor (or null for document/window scroll), letting overlay consumers attach scroll listeners to the right element. - **Sidebar geometry signals** — `ui.viewport.observe` fires when the comments rail opens/closes, invalidating cached viewport geometry. - **Table of contents interactions** — Hover highlighting and section-link navigation for table of contents. ### Improvements - **Column balancing at continuous breaks** — Multi-column sections now balance correctly at continuous section breaks, matching Word's layout. Explicit column widths (equal or unequal) and per-column spacing extract accurately. - **Tracked change granularity** — Inline cell changes within a whole-table tracked change consolidate into one logical change in the review API, mirroring the comments containment rule. - **Line break handling in mutations** — Generated newlines in text-mode mutations serialize as Word-native `` elements; read model treats lineBreak nodes as `\n` so search/query/rewrite stay consistent. - **Caret geometry for tabs and soft breaks** — Tab carets anchor to line top; soft-break continuation carets position at line start with alignment-aware offset instead of the page right edge. - **Page break suppression** — Style-driven pageBreakBefore directly after an explicit page break no longer renders a redundant blank page, matching Word's structural rule. - **Textbox table content rendering** — Tables inside textboxes render with correct alignment and text flow. - **Plan-engine block identity repair** — Runtime self-healing of duplicate block identities on compile, preventing stale cross-document references. - **Font substitution evidence** — Font reports carry per-face evidence (metric-safe, visual-only, glyph exceptions) from the docfonts registry, giving consumers the fidelity detail behind each substitution. ### Fixes - **Table cell selection collapse** — Dragging a body selection into an empty table cell no longer collapses the selection; prosemirror-tables normalization guard keeps the extended range. - **Multiline selection rendering** — Interior lines of multi-line selections now render the full width highlight instead of slivers; per-line rect computation handles absolutely-positioned `.superdoc-line` elements across browsers. - **Empty cell geometry** — Empty table cell paragraphs (no runs) resolve to their ProseMirror start instead of null, preventing frozen selections during active drags. - **Image alpha export** — Process alphaModFix for images on export, preserving transparency properties. - **Text selection in generated lineBreak contexts** — Search and offset resolution now treat lineBreak nodes as `\n`, so a match spanning text+lineBreak+text coalesces to one contiguous range. - **Font toolbar updates** — Document font toolbar rebuilds and layout re-renders on fonts-changed events; dropdown state persists through editor handoff. * chore(esign): 2.7.2 [skip ci] Based on my analysis of the commits and changes, here are the release notes: ### Fixes - **Page breaks** — Removed redundant blank pages when a paragraph with pageBreakBefore style follows an explicit page break. Word's rule is structural, not geometric; we now match that behavior exactly. - **Table cell selection** — Fixed selection highlight disappearing over empty space inside table cells. Also fixed multiline selection rendering and empty cell hit detection. - **Textbox rendering** — Corrected rendering and text alignment for textboxes containing tables. - **Image alpha transparency** — Process `alphaModFix` attributes correctly during import and export to preserve image transparency settings. - **Block identity repair** — Runtime self-healing for duplicate block identities on compile, preventing stale references from breaking document operations. ### What's New - **Textbox editing** — Phase 0 and 1 of textbox content editing. Render and edit VML and DrawingML textbox content. Full support for textboxes in headers, footers, and table cells with proper position preservation through import/export. ### Improvements - **Font system** — Bundle docfonts 0.15 and 0.16 with expanded census rows and legal-cleared fallback fonts for better coverage. - **Documentation** — Updated examples for custom UI APIs and clarified viewport geometry behavior. * fix: roll back default toolbar fonts * test: update font dropdown behavior expectations * chore(cli): 0.17.1 [skip ci] Based on my analysis of the commits, v0.17.1 contains a single fix: rolling back the default toolbar font options to a conservative baseline. ### Fixes - **Toolbar fonts** — Reverted default font dropdown to the conservative baseline (Arial, Courier New, Georgia, Times New Roman). Per-document font options remain available through the font selector. * chore(sdk): 1.16.1 [skip ci] ### Fixes - **Default toolbar fonts** — Rolled back font dropdown to a conservative baseline (Arial, Courier New, Georgia, Times New Roman). Per-document font options remain available through the font selector. * chore(mcp): 0.12.1 [skip ci] Based on my analysis of the git diff, this patch release contains a single fix related to the toolbar font dropdown. Here are the release notes: ### Fixes - **Toolbar fonts** — Rolled back font dropdown to conservative baseline (Arial, Courier New, Georgia, Times New Roman). Per-document font options remain available through the font selector. * chore(release): 1.40.1 [skip ci] ### Fixes - Toolbar font dropdown reverted to a conservative baseline (Arial, Courier New, Georgia, Times New Roman) while the optional font-pack selection UI is finalized. Full font resolution through documents remains unchanged. * chore(react): 1.11.1 [skip ci] ### Fixes - Toolbar font dropdown returns to a conservative baseline (Arial, Courier New, Georgia, Times New Roman) while the optional font-pack selection UI is finalized — full font resolution within documents remains unchanged. * chore(vscode): 2.12.1 [skip ci] ### Fixes - Toolbar font dropdown reverted to a conservative baseline (Arial, Courier New, Georgia, Times New Roman) while the optional font-pack selection UI is finalized. Document rendering of all fonts remains unchanged. * fix: resolve stable merge conflicts * fix: update font dropdown behavior expectations * fix: align font option tests with rich pack * fix: update ui font option expectations * fix: avoid contract demo rebuild on dev * fix: update react font hook expectations * chore(cli): 0.18.0 [skip ci] ### What's New - **Bundled fonts are now explicit and predictable.** The optional `@superdoc-dev/fonts` package (renamed from `@superdoc/fonts`) is now the only source for bundled font substitutes. Without it, the toolbar shows a safe baseline (Arial, Times New Roman, Courier New) and documents render with system fonts. With it configured, the full reviewed set becomes available. - **Config-gated font availability prevents stray requests.** An unconfigured app never tries to fetch a substitute `.woff2` file it cannot serve, so there are no spurious 404s or one-time warnings. Availability is a config decision, not a runtime probe. - **Curate bundled fonts by name with `createSuperDocFonts()`.** Use `include` to allow only specific Word families, or `exclude` to keep everything except a few. Names are validated at setup time — a typo fails fast instead of silently hiding fonts. Curation changes what the toolbar advertises and which families SuperDoc substitutes. ```js import { createSuperDocFonts } from '@superdoc-dev/fonts'; new SuperDoc({ selector: '#editor', document: 'contract.docx', fonts: createSuperDocFonts({ exclude: ['Cooper Black', 'Brush Script MT'] }), }); ``` - **Document-scoped activation and curation.** Each document decides which bundled fonts it uses. A curated document never reuses a full-pack document's cached font measures, so resolution stays accurate regardless of what curation layers are in use. ### Improvements - Updated all getting-started examples and documentation to use the new `@superdoc-dev/fonts` package and curation APIs. - Toolbar font dropdown now correctly reflects availability based on pack configuration. * chore(sdk): 1.17.0 [skip ci] ### What's New - **Bundled fonts are now explicit and predictable.** The optional `@superdoc-dev/fonts` package (renamed from `@superdoc/fonts`) is now the only source for metric-compatible font substitutes. Without it, the toolbar shows a safe baseline (Arial, Courier New, Times New Roman) and documents render with system fonts. With it configured, the full 30-family set becomes available. - **Config-gated font availability prevents stray requests.** An unconfigured app never tries to fetch a `.woff2` file it cannot serve — no spurious 404s, no one-time warnings. Availability is explicit, determined by your config, not discovered at runtime. - **Curate bundled fonts by name with `createSuperDocFonts()`.** Use `include` to allow only specific Word families, or `exclude` to block a few. Names are validated at setup time — a typo fails fast with suggestions instead of silently hiding fonts. Curation changes what the toolbar advertises and which families get substituted. ```js import { createSuperDocFonts } from '@superdoc-dev/fonts'; new SuperDoc({ selector: '#editor', document: 'contract.docx', fonts: createSuperDocFonts({ exclude: ['Cooper Black', 'Brush Script MT'] }), }); ``` - **Document-scoped activation and curation.** Each document independently decides which bundled fonts it uses. A curated document never reuses a full-pack document's cached font measures, so resolution stays accurate regardless of what layers are in use. ### Improvements - Updated all getting-started examples and framework guides to use the new `@superdoc-dev/fonts` package. - Toolbar font dropdown now correctly reflects availability based on your pack configuration. - Font availability and curation signature are now document-scoped, eliminating cache collisions across different configurations. * chore(mcp): 0.13.0 [skip ci] ### What's New - **Bundled fonts are now explicit and predictable.** The optional `@superdoc-dev/fonts` package (renamed from `@superdoc/fonts`) is now the only source for metric-compatible font substitutes. Without it, the toolbar shows a safe baseline (Arial, Courier New, Times New Roman) and documents render with system fonts. With it configured, the full reviewed set becomes available. - **Config-gated font availability prevents stray requests.** An unconfigured app never tries to fetch a `.woff2` file it cannot serve — no spurious 404s, no one-time warnings. Availability is explicit, determined by your config, not discovered at runtime. - **Curate bundled fonts by name with `createSuperDocFonts()`.** Use `include` to allow only specific Word families, or `exclude` to block a few. Names are validated at setup time — a typo fails fast with suggestions instead of silently hiding fonts. Curation changes what the toolbar advertises and which families get substituted. ```js import { createSuperDocFonts } from '@superdoc-dev/fonts'; new SuperDoc({ selector: '#editor', document: 'contract.docx', fonts: createSuperDocFonts({ exclude: ['Cooper Black', 'Brush Script MT'] }), }); ``` - **Document-scoped activation and curation.** Each document independently decides which bundled fonts it uses. A curated document never reuses a full-pack document's cached font measures, so resolution stays accurate regardless of what curation layers are in use. ### Improvements - Updated all getting-started examples and framework guides to use the new `@superdoc-dev/fonts` package. - Toolbar font dropdown now correctly reflects availability based on your pack configuration. - Font availability and curation signature are now document-scoped, eliminating cache collisions across different configurations. * chore(fonts): 0.1.1 [skip ci] Based on my analysis of the changes in this release, here are the release notes: ### What's New - **@superdoc-dev/fonts is now the only bundled font source** — The fonts package is now the single recommended way to load metric-compatible fallbacks. The core `superdoc` package no longer ships or bundles fonts. ### Improvements - **Simplified fonts API** — Pass `superdocFonts` directly to SuperDoc's config, or use `createSuperDocFonts({ include, exclude })` to curate which families you need. - **CDN build is baseline-by-default** — The CDN/`