Skip to content

Version bump main: 9.54.0 → 9.55.0#3385

Draft
juliaroldi wants to merge 22 commits into
releasefrom
u/juliaroldi/bump-ver
Draft

Version bump main: 9.54.0 → 9.55.0#3385
juliaroldi wants to merge 22 commits into
releasefrom
u/juliaroldi/bump-ver

Conversation

@juliaroldi

@juliaroldi juliaroldi commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Release PR merging master into release, bumping main in versions.json from 9.54.0 → 9.55.0 (react and legacyAdapter unchanged). It rolls up the following changes from master:

Markdown paste

Content Model fixes

APIs & image edit

Tests, deps & tooling

How to test

  1. Build and lint: yarn eslint && yarn b
  2. Run the full fast test suite: yarn test:fast
  3. Confirm versions.json shows main: 9.55.0.

JiuqingSong and others added 22 commits June 2, 2026 15:24
…path valid (#3358)

When formatInsertPointWithContentModel persists the Content Model group path during DOM to Model conversion, a FormatContainer that falls back to a plain paragraph would be removed from the model, leaving the persisted path invalid. Add a skipFormatContainerFallbackCheck option that keeps the FormatContainer in that scenario so the formatting callback can still rely on the path.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When handleBlockGroupChildren finishes processing a block group whose list node stack is rooted at the parent being left, clear the entire node stack instead of only its inner levels so a sibling block group does not incorrectly reuse the invalidated list element.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
#3362)

When setSelection applies a range selection, a leading or trailing
SelectionMarker that has a real (non-marker) selected segment next to it in
the same paragraph carries no selection information and can be removed. Track,
per paragraph, whether any non-marker segment was selected and which boundary
markers were kept; after the segment loop, drop those boundary markers if the
paragraph contained real selected content.

This is scoped to the same paragraph on purpose: a marker at a paragraph edge
must be kept to distinguish "selection starts at the beginning of this line"
from "selection starts at the end of the previous line".

Update the #3341 reconcileSelection snapshots accordingly: the preserveMarker
guard still hands setSelection two live markers (so the selected segment keeps
isSelected), and setSelection now drops those redundant boundary markers.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reconcile IMG src and data-* attribute changes in Content Model cache

Previously any attribute change other than id on editor content would set
mutation type to "unknown" and invalidate the whole cached Content Model.

Recognize src and data-* changes on an indexed IMG element and update the
related ContentModelImage (src property or dataset) in place, so the cache
stays valid. Add a new "attribute" mutation type carrying the element and
attribute name, and a reconcileImageAttribute method on DomIndexer.


@

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds two new public APIs to roosterjs-content-model-markdown and a "Paste as Markdown" demo button that uses them to decide whether to convert clipboard content with convertMarkdownToContentModel or fall back to the regular paste flow.
#3365)

@
Treat a backslash-escaped ASCII punctuation character (e.g. "\*") as a
literal character so it is not parsed as a formatting marker.


@

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Add MarkdownPastePlugin to convert pasted markdown content

Add a MarkdownPastePlugin in the roosterjs-content-model-markdown package
that handles the BeforePaste event and, when the clipboard content can be
interpreted as markdown, converts the plain text into a Content Model and
pastes it as rich content.

- Introduce the 'asMarkdown' PasteType so callers can explicitly request a
  markdown paste; the demo's "Paste as Markdown" button now routes through it.
- Add MarkdownPasteOptions with an autoConversion flag (default false) so the
  plugin can optionally auto-convert any markdown-looking paste.
- Map the new PasteType to Normal in the legacy editor adapter.
- Wire the plugin and its autoConversion option into the demo site's plugins
  side pane.
This change makes the converter prefer the pasteType already present on the new event, only falling back to the mapping from the old event when the new event doesn't have one
Adds a new project skill, draft-pr, at .claude/skills/draft-pr/SKILL.md. The skill walks through creating a pull request for the current branch: it inspects the diff against master, generates a concise imperative title and a structured description (a ## Summary plus a ## How to test section), and opens the PR with the gh CLI. It follows the same authoring conventions as the existing version-bump skill and enforces repo-specific rules from AGENTS.md (PRs target master, tests use yarn test:fast).
…rd uppercase (#3372)

* new tests

* Only capitalize the beginning of a word

* Add button to demo

* Normalize line endings to LF for capitalization changes

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.4.0 to 3.4.9.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](cure53/DOMPurify@3.4.0...3.4.9)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-version: 3.4.9
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jiuqing Song <jisong@microsoft.com>
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.4.9 to 3.4.11.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](cure53/DOMPurify@3.4.9...3.4.11)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-version: 3.4.11
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.11.1 to 7.29.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.29.7/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-version: 7.29.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jiuqing Song <jisong@microsoft.com>
Fixes the editor jumping/scrolling when an image is selected for editing. In createImageWrapper.ts, attaching the shadow root replaces the rendered light-DOM image with a taller edit wrapper (border + resize/rotate/crop handles), which grows the surrounding line box and causes the browser to scroll the selection back into view.

This pins the shadow host span to the original image's footprint — captured from image.offsetWidth/offsetHeight before the shadow root takes over — by setting display: inline-block, fixed width/height, vertical-align: bottom, and overflow: visible. The handles and wrapper still overflow the host visually, but the line box no longer grows, so the editor stays put. Pinning is skipped when the image has no measurable footprint (offsetWidth/offsetHeight of 0).
* Re-enable and stabilize previously-disabled tests

Several test suites were disabled (xit/xdescribe) due to flakiness or
environment dependence. Re-enable them and fix the underlying issues so
they pass deterministically regardless of spec order:

- selectionConverterTest: spy on the deep createRange module did not
  intercept the barrel import; exercise the real createRange with a
  document-attached image instead.
- updateRotateHandleTest: the spy targeted rotateHandle while the code
  reads rotateCenter; point it at the right element and feed each
  "hidden" case the intended edge distance (and correct an impossible
  expected handle value).
- applyChangeTest: replace brittle exact PNG data-URL comparisons with
  IHDR-dimension checks (encoder-independent), and create a fresh
  contentModelImage per test to remove order-dependent editingInfo state.
- tableEditorTest: give the editor a deterministic size so the table is
  never flush against the scroll-container edge, which otherwise made
  inserter visibility depend on leftover document.body layout.
- tableResizerTest: recreate the content model table per test (onDragging
  mutates it in place) and gate verifyCellRectChange on growth only so an
  incidental cross-axis border-box shift does not flip the assertion.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix test

* improve

* improve

* fix

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ion (#3379)

* Fix normalizeSingleSegment to preserve leading space for word separation

- Search backward for the nearest non-empty text segment to determine
  whether leading spaces should be preserved or removed
- Skip empty text segments during normalization to avoid corrupting context
- Replace nbsp with regular space for leading space preservation since
  nbsp prevents word wrapping
- Add unit tests for normalizeSingleSegment

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix comment

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…3378)

Cover previously-untested code paths:
- ContextMenuPluginBase, TouchPlugin (new test files)
- CustomReplacePlugin guard branches and replacement callback
- TableEditPlugin onMouseMove/ensureTableRects/defaultTableSelector
- TableEditor editing lifecycle, public methods, getOnMouseOut, RTL
- EditorAdapter API surface (new describe block)
- buildRangeEx and insertNode utils (new test files)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Retain segments with undeletable links during model pruning

Keep segments that have link.format.undeletable set to true in
pruneUnselectedModel, even when they are not selected. This prevents
undeletable link segments from being lost during selection-based pruning.

Add unit tests covering the new behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* improve

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@juliaroldi juliaroldi changed the base branch from master to release June 26, 2026 14:08
@github-actions

Copy link
Copy Markdown
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://microsoft.github.io/roosterjs/pr-preview/pr-3385/

Built to branch gh-pages at 2026-06-26 14:09 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants