From a820fcde5304bc6e99867ebe3e51eb418aa74964 Mon Sep 17 00:00:00 2001
From: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com>
Date: Thu, 4 Jun 2026 13:16:51 +0500
Subject: [PATCH] editor: allow any width/height value in EmbedSizeOptions when
inserting embed (#9925)
* editor: allow any width/height value in EmbedSizeOptions when inserting embeds
* editor: only accept valid url as value
* editor: allow embeding normal website urls
* editor: check url if embedSource=url
* editor: use defaultValue prop for width/height
---
.../editor/src/toolbar/popups/embed-popup.tsx | 73 +++++++++++--------
1 file changed, 41 insertions(+), 32 deletions(-)
diff --git a/packages/editor/src/toolbar/popups/embed-popup.tsx b/packages/editor/src/toolbar/popups/embed-popup.tsx
index cb634952b..52747e407 100644
--- a/packages/editor/src/toolbar/popups/embed-popup.tsx
+++ b/packages/editor/src/toolbar/popups/embed-popup.tsx
@@ -17,17 +17,17 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
-import { Flex, Text } from "@theme-ui/components";
-import { useCallback, useState } from "react";
-import { Popup } from "../components/popup.js";
-import { Input, Textarea } from "@theme-ui/components";
-import { Embed, EmbedSizeOptions } from "../../extensions/embed/index.js";
-import { convertUrlToEmbedUrl } from "@social-embed/lib";
-import { InlineInput } from "../../components/inline-input/index.js";
-import { Tabs, Tab } from "../../components/tabs/index.js";
import { strings } from "@notesnook/intl";
+import { convertUrlToEmbedUrl, isValidUrl } from "@social-embed/lib";
+import { Flex, Input, Text, Textarea } from "@theme-ui/components";
+import { useCallback, useState } from "react";
+import { InlineInput } from "../../components/inline-input/index.js";
+import { Tab, Tabs } from "../../components/tabs/index.js";
+import { Embed, EmbedSizeOptions } from "../../extensions/embed/index.js";
+import { Popup } from "../components/popup.js";
type EmbedSource = "url" | "code";
+
export type EmbedPopupProps = {
onClose: (embed?: Embed) => void;
title: string;
@@ -38,33 +38,30 @@ export type EmbedPopupProps = {
export function EmbedPopup(props: EmbedPopupProps) {
const { onClose, onSizeChanged, title, embed } = props;
- const [width, setWidth] = useState(embed?.width || 300);
- const [height, setHeight] = useState(embed?.height || 150);
const [src, setSrc] = useState(embed?.src || "");
const [embedSource, setEmbedSource] = useState("url");
const [error, setError] = useState(null);
+ const [size, setSize] = useState({
+ width: embed?.width || 300,
+ height: embed?.height || 150
+ });
const onSizeChange = useCallback(
(newWidth?: number, newHeight?: number) => {
- const size: EmbedSizeOptions = newWidth
- ? {
- width: newWidth,
- height: newWidth * (height / width)
- }
- : newHeight
- ? {
- width: newHeight * (width / height),
- height: newHeight
- }
- : {
- width: 0,
- height: 0
- };
- setWidth(size.width);
- setHeight(size.height);
- if (onSizeChanged) onSizeChanged(size);
+ const hasNewWidth = Number.isFinite(newWidth);
+ const hasNewHeight = Number.isFinite(newHeight);
+
+ if (!hasNewWidth && !hasNewHeight) return;
+ setSize((size) => {
+ const newSize = {
+ width: hasNewWidth ? ((newWidth || 0) as number) : size.width,
+ height: hasNewHeight ? ((newHeight || 0) as number) : size.height
+ };
+ if (onSizeChanged) onSizeChanged(newSize);
+ return newSize;
+ });
},
- [height, width, onSizeChanged]
+ [onSizeChanged]
);
return (
@@ -77,8 +74,9 @@ export function EmbedPopup(props: EmbedPopupProps) {
onClick: () => {
setError(null);
let _src = src;
- let _width = width;
- let _height = height;
+ let _width = size.width;
+ let _height = size.height;
+
if (embedSource === "code") {
const document = new DOMParser().parseFromString(src, "text/html");
if (document.getElementsByTagName("iframe").length <= 0)
@@ -100,8 +98,19 @@ export function EmbedPopup(props: EmbedPopupProps) {
if (heightValue && !isNaN(parseInt(heightValue)))
_height = parseInt(heightValue);
}
+
+ if (embedSource === "url" && !isValidUrl(src)) {
+ return setError("Please provide a valid url.");
+ }
+
const convertedUrl = convertUrlToEmbedUrl(_src);
+
if (convertedUrl) _src = convertedUrl;
+
+ if (!_src && embedSource === "url") {
+ return setError("Please provide a valid embed url.");
+ }
+
if (_src.startsWith("javascript:")) {
return setError("Embedding javascript code is not supported.");
}
@@ -147,7 +156,7 @@ export function EmbedPopup(props: EmbedPopupProps) {
label="width"
type="number"
placeholder={strings.width()}
- value={width}
+ defaultValue={size.width}
sx={{
mr: 1,
fontSize: "body"
@@ -158,7 +167,7 @@ export function EmbedPopup(props: EmbedPopupProps) {
label="height"
type="number"
placeholder={strings.height()}
- value={height}
+ defaultValue={size.height}
sx={{ fontSize: "body" }}
onChange={(e) =>
onSizeChange(undefined, e.target.valueAsNumber)