Skip to content

Commit

Permalink
fix: prevent file system D&D, C&P, upload if no uploadImageHandler (#549
Browse files Browse the repository at this point in the history
)

* Removed uploadImageHandler from ImageWithNoBackend example

* Drag and paste, block file system but allow web

* Allow ImageDialog to accept links

* fix: drag and drop of images from the web

---------

Co-authored-by: Petyo Ivanov <underlog@gmail.com>
  • Loading branch information
rissois and petyosi authored Jul 24, 2024
1 parent 10bd8d7 commit 71daa82
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 49 deletions.
4 changes: 1 addition & 3 deletions src/examples/images.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ export const ImageWithNoBackend: Story<{ readOnly: boolean }> = () => {
<MDXEditor
markdown=""
plugins={[
imagePlugin({
imageUploadHandler: expressImageUploadHandler
}),
imagePlugin(),
diffSourcePlugin(),
toolbarPlugin({
toolbarContents: () => (
Expand Down
4 changes: 3 additions & 1 deletion src/plugins/image/ImageDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ export const ImageDialog: React.FC = () => {
}}
className={styles.multiFieldForm}
>
{imageUploadHandler !== null && (
{imageUploadHandler === null ? (
<input type="hidden" accept="image/*" {...register('file')} />
) : (
<div className={styles.formField}>
<label htmlFor="file">{t('uploadImage.uploadInstructions', 'Upload an image from your device:')}</label>
<input type="file" accept="image/*" {...register('file')} />
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/image/ImageNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ export class ImageNode extends DecoratorNode<JSX.Element> {
this.__src = src
this.__title = title
this.__altText = altText
this.__width = width ?? 'inherit'
this.__height = height ?? 'inherit'
this.__width = width ? width : 'inherit'
this.__height = height ? height : 'inherit'
}

/** @internal */
Expand Down
91 changes: 48 additions & 43 deletions src/plugins/image/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,17 +221,14 @@ export const imageDialogState$ = Cell<InactiveImageDialogState | NewImageDialogS
editor.registerCommand<DragEvent>(
DRAGSTART_COMMAND,
(event) => {
if (!theUploadHandler) {
return false
}
return onDragStart(event)
},
COMMAND_PRIORITY_HIGH
),
editor.registerCommand<DragEvent>(
DRAGOVER_COMMAND,
(event) => {
return onDragover(event)
return onDragover(event, !!theUploadHandler)
},
COMMAND_PRIORITY_LOW
),
Expand All @@ -243,38 +240,44 @@ export const imageDialogState$ = Cell<InactiveImageDialogState | NewImageDialogS
},
COMMAND_PRIORITY_HIGH
),
...(theUploadHandler !== null
? [
editor.registerCommand(
PASTE_COMMAND,
(event: ClipboardEvent) => {
let cbPayload = Array.from(event.clipboardData?.items ?? [])
cbPayload = cbPayload.filter((i) => i.type.includes('image')) // Strip out the non-image bits

if (!cbPayload.length || cbPayload.length === 0) {
return false
} // If no image was present in the collection, bail.

const imageUploadHandlerValue = r.getValue(imageUploadHandler$)!

Promise.all(cbPayload.map((file) => imageUploadHandlerValue(file.getAsFile()!)))
.then((urls) => {
urls.forEach((url) => {
editor.dispatchCommand(INSERT_IMAGE_COMMAND, {
src: url,
altText: ''
})
})
})
.catch((e: unknown) => {
throw e
})
return true
},
COMMAND_PRIORITY_CRITICAL
)
]
: [])
editor.registerCommand(
PASTE_COMMAND,
(event: ClipboardEvent) => {
if (!theUploadHandler) {
let fromWeb = Array.from(event.clipboardData?.items ?? [])
fromWeb = fromWeb.filter((i) => i.type.includes('text')) // Strip out the non-image bits

if (!fromWeb.length || fromWeb.length === 0) {
return true
} // If from file system, eject without calling imageUploadHandler.
return false // If from web, bail.
}

let cbPayload = Array.from(event.clipboardData?.items ?? [])
cbPayload = cbPayload.filter((i) => i.type.includes('image')) // Strip out the non-image bits

if (!cbPayload.length || cbPayload.length === 0) {
return false
} // If no image was present in the collection, bail.

const imageUploadHandlerValue = r.getValue(imageUploadHandler$)!

Promise.all(cbPayload.map((file) => imageUploadHandlerValue(file.getAsFile()!)))
.then((urls) => {
urls.forEach((url) => {
editor.dispatchCommand(INSERT_IMAGE_COMMAND, {
src: url,
altText: ''
})
})
})
.catch((e: unknown) => {
throw e
})
return true
},
COMMAND_PRIORITY_CRITICAL
)
)
})
}
Expand Down Expand Up @@ -395,14 +398,16 @@ function onDragStart(event: DragEvent): boolean {
return true
}

function onDragover(event: DragEvent): boolean {
// test if the user is dragging a file from the explorer
let cbPayload = Array.from(event.dataTransfer?.items ?? [])
cbPayload = cbPayload.filter((i) => i.type.includes('image')) // Strip out the non-image bits
function onDragover(event: DragEvent, hasUploadHandler: boolean): boolean {
if (hasUploadHandler) {
// test if the user is dragging a file from the explorer
let cbPayload = Array.from(event.dataTransfer?.items ?? [])
cbPayload = cbPayload.filter((i) => i.type.includes('image')) // Strip out the non-image bits

if (cbPayload.length > 0) {
event.preventDefault()
return true
if (cbPayload.length > 0) {
event.preventDefault()
return true
}
}

// handle moving images
Expand Down

0 comments on commit 71daa82

Please sign in to comment.