Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
7c35c40
Fix toggling format issue at composition stage for CJK (#3064)
haven2world Jun 11, 2025
3ba879c
Avoid "undefined" in HTML to Markdown generated content (#3069)
Durss Jun 11, 2025
a4e9602
Add focus handling in formatTableWithContentModel and its tests (#3072)
BryanValverdeU Jun 16, 2025
00e00f7
format applier (#3073)
juliaroldi Jun 16, 2025
87b1570
Keep implicit paragraph when pressing Enter at the start of it. (#3075)
BryanValverdeU Jun 18, 2025
184c018
Add beforeLogicalRootChanged event handling and related tests (#3077)
BryanValverdeU Jun 19, 2025
9da5af4
Disable isComposing check in DOM event propagation for Android (#3076)
Rain-Zheng Jun 20, 2025
7fab305
Allow plugins to store state in snapshot (#3079)
florian-msft Jun 26, 2025
7081cdd
Fix #3080 (#3084)
JiuqingSong Jul 1, 2025
fd808bd
Add auto direction to setDirection (#3082)
wisaulni Jul 7, 2025
327d6ab
Ensure image is loaded before creating image wrapper (#3090)
BryanValverdeU Jul 18, 2025
eb3685f
test (#3092)
juliaroldi Jul 22, 2025
3ad7db1
Fix #3085 (#3095)
JiuqingSong Jul 22, 2025
47271ff
Adjust the image wrapper to stay inline (#3093)
juliaroldi Jul 22, 2025
74bc3e4
Fix 309357 (#3097)
JiuqingSong Jul 22, 2025
6307ffb
Fix #3063 (#3096)
JiuqingSong Jul 23, 2025
82f0466
Fix #3087 Delete paragraph styles when there is nothing else to be de…
JiuqingSong Jul 23, 2025
2da7000
Remove karma changes (#3102)
juliaroldi Jul 24, 2025
16ba94c
Adjust Block Indentation (#3099)
juliaroldi Jul 25, 2025
596ed24
Process non-visible elements (#3089)
juliaroldi Jul 25, 2025
eb7cfaa
Fix runtime color for dark mode (#3101)
JiuqingSong Jul 27, 2025
6ed2303
table rtl (#3103)
juliaroldi Jul 28, 2025
bf46671
image-handles (#3104)
juliaroldi Jul 28, 2025
0437f87
Fix superscript rule (#3106)
juliaroldi Jul 30, 2025
4cddcac
Fix 380860 (#3107)
JiuqingSong Jul 31, 2025
9acc158
Support 'HTMLFast' mode when get HTML (#3109)
JiuqingSong Aug 10, 2025
dc7b236
Bump tmp from 0.2.1 to 0.2.4 (#3114)
dependabot[bot] Aug 11, 2025
be90b35
Fix #3110 (#3113)
BryanValverdeU Aug 12, 2025
deb3009
Add markdown support for strikethrough
francismengMS Aug 13, 2025
6fcf93a
Fix test
francismengMS Aug 13, 2025
e736fa9
Try fix unstable test (#3118)
BryanValverdeU Aug 14, 2025
b46c3e0
Merge branch 'master' into add-support-for-strikethrough
FrancisMengx Aug 14, 2025
cb770a5
Merge pull request #3117 from microsoft/add-support-for-strikethrough
FrancisMengx Aug 14, 2025
c00c270
add support for nested style markdowns
francismengMS Aug 14, 2025
9e25b8f
move let to const
francismengMS Aug 14, 2025
c363b6d
update
francismengMS Aug 14, 2025
25c9c9e
Support DL,DT,DD in content model (#3120)
JiuqingSong Aug 15, 2025
f7cf931
Add an experimental feature for 'HTMLFast' when export html (#3121)
JiuqingSong Aug 15, 2025
4dee325
Fix 276282 (#3125)
JiuqingSong Aug 19, 2025
283e7f8
Fix #3112 Delete empty block group when need (#3124)
JiuqingSong Aug 19, 2025
d367b9a
update
francismengMS Aug 20, 2025
91a1e0f
remove console log
francismengMS Aug 20, 2025
6b5f0e0
fix regression
francismengMS Aug 21, 2025
de2a396
update
francismengMS Aug 21, 2025
46a6b59
Merge branch 'master' into add-support-for-nested-style-markdown
FrancisMengx Aug 21, 2025
6464adf
Merge pull request #3119 from microsoft/add-support-for-nested-style-…
FrancisMengx Aug 22, 2025
43a8880
Do not add undo snapshot from ImageEdit plugin if image is not change…
JiuqingSong Aug 26, 2025
62dafa5
Support different options for empty line mode in mark down (#3128)
JiuqingSong Aug 26, 2025
622a089
Fix auto link (#3129)
juliaroldi Aug 27, 2025
3ab45b3
Graduate option "disableCache" (#3132)
JiuqingSong Aug 28, 2025
9f8abbf
Improve handleParagraph function (#3130)
JiuqingSong Aug 28, 2025
8d8f0fe
Remove console.log added accidentally in test code (#3134)
JiuqingSong Aug 28, 2025
26c4616
Toggle blockquote in Format Container (#3126)
juliaroldi Aug 28, 2025
63d7a7d
Fix auto-capitalization for iOS (#3131)
isnine Aug 30, 2025
0f17465
Fix RTL for Image Selection (#3136)
juliaroldi Sep 2, 2025
8e7a710
Revert "Improve handleParagraph function (#3130)" (#3137)
JiuqingSong Sep 2, 2025
0d1f6e9
Merge branch 'master' into u/jisong/9352
JiuqingSong Sep 8, 2025
64bcd24
9.36.0
JiuqingSong Sep 8, 2025
0f9e725
Apply suggestion from @Copilot
juliaroldi Sep 8, 2025
62f238c
trigger cla
JiuqingSong Sep 8, 2025
9d9d523
Merge branch 'u/jisong/9352' of https://github.com/microsoft/roosterj…
JiuqingSong Sep 8, 2025
ddbea8d
trigger cla again
JiuqingSong Sep 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ function createEditorEnvironment(
modelToDomSettings: createModelToDomSettings(options),
isMac: appVersion.indexOf('Mac') != -1,
isAndroid: /android/i.test(userAgent),
isIOS: /iPad|iPhone/.test(userAgent),
isSafari:
userAgent.indexOf('Safari') >= 0 &&
userAgent.indexOf('Chrome') < 0 &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ describe('createEditorCore', () => {
environment: {
isMac: false,
isAndroid: false,
isIOS: false,
isSafari: false,
isMobileOrTablet: false,
domToModelSettings: mockedDomToModelSettings,
Expand Down Expand Up @@ -218,6 +219,7 @@ describe('createEditorCore', () => {
environment: {
isMac: false,
isAndroid: true,
isIOS: false,
isSafari: false,
isMobileOrTablet: true,
domToModelSettings: mockedDomToModelSettings,
Expand Down Expand Up @@ -252,6 +254,7 @@ describe('createEditorCore', () => {
environment: {
isMac: false,
isAndroid: true,
isIOS: false,
isSafari: false,
isMobileOrTablet: true,
domToModelSettings: mockedDomToModelSettings,
Expand Down Expand Up @@ -286,6 +289,7 @@ describe('createEditorCore', () => {
environment: {
isMac: true,
isAndroid: false,
isIOS: false,
isSafari: false,
isMobileOrTablet: false,
domToModelSettings: mockedDomToModelSettings,
Expand Down Expand Up @@ -320,6 +324,7 @@ describe('createEditorCore', () => {
environment: {
isMac: false,
isAndroid: false,
isIOS: false,
isSafari: true,
isMobileOrTablet: false,
domToModelSettings: mockedDomToModelSettings,
Expand Down Expand Up @@ -354,6 +359,7 @@ describe('createEditorCore', () => {
environment: {
isMac: false,
isAndroid: false,
isIOS: false,
isSafari: false,
isMobileOrTablet: false,
domToModelSettings: mockedDomToModelSettings,
Expand All @@ -368,4 +374,40 @@ describe('createEditorCore', () => {
undefined
);
});

it('iOS iPhone Safari', () => {
const mockedDiv = {
ownerDocument: {
defaultView: {
navigator: {
userAgent:
'Mozilla/5.0 (iPhone; CPU iPhone OS 18_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
},
},
},
attributes: {
a: 'b',
},
} as any;
const mockedOptions = {} as any;

runTest(mockedDiv, mockedOptions, {
environment: {
isMac: false,
isAndroid: false,
isIOS: true,
isSafari: false,
isMobileOrTablet: true,
domToModelSettings: mockedDomToModelSettings,
modelToDomSettings: mockedModelToDomSettings,
},
});

expect(DarkColorHandlerImpl.createDarkColorHandler).toHaveBeenCalledWith(
mockedDiv,
getDarkColorFallback,
undefined,
undefined
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,14 @@ export function keyboardDelete(
let handled = false;
const selection = editor.getDOMSelection();

if (shouldDeleteWithContentModel(selection, rawEvent, handleExpandedSelection)) {
if (
shouldDeleteWithContentModel(
selection,
rawEvent,
handleExpandedSelection,
editor.getEnvironment().isIOS ?? false
)
) {
editor.formatContentModel(
(model, context) => {
const result = deleteSelection(
Expand Down Expand Up @@ -92,7 +99,8 @@ function getDeleteSteps(rawEvent: KeyboardEvent, isMac: boolean): (DeleteSelecti
function shouldDeleteWithContentModel(
selection: DOMSelection | null,
rawEvent: KeyboardEvent,
handleExpandedSelection: boolean
handleExpandedSelection: boolean,
isIOS: boolean
) {
if (!selection) {
return false; // Nothing to delete
Expand Down Expand Up @@ -121,16 +129,20 @@ function shouldDeleteWithContentModel(
return !(
isNodeOfType(startContainer, 'TEXT_NODE') &&
!isModifierKey(rawEvent) &&
(canDeleteBefore(rawEvent, startContainer, startOffset) ||
(canDeleteBefore(rawEvent, startContainer, startOffset, isIOS) ||
canDeleteAfter(rawEvent, startContainer, startOffset))
);
}
}

function canDeleteBefore(rawEvent: KeyboardEvent, text: Text, offset: number) {
if (rawEvent.key != 'Backspace' || offset <= 1) {
function canDeleteBefore(rawEvent: KeyboardEvent, text: Text, offset: number, isIOS: boolean) {
if (rawEvent.key != 'Backspace') {
return false;
}
if (offset <= 1) {
// For iOS, allow browser to handle deletion of first character on iOS to preserve auto-capitalization
return offset === 1 && isIOS;
}

const length = text.nodeValue?.length ?? 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ export class ImageEditPlugin implements ImageEditor, EditorPlugin {
) {
let editingImageModel: ContentModelImage | undefined;
const selection = editor.getDOMSelection();
let isRTL: boolean = false;

editor.formatContentModel(
(model, context) => {
Expand Down Expand Up @@ -426,6 +427,7 @@ export class ImageEditPlugin implements ImageEditor, EditorPlugin {
this.isCropMode = isCropMode;
mutateSegment(editingImage.paragraph, editingImage.image, image => {
editingImageModel = image;
isRTL = editingImage.paragraph.format.direction == 'rtl';
this.imageEditInfo = updateImageEditInfo(image, selection.image);
image.format.imageState = 'isEditing';
});
Expand All @@ -447,9 +449,9 @@ export class ImageEditPlugin implements ImageEditor, EditorPlugin {
isElementOfType(node, 'img')
) {
if (isCropMode) {
this.startCropMode(editor, node);
this.startCropMode(editor, node, isRTL);
} else {
this.startRotateAndResize(editor, node);
this.startRotateAndResize(editor, node, isRTL);
}
}
},
Expand Down Expand Up @@ -541,7 +543,7 @@ export class ImageEditPlugin implements ImageEditor, EditorPlugin {
editor.setEditorStyle(IMAGE_EDIT_CLASS_CARET, `caret-color: transparent;`);
}

public startRotateAndResize(editor: IEditor, image: HTMLImageElement) {
public startRotateAndResize(editor: IEditor, image: HTMLImageElement, isRTL: boolean) {
if (this.imageEditInfo) {
this.startEditing(editor, image, ['resize', 'rotate']);
if (this.selectedImage && this.imageEditInfo && this.wrapper && this.clonedImage) {
Expand All @@ -566,7 +568,9 @@ export class ImageEditPlugin implements ImageEditor, EditorPlugin {
this.selectedImage,
this.clonedImage,
this.wrapper,
this.resizers
this.resizers,
undefined /* croppers */,
isRTL
);
this.wasImageResized = true;
}
Expand All @@ -592,7 +596,10 @@ export class ImageEditPlugin implements ImageEditor, EditorPlugin {
this.options,
this.selectedImage,
this.clonedImage,
this.wrapper
this.wrapper,
undefined /* resizers */,
undefined /* croppers */,
isRTL
);
this.updateRotateHandleState(
editor,
Expand All @@ -619,7 +626,9 @@ export class ImageEditPlugin implements ImageEditor, EditorPlugin {
this.selectedImage,
this.clonedImage,
this.wrapper,
this.resizers
this.resizers,
undefined /* croppers */,
isRTL
);

this.updateRotateHandleState(
Expand Down Expand Up @@ -684,7 +693,7 @@ export class ImageEditPlugin implements ImageEditor, EditorPlugin {
return canRegenerateImage(image);
}

private startCropMode(editor: IEditor, image: HTMLImageElement) {
private startCropMode(editor: IEditor, image: HTMLImageElement, isRTL: boolean) {
if (this.imageEditInfo) {
this.startEditing(editor, image, ['crop']);
if (this.imageEditInfo && this.selectedImage && this.wrapper && this.clonedImage) {
Expand All @@ -708,8 +717,9 @@ export class ImageEditPlugin implements ImageEditor, EditorPlugin {
this.selectedImage,
this.clonedImage,
this.wrapper,
undefined,
this.croppers
undefined /* resizers */,
this.croppers,
isRTL
);
this.isCropMode = true;
}
Expand All @@ -724,8 +734,9 @@ export class ImageEditPlugin implements ImageEditor, EditorPlugin {
this.selectedImage,
this.clonedImage,
this.wrapper,
undefined,
this.croppers
undefined /* resizers */,
this.croppers,
isRTL
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,6 @@ export function checkIfImageWasResized(image: HTMLImageElement): boolean {
}
}

/**
* @internal
*/
export function isRTL(image: HTMLImageElement): boolean {
return window.getComputedStyle(image).direction === 'rtl';
}

function isFixedNumberValue(value: string | number) {
const numberValue = typeof value === 'string' ? parseInt(value) : value;
return !isNaN(numberValue);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import type { ImageMetadataFormat } from 'roosterjs-content-model-types';
import {
getPx,
isASmallImage,
isRTL,
setFlipped,
setSize,
setWrapperSizeDimensions,
Expand All @@ -26,7 +25,8 @@ export function updateWrapper(
clonedImage: HTMLImageElement,
wrapper: HTMLSpanElement,
resizers?: HTMLDivElement[],
croppers?: HTMLDivElement[]
croppers?: HTMLDivElement[],
isRTL?: boolean
) {
const {
angleRad,
Expand Down Expand Up @@ -70,7 +70,7 @@ export function updateWrapper(

// Update the text-alignment to avoid the image to overflow if the parent element have align center or right
// or if the direction is Right To Left
if (isRTL(clonedImage)) {
if (isRTL) {
wrapper.style.textAlign = 'right';
if (!croppers) {
clonedImage.style.left = getPx(cropLeftPx);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,7 @@ describe('keyboardDelete', () => {
type: 'range',
range: { collapsed: false },
}),
getEnvironment: () => ({}),
} as any) as IEditor;
const event = {
which: Delete,
Expand All @@ -559,6 +560,7 @@ describe('keyboardDelete', () => {
type: 'range',
range: { collapsed: false },
}),
getEnvironment: () => ({}),
} as any;
const which = Backspace;
const event = {
Expand Down Expand Up @@ -589,6 +591,7 @@ describe('keyboardDelete', () => {
const editor = {
formatContentModel: formatWithContentModelSpy,
getDOMSelection: () => range,
getEnvironment: () => ({}),
} as any;

keyboardDelete(editor, rawEvent);
Expand All @@ -611,6 +614,7 @@ describe('keyboardDelete', () => {
const editor = {
formatContentModel: formatWithContentModelSpy,
getDOMSelection: () => range,
getEnvironment: () => ({}),
} as any;

keyboardDelete(editor, rawEvent);
Expand All @@ -636,6 +640,7 @@ describe('keyboardDelete', () => {
const editor = {
formatContentModel: formatWithContentModelSpy,
getDOMSelection: () => range,
getEnvironment: () => ({}),
} as any;

keyboardDelete(editor, rawEvent, false /* handleExpandedSelectionOnDelete */);
Expand All @@ -659,6 +664,7 @@ describe('keyboardDelete', () => {
const editor = {
formatContentModel: formatWithContentModelSpy,
getDOMSelection: () => range,
getEnvironment: () => ({}),
} as any;

keyboardDelete(editor, rawEvent);
Expand All @@ -682,6 +688,7 @@ describe('keyboardDelete', () => {
const editor = {
formatContentModel: formatWithContentModelSpy,
getDOMSelection: () => range,
getEnvironment: () => ({}),
} as any;

keyboardDelete(editor, rawEvent);
Expand All @@ -707,6 +714,7 @@ describe('keyboardDelete', () => {
const editor = {
formatContentModel: formatWithContentModelSpy,
getDOMSelection: () => range,
getEnvironment: () => ({}),
} as any;

keyboardDelete(editor, rawEvent, false /* handleExpandedSelectionOnDelete */);
Expand Down Expand Up @@ -740,6 +748,7 @@ describe('keyboardDelete', () => {
const editor = {
formatContentModel: formatWithContentModelSpy,
getDOMSelection: () => range,
getEnvironment: () => ({}),
} as any;

keyboardDelete(editor, rawEvent, false /* handleExpandedSelectionOnDelete */);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,7 @@ describe('ImageEditPlugin - applyFormatWithContentModel', () => {
getAttribute: () => 'test',
};
plugin.setEditingInfo(mockImageWithWidth);
plugin.startRotateAndResize(editor, mockedImage);
plugin.startRotateAndResize(editor, mockedImage, false);
plugin.setIsEditing(isEditing);
plugin.applyFormatWithContentModel(editor, isCropMode, shouldSelectImage, isApiOperation);
const newModel = editor.getContentModelCopy('disconnected');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
checkIfImageWasResized,
getPx,
isASmallImage,
isRTL,
rotateCoordinate,
setFlipped,
setSize,
Expand Down Expand Up @@ -105,12 +104,4 @@ describe('imageEditUtils', () => {
expect(result).toBeFalsy();
});
});

describe('isRTL', () => {
it(' not isRTL', () => {
const image = document.createElement('img');
const result = isRTL(image);
expect(result).toBeFalsy();
});
});
});
Loading
Loading