diff --git a/packages/editor/src/extensions/image/component.tsx b/packages/editor/src/extensions/image/component.tsx
index fc6bb9946..a387585f6 100644
--- a/packages/editor/src/extensions/image/component.tsx
+++ b/packages/editor/src/extensions/image/component.tsx
@@ -60,19 +60,18 @@ export function ImageComponent(
});
const dom = editor.view.dom;
+ const downloadOptions = useToolbarStore((store) => store.downloadOptions);
+ const isReadonly = !editor.isEditable;
+ const isSVG = !!mime && mime.includes("/svg");
const size =
editor.view.dom.clientWidth === 0
? node.attrs
- : clampSize(node.attrs, dom.clientWidth, aspectRatio);
+ : clampSize(node.attrs, dom.clientWidth, aspectRatio, isSVG);
let align = node.attrs.align;
if (!align) align = textDirection ? "right" : "left";
- const downloadOptions = useToolbarStore((store) => store.downloadOptions);
- const isReadonly = !editor.isEditable;
- const isSVG = !!mime && mime.includes("/svg");
-
useEffect(() => {
if (!inView) return;
if (src || !hash || bloburl) return;
@@ -113,12 +112,114 @@ export function ImageComponent(
}
}}
>
+
+ {selected && (
+
+
+
+ )}
+ {Boolean(resizing) && (
+
+
+ {resizing?.width}
+ {" × "}
+ {resizing?.height}
+
+
+ )}
+
+ {isSVG ? (
+
+ ) : null}
{
setResizing({ width, height });
}}
@@ -127,65 +228,6 @@ export function ImageComponent(
editor.commands.setImageSize({ width, height });
}}
>
-
- {selected && (
-
-
-
- )}
- {Boolean(resizing) && (
-
-
- {resizing?.width}
- {" × "}
- {resizing?.height}
-
-
- )}
-
{progress ? (
{
const { hash, filename, mime, size } = node.attrs;
@@ -312,6 +364,47 @@ export function ImageComponent(
onLoad={async function onLoad() {
if (!imageRef.current) return;
+ // For SVGs rendered as iframes, naturalWidth/naturalHeight are 0.
+ // Read the viewBox from the SVG contentDocument instead.
+ if (isSVG) {
+ try {
+ const iframe = imageRef.current as unknown as HTMLIFrameElement;
+ const svgEl =
+ iframe.contentDocument?.querySelector("svg");
+ const viewBox = svgEl?.getAttribute("viewBox");
+ if (viewBox) {
+ const parts = viewBox.split(/[\s,]+/).map(Number);
+ if (parts.length === 4 && parts[2] > 0 && parts[3] > 0) {
+ const svgAspectRatio = parts[2] / parts[3];
+ if (
+ !aspectRatio ||
+ Math.abs(aspectRatio - svgAspectRatio) > 0.01
+ ) {
+ const fixedDimensions = fixAspectRatio(
+ size.width ?? 0,
+ svgAspectRatio
+ );
+ await editor.threadsafe((editor) =>
+ editor.commands.updateAttachment(
+ {
+ ...fixedDimensions,
+ aspectRatio: svgAspectRatio
+ },
+ {
+ query: makeImageQuery(src, hash),
+ ignoreEdit: true
+ }
+ )
+ );
+ }
+ }
+ }
+ } catch {
+ // cross-origin or missing contentDocument — skip
+ }
+ return;
+ }
+
const { naturalWidth, naturalHeight, clientHeight, clientWidth } =
imageRef.current;
const originalWidth = naturalWidth || clientWidth;
@@ -389,7 +482,8 @@ function canParse(src: string) {
function clampSize(
size: { width?: number; height?: number },
maxWidth: number,
- aspectRatio?: number
+ aspectRatio?: number,
+ isSVG?: boolean
): { width: number; height: number } {
if (typeof aspectRatio === "string" && isNaN(aspectRatio)) aspectRatio = 1;
@@ -398,6 +492,10 @@ function clampSize(
if (!aspectRatio) aspectRatio = size.width / size.height;
+ // SVGs (especially infinite canvas exports from OneNote) should preserve
+ // their original dimensions. The container handles overflow via scrolling.
+ if (isSVG) return { width: size.width, height: size.height };
+
if (size.width > maxWidth)
return { width: maxWidth, height: maxWidth / aspectRatio };