mirror of
https://github.com/facebook/lexical.git
synced 2025-07-03 23:00:17 +08:00
[lexical-playground] Bug Fix: Use natural dimensions for inherited image size (#7388)
This commit is contained in:
@ -388,8 +388,12 @@ test.describe('Images', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Can add images by arbitrary URL', async ({page, isPlainText}) => {
|
test('Can add images by arbitrary URL', async ({
|
||||||
test.skip(isPlainText);
|
page,
|
||||||
|
isPlainText,
|
||||||
|
isCollab,
|
||||||
|
}) => {
|
||||||
|
test.skip(isPlainText || isCollab, 'Skip in plain text and collab mode');
|
||||||
|
|
||||||
await focusEditor(page);
|
await focusEditor(page);
|
||||||
|
|
||||||
@ -418,7 +422,7 @@ test.describe('Images', () => {
|
|||||||
alt="lexical logo"
|
alt="lexical logo"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
src="https://lexical.dev/img/logo.svg"
|
src="https://lexical.dev/img/logo.svg"
|
||||||
style="height: inherit; max-width: 500px; width: inherit;" />
|
style="height: 112px; max-width: 500px; width: 500px" />
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
@ -790,4 +794,58 @@ test.describe('Images', () => {
|
|||||||
`,
|
`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test(`Verifies image dimensions are properly calculated for both SVG and JPG formats`, async ({
|
||||||
|
page,
|
||||||
|
isPlainText,
|
||||||
|
isCollab,
|
||||||
|
}) => {
|
||||||
|
test.skip(isPlainText || isCollab, 'Skip in plain text and collab mode');
|
||||||
|
|
||||||
|
await focusEditor(page);
|
||||||
|
|
||||||
|
// Insert an SVG image using the Lexical logo
|
||||||
|
await insertUrlImage(
|
||||||
|
page,
|
||||||
|
'https://lexical.dev/img/logo.svg',
|
||||||
|
'lexical logo',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Insert a JPG image
|
||||||
|
await insertUrlImage(page, SAMPLE_IMAGE_URL, 'sample image');
|
||||||
|
|
||||||
|
// Verify both images are inserted with proper dimensions and styling
|
||||||
|
await assertHTML(
|
||||||
|
page,
|
||||||
|
html`
|
||||||
|
<p class="PlaygroundEditorTheme__paragraph">
|
||||||
|
<span
|
||||||
|
class="editor-image"
|
||||||
|
contenteditable="false"
|
||||||
|
data-lexical-decorator="true">
|
||||||
|
<div draggable="false">
|
||||||
|
<img
|
||||||
|
alt="lexical logo"
|
||||||
|
draggable="false"
|
||||||
|
src="https://lexical.dev/img/logo.svg"
|
||||||
|
style="height: 112px; max-width: 500px; width: 500px" />
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="editor-image"
|
||||||
|
contenteditable="false"
|
||||||
|
data-lexical-decorator="true">
|
||||||
|
<div draggable="false">
|
||||||
|
<img
|
||||||
|
alt="sample image"
|
||||||
|
draggable="false"
|
||||||
|
src="${SAMPLE_IMAGE_URL}"
|
||||||
|
style="height: inherit; max-width: 500px; width: inherit;" />
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
<br />
|
||||||
|
</p>
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -79,6 +79,10 @@ function useSuspenseImage(src: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isSVG(src: string): boolean {
|
||||||
|
return src.toLowerCase().endsWith('.svg');
|
||||||
|
}
|
||||||
|
|
||||||
function LazyImage({
|
function LazyImage({
|
||||||
altText,
|
altText,
|
||||||
className,
|
className,
|
||||||
@ -99,19 +103,82 @@ function LazyImage({
|
|||||||
onError: () => void;
|
onError: () => void;
|
||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
useSuspenseImage(src);
|
useSuspenseImage(src);
|
||||||
|
const [dimensions, setDimensions] = useState<{
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
} | null>(null);
|
||||||
|
const isSVGImage = isSVG(src);
|
||||||
|
|
||||||
|
// Set initial dimensions for SVG images
|
||||||
|
useEffect(() => {
|
||||||
|
if (imageRef.current && isSVGImage) {
|
||||||
|
const {naturalWidth, naturalHeight} = imageRef.current;
|
||||||
|
setDimensions({
|
||||||
|
height: naturalHeight,
|
||||||
|
width: naturalWidth,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [imageRef, isSVGImage]);
|
||||||
|
|
||||||
|
// Calculate final dimensions with proper scaling
|
||||||
|
const calculateDimensions = () => {
|
||||||
|
if (!isSVGImage) {
|
||||||
|
return {
|
||||||
|
height,
|
||||||
|
maxWidth,
|
||||||
|
width,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use natural dimensions if available, otherwise fallback to defaults
|
||||||
|
const naturalWidth = dimensions?.width || 200;
|
||||||
|
const naturalHeight = dimensions?.height || 200;
|
||||||
|
|
||||||
|
let finalWidth = naturalWidth;
|
||||||
|
let finalHeight = naturalHeight;
|
||||||
|
|
||||||
|
// Scale down if width exceeds maxWidth while maintaining aspect ratio
|
||||||
|
if (finalWidth > maxWidth) {
|
||||||
|
const scale = maxWidth / finalWidth;
|
||||||
|
finalWidth = maxWidth;
|
||||||
|
finalHeight = Math.round(finalHeight * scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scale down if height exceeds maxHeight while maintaining aspect ratio
|
||||||
|
const maxHeight = 500;
|
||||||
|
if (finalHeight > maxHeight) {
|
||||||
|
const scale = maxHeight / finalHeight;
|
||||||
|
finalHeight = maxHeight;
|
||||||
|
finalWidth = Math.round(finalWidth * scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
height: finalHeight,
|
||||||
|
maxWidth,
|
||||||
|
width: finalWidth,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const imageStyle = calculateDimensions();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<img
|
<img
|
||||||
className={className || undefined}
|
className={className || undefined}
|
||||||
src={src}
|
src={src}
|
||||||
alt={altText}
|
alt={altText}
|
||||||
ref={imageRef}
|
ref={imageRef}
|
||||||
style={{
|
style={imageStyle}
|
||||||
height,
|
|
||||||
maxWidth,
|
|
||||||
width,
|
|
||||||
}}
|
|
||||||
onError={onError}
|
onError={onError}
|
||||||
draggable="false"
|
draggable="false"
|
||||||
|
onLoad={(e) => {
|
||||||
|
if (isSVGImage) {
|
||||||
|
const img = e.currentTarget;
|
||||||
|
setDimensions({
|
||||||
|
height: img.naturalHeight,
|
||||||
|
width: img.naturalWidth,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user