fix(muya): size an image from where its resize handle was grabbed (#5… · marktext/marktext@9b34d72 · GitHub
Skip to content

Commit 9b34d72

Browse files
Jocsclaude
andauthored
fix(muya): size an image from where its resize handle was grabbed (#5392) (#5535)
`_mouseMove` measured the new width against the opposite handle's current position, read fresh on every event. For the left handle that reference is the image's right edge, and a left-aligned image grows on its right side -- so each width it wrote moved the very edge the next event measured from, re-adding the whole accumulated delta. A 60 px drag widened the image by 210 px, ran away to the column width after ~25 px of travel, and saved a width wider than the one on screen. The right handle measured against the left edge, which does not move, so it tracked the pointer correctly. Snapshot the pointer position and the image width at mousedown and offset from those instead. Nothing read during the drag is affected by what the drag writes, so both handles now track the pointer 1:1, for centre- and right-aligned images as much as the default left-aligned one. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent ccc6b05 commit 9b34d72

3 files changed

Lines changed: 137 additions & 21 deletions

File tree

Lines changed: 106 additions & 0 deletions

‎packages/muya/src/ui/imageResizeBar/__tests__/imageResizeBar.spec.ts‎

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,19 +88,24 @@ function contentBar(): HTMLElement {
8888
return bar;
8989
}
9090

91-
// happy-dom's MouseEvent has no `x`, and `_mouseMove` ignores events without it.
92-
function mouseMove(clientX: number): MouseEvent {
93-
const event = new MouseEvent('mousemove', { bubbles: true, clientX });
91+
// happy-dom's MouseEvent has no `x`, which is how the bar recognises a mouse
92+
// event; real browsers always set it, on mousedown as much as on mousemove.
93+
function mouseEvent(type: string, clientX: number): MouseEvent {
94+
const event = new MouseEvent(type, { bubbles: true, clientX });
9495
Object.defineProperty(event, 'x', { value: clientX });
9596
return event;
9697
}
9798

99+
function mouseMove(clientX: number): MouseEvent {
100+
return mouseEvent('mousemove', clientX);
101+
}
102+
98103
// happy-dom rethrows listener errors from dispatchEvent; collect them per
99104
// step so a throwing mousemove still lets the mouseup run.
100105
function dragFrom(target: HTMLElement, clientX = 40): unknown[] {
101106
const listenerErrors: unknown[] = [];
102107
const steps: Array<[EventTarget, Event]> = [
103-
[target, new MouseEvent('mousedown', { bubbles: true })],
108+
[target, mouseEvent('mousedown', 0)],
104109
[document.body, mouseMove(clientX)],
105110
[document.body, new MouseEvent('mouseup', { bubbles: true })],
106111
];
@@ -202,8 +207,9 @@ describe('image resize bar and document content with class "bar" (#5116)', () =>
202207
const errors = dragFrom(document.querySelector<HTMLElement>('.mu-transformer .bar.right')!, 200);
203208

204209
expect(errors).toEqual([]);
205-
// happy-dom has no layout, so the left handle sits at x 0: 200 - 0 - CIRCLE_RADIO.
206-
expect(block.updateImage).toHaveBeenCalledWith(imageInfo, 'width', '195');
210+
// The width grows by the pointer's travel since mousedown. happy-dom
211+
// has no layout, so the image starts at width 0 and the press at x 0.
212+
expect(block.updateImage).toHaveBeenCalledWith(imageInfo, 'width', '200');
207213
});
208214
});
209215

@@ -216,7 +222,7 @@ describe('image resize bar and document content with class "bar" (#5116)', () =>
216222
function dragOutsideWindow(handle: HTMLElement, clientX: number): unknown[] {
217223
const listenerErrors: unknown[] = [];
218224
const steps: Array<[EventTarget, Event]> = [
219-
[handle, new MouseEvent('mousedown', { bubbles: true })],
225+
[handle, mouseEvent('mousedown', 0)],
220226
[document.body, mouseMove(clientX / 2)],
221227
[document.documentElement, mouseMove(clientX)],
222228
[document.documentElement, new MouseEvent('mouseup', { bubbles: true })],
@@ -250,8 +256,8 @@ describe('image resize released outside the window (#5393)', () => {
250256
);
251257

252258
expect(errors).toEqual([]);
253-
expect(block.updateImage).toHaveBeenCalledWith(imageInfo, 'width', '195');
254-
expect(reference.querySelector('img')!.getAttribute('width')).toBe('195');
259+
expect(block.updateImage).toHaveBeenCalledWith(imageInfo, 'width', '200');
260+
expect(reference.querySelector('img')!.getAttribute('width')).toBe('200');
255261
});
256262

257263
it('leaves no drag listeners behind', () => {

‎packages/muya/src/ui/imageResizeBar/index.ts‎

Lines changed: 16 additions & 12 deletions

0 commit comments

Comments
 (0)