Skip to content

Commit

Permalink
Merge pull request #2744 from microsoft/u/juliaroldi/crop-context-menu
Browse files Browse the repository at this point in the history
  • Loading branch information
juliaroldi authored Jul 12, 2024
2 parents 5e2b680 + 12673f7 commit addd332
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { getHTMLImageOptions } from './utils/getHTMLImageOptions';
import { getSelectedImage } from './utils/getSelectedImage';
import { getSelectedImageMetadata, updateImageEditInfo } from './utils/updateImageEditInfo';
import { ImageEditElementClass } from './types/ImageEditElementClass';
import { normalizeImageSelection } from './utils/normalizeImageSelection';
import { Resizer } from './Resizer/resizerContext';
import { Rotator } from './Rotator/rotatorContext';
import { updateRotateHandle } from './Rotator/updateRotateHandle';
Expand Down Expand Up @@ -256,6 +257,9 @@ export class ImageEditPlugin implements ImageEditor, EditorPlugin {
image.isSelectedAsImageSelection = shouldSelectImage;
}
);
if (shouldSelectImage) {
normalizeImageSelection(previousSelectedImage);
}
this.cleanInfo();
result = true;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { mutateBlock } from 'roosterjs-content-model-dom';
import type { ImageAndParagraph } from '../types/ImageAndParagraph';

/**
* Selecting directly on the image will only capture the image segment.
* However, if the selection is made while the image is within a wrapper, it will capture the span that encloses the image.
* In the last case, the selection will be marked as <---SelectionMarker---><---Image---><---SelectionMarker--->.
* To fix this behavior the extra selection markers are removed.
* @internal
*/
export function normalizeImageSelection(imageAndParagraph: ImageAndParagraph) {
const paragraph = imageAndParagraph.paragraph;
const index = paragraph.segments.indexOf(imageAndParagraph.image);
if (index > 0) {
const markerBefore = paragraph.segments[index - 1];
const markerAfter = paragraph.segments[index + 1];
if (
markerBefore &&
markerAfter &&
markerAfter.segmentType == 'SelectionMarker' &&
markerBefore.segmentType == 'SelectionMarker' &&
markerAfter.isSelected &&
markerBefore.isSelected
) {
const mutatedParagraph = mutateBlock(paragraph);
mutatedParagraph.segments.splice(index - 1, 1);
mutatedParagraph.segments.splice(index, 1);
}
return imageAndParagraph;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { ImageAndParagraph } from '../../../lib/imageEdit/types/ImageAndParagraph';
import { normalizeImageSelection } from '../../../lib/imageEdit/utils/normalizeImageSelection';
import type { ReadonlyContentModelImage } from 'roosterjs-content-model-types';

describe('normalizeImageSelection', () => {
it('normalize image selection', () => {
const image: ReadonlyContentModelImage = {
segmentType: 'Image',
src: 'test',
format: {
fontFamily: 'Calibri',
fontSize: '11pt',
textColor: 'rgb(0, 0, 0)',
id: 'image_0',
maxWidth: '1800px',
},
dataset: {},
isSelectedAsImageSelection: true,
isSelected: true,
};
const imageAndParagraph: ImageAndParagraph = {
paragraph: {
blockType: 'Paragraph',
segments: [
{
segmentType: 'SelectionMarker',
isSelected: true,
format: {},
},
image,
{
segmentType: 'SelectionMarker',
isSelected: true,
format: {},
},
],
format: {},
segmentFormat: {
fontFamily: 'Calibri',
fontSize: '11pt',
textColor: 'rgb(0, 0, 0)',
},
},
image: image,
};

const result = normalizeImageSelection(imageAndParagraph);
expect(result?.paragraph).toEqual({
blockType: 'Paragraph',
segments: [
{
segmentType: 'Image',
src: 'test',
format: {
fontFamily: 'Calibri',
fontSize: '11pt',
textColor: 'rgb(0, 0, 0)',
id: 'image_0',
maxWidth: '1800px',
},
dataset: {},
isSelectedAsImageSelection: true,
isSelected: true,
},
],
format: {},
segmentFormat: {
fontFamily: 'Calibri',
fontSize: '11pt',
textColor: 'rgb(0, 0, 0)',
},
});
});

it('normalize image selection', () => {
const imageAndParagraph: ImageAndParagraph = {
paragraph: {
blockType: 'Paragraph',
segments: [
{
segmentType: 'SelectionMarker',
format: {},
},
{
segmentType: 'Text',
text: 'test',
format: {},
},
{
segmentType: 'Image',
src: 'test',
format: {
fontFamily: 'Calibri',
fontSize: '11pt',
textColor: 'rgb(0, 0, 0)',
id: 'image_0',
maxWidth: '1800px',
},
dataset: {},
isSelectedAsImageSelection: true,
isSelected: true,
},
{
segmentType: 'SelectionMarker',
isSelected: true,
format: {},
},
],
format: {},
segmentFormat: {
fontFamily: 'Calibri',
fontSize: '11pt',
textColor: 'rgb(0, 0, 0)',
},
},
image: {
segmentType: 'Image',
src: 'test',
format: {
fontFamily: 'Calibri',
fontSize: '11pt',
textColor: 'rgb(0, 0, 0)',
id: 'image_0',
maxWidth: '1800px',
},
dataset: {},
isSelectedAsImageSelection: true,
isSelected: true,
},
};

const result = normalizeImageSelection(imageAndParagraph);
expect(result).toBeUndefined();
});
});

0 comments on commit addd332

Please sign in to comment.