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
This commit is contained in:
Ammar Ahmed
2026-06-04 13:16:51 +05:00
committed by GitHub
parent 5ddf1eddf5
commit a820fcde53

View File

@@ -17,17 +17,17 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
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<EmbedSource>("url");
const [error, setError] = useState<string | null>(null);
const [size, setSize] = useState<EmbedSizeOptions>({
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)