noeloconnell / quill-image-uploader Goto Github PK
View Code? Open in Web Editor NEWA module for Quill rich text editor to allow images to be uploaded to a server instead of being base64 encoded
License: MIT License
A module for Quill rich text editor to allow images to be uploaded to a server instead of being base64 encoded
License: MIT License
When you copy/paste HTML into Quill, and the pasted HTML has an image that has a src
that is a data URL, then this module doesn't properly upload the image.
Screencast of this issue in action: http://somup.com/cYQjrwXZPy
Admittedly, this issue is not as common, because most images on the internet don't have src
attribute values that are data URLs, but it still needs fixing.
Hello, first of all thanks for this module.
I know this is probably not the right place for this - but can you please refer me to an example of implementing this module with React-Quill?
Thanks in advance.
It appears that the package is licensed MIT in the package.json, but there's no full license file specifying the copyright owner and year(s) along with the text of the license. Could you add one please? Thank you!
Hi! 👋
Firstly, thanks for your work on this project! 🙂
Today I used patch-package to patch [email protected]
for the project I'm working on.
I need to select multiple image files. I tried this solution. Maybe it's incomplete, but it worked.
Here is the diff that solved my problem:
diff --git a/node_modules/quill-image-uploader/src/quill.imageUploader.js b/node_modules/quill-image-uploader/src/quill.imageUploader.js
index 58fb063..fc72f38 100644
--- a/node_modules/quill-image-uploader/src/quill.imageUploader.js
+++ b/node_modules/quill-image-uploader/src/quill.imageUploader.js
@@ -29,6 +29,7 @@ class ImageUploader {
this.fileHolder = document.createElement("input");
this.fileHolder.setAttribute("type", "file");
this.fileHolder.setAttribute("accept", "image/*");
+ this.fileHolder.setAttribute("multiple", "");
this.fileHolder.setAttribute("style", "visibility:hidden");
this.fileHolder.onchange = this.fileChanged.bind(this);
@@ -146,8 +147,9 @@ class ImageUploader {
}
fileChanged() {
- const file = this.fileHolder.files[0];
- this.readAndUploadFile(file);
+ for (const file of this.fileHolder.files) {
+ this.readAndUploadFile(file);
+ }
}
insertBase64Image(url) {
This issue body was partially generated by patch-package.
open the example codesandbox and just paste a image.
https://codesandbox.io/s/mutable-tdd-lrsvh?file=/index.html
quill-image-uploader/src/quill.imageUploader.js
Lines 99 to 102 in 98907e3
this.quill.getSelection()
returns null, but works well on chromuim 102.0.5005.115
Cannot Import modules/ImageUploader when using script tag.
I found this issue because the image uploader does not register yet into quill. So I try to add below code before initiate quill object
Quill.register('modules/ImageUploader', ImageUploader, true);
I am Sorry, I don't open the example in sanbox, because the quill.register has added in the example in code sanbox.
Thanks so much for making such a useful little plugin, it is awesome.
I have encountered an issue while trying to use with react-quill wrapper. For some reason if you turn it into a controlled component and updated the value via onChange function of react-quill something brakes.
From console.logs I figured that the image gets stuck on base64 representation and then does not reach the next step of being deleted, and re-inserted as an img tag.
Here is a forked version of code sandbox
If you try to upload the image it will not work.
Thanks so much for working on this!
If I am totally missing something please point this poor soul towards it, haha :)
The recently released version doesn't show loader in React Quill Editor.
Paste from Word is making a photo instead of pasting just text. This happen only on Google Chrome
setup: () => {
const modules = [{
name: 'imageUploader',
module: ImageUploader,
options: {
upload: file => {
return new Promise((resolve, reject) => {
let Image = Quill.import('formats/image');
Image.className = 'img-fluid';
Quill.register(Image, true);
const formData = new FormData();
formData.append("image", file);
axios({
url: '/api/upload-image',
method: 'POST',
data: formData
}).then((result) => {
resolve(result.data.url);
let url = result.data.url;
}).catch((err) => {
reject("Upload failed");
console.error("Error:", error);
})
});
}
}
}
]
return {modules}
},
I followed the example for react-quill. I have:
import 'react-quill/dist/quill.snow.css'
import ImageUploader from 'quill-image-uploader'
import ReactQuill, { Quill } from 'react-quill'
Quill.register('modules/imageUploader', ImageUploader)
and when I add imageUploader
to modules
the component doesn't render.
Hi, i have successfully embedded this script, but the url is being misformed like this:
DELTA OK and readable:
{"ops":[{"insert":"Hello World!"},{"insert":{"image":"https://domain/1_2022-09-20_15:18:31.jpeg"}},{"insert":"\nSome initial "},{"attributes":{"bold":true},"insert":"bold"},{"insert":" text\n"}]}
HTML:
"<p>Hello World!<img src=\"https:/domain/1_2022-09-20_15:18:31.jpeg\"></p><p>Some initial <strong>bold</strong> text</p>"
So the image is added like this:
<img src=[\"https:/domain/1_2022-09-20_16:00:10.jpeg\"](https://domain/%22https://domain/1_2022-09-20_16:00:10.jpeg/%22)>
How do i get rid of the extra domain in the front and the %22 ?
ERROR from console
https://domain/%22https:/domain/1_2022-09-20_16:00:10.jpeg/%22/ 404
See here for demo
https://www.loom.com/share/6be7f1acb77147e8ba9e019607927c8c
When typing on the line of an uploading image blot, it creates duplicate loader blots.
Hi everyone,
I have a question about how to insert custom attributes (ex:dataset) into img tag?
const editorOption = {
modules: [
{
name: "ImageUploader",
module: ImageUploader,
options: {
upload: (file) => {
return new Promise((resolve, reject) => {
const formData = new FormData();
formData.append("file", file);
formData.append("user_id", "180f891d-2dda-4fa1-8280-35de6cbd0e0b");
const config: any = {
headers: {
"Content-Type": "multipart/form-data"
}
};
axios
.post(
"https://dev.intelliances.com/broker/medical/v2/gcs/upload",
formData,
config
)
.then((res) => {
resolve(res.data.data.target_url);
})
.catch((err) => {
console.log(err);
});
});
},
}
}
]
};
It would be good to know from docs about the necessity of formats: ['imageBlot']
. And that resolving upload promise immediately will not work.
Hello,
I will start by a Thanks for this module, using it on quill v1 for some months now.
Do you have any prevision for a compatiblity with QuillJS V2 ? (in RC2 when I write this message), I can not install as the package.json won't allow it, as quill is marked as compatible with ^1.3.7, so the v2 is out of range.
Thanks.
I want to use this on a simple Html/JS page. I've tried fiddling with it but it doesn't seem to work.
Also if I want to use it in a browser how do I set the uploadURL?
Thanks!
The following line requires a custom Webpack configuration:
This is the output of an Angular 15 production build:
> ./node_modules/quill-image-uploader/src/quill.imageUploader.css:1:0 - Error: Module parse failed: Unexpected token (1:0)
> You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> > .image-uploading {
> | position: relative;
> | display: inline-block;
We would like to discuss if there is a better solution that does not require a custom Webpack loader / configuration.
Looking forward to hearing your thoughts. Thank you!
Hello,
When I make an upload fail (for instance the file uploaded is too big), the placeholder image will stay with the loading animation. I can take care myself of the user notification and I think it should be the case for everybody, but I would like the placeholder image to be removed if the upload didn't worked.
Thanks
Hi,
After uploading image to the server. We get url of the img, So Instead of resolving it directly I wanted to send some extra information along with header in the GET request for the Image URL. How to do it ?
Thanks for the Quill module!
We noticed that the image upload functionality didn't work in our application nor the demo file. I haven't been able to figure out why as we're transpiling everything on our end. I was able to trace IE11's execution all the way up to line 28 in quill.imageUploader.js
:
this.fileHolder.click();
After this line, nothing else executes. I considered that IE11 might have trouble programmatically clicking a file input element, but I saw this same functionality working in some other examples. Any ideas?
When using Google Chrome, click and drag a image creates a copy of it
Expected behaviour:
Moves a image when click and drag
Current behaviour:
Creates a copy of the dragged image.
Plataform:
Google Chrome v96.0.4664.45
If you guys have time, I would strongly urge you all to refactor to typescript, as to not use typescript in libraries like this places a burden on those who use typescript in their projects.
Also, as a general coding principle not specific to javascript or typescript, code that isn't typed in any language is not good code (unless the code is so simple that it does not need to be typed, but this would not be the case for this library)
remove image file from storage when image being remove in editor
Using [email protected]
, when pasting an image from clipboard using Google Chrome, I get an error:
Uncaught (in promise) TypeError: Cannot read properties of null (reading 'index')
at e.value (quill.imageUploader.min.js:1:5838)
at quill.imageUploader.min.js:1:5464
which seems to be this.range
being null
at insertToEditor
.
This issue appears with different users, but only seems to appear in the browser Google Chrome.
everything seems to work fine, however once I install this library, i am no longer able to drag images from the web.
so if i go on google images and drag and drop and image into the editor, it will not work.
When we try to upload the image in between words or letters in ReactQuill Editor, after Image upload it trims 3 characters exactly every time in the editor and it is replaced by Image.
Please support upload image after paste action.
If someone use react-quill
, they would find that loading
can not see, the solution is that add imageBlot
to config -> formats
formats: [
'alt',
'height',
'width',
'style',
// 'size',
// 'header',
'bold',
'imageBlot',
// 'align',
'italic',
'underline',
// 'strike',
// 'blockquote',
// 'list',
// 'script',
// 'bullet',
// 'indent',
// 'link',
'image'
],
thank you for your work!!
<ReactQuill theme="snow" value={dmText} modules={quill_modules} placeholder={'Enter your post text here'} />
and for my quill_module definition
const quill_modules = {
toolbar: [
["bold", "italic", "image"],
],
imageUploader: {
upload: file => {
return new Promise((resolve, reject) => {
const formData = new FormData();
formData.append("image", file);
fetch(
"https://api.imgbb.com/1/upload?key=d36eb6591370ae7f9089d85875e56b22",
{
method: "POST",
body: formData
}
)
.then(response => response.json())
.then(result => {
console.log("Upload result", result);
resolve(result.data.url);
})
.catch(error => {
reject("Upload failed");
console.error("Error:", error);
});
});
}
}
};
Me eyes are telling me this is the EXACT example used in the React Quill Demo and I get this everytime (both button and drag and drop)
Image upload looks good (final result being resolved to resolve()
is https://i.ibb.co/3TqP7wx/googlelogo-color-272x92dp.png
What could I be doing wrong?
Hi there,
The module you wrote looks really really nice! I'm just wondering if it's possible to add a callback function that allows us to customize the behavior right after inserting the image(after this line: this.quill.insertEmbed()), since the editor on our platform has a default format requirement for the images that inserted. It would be really convenient if there's an optional callback function there, or else I need to implement the whole module all by self 😢
Or add an option to allows customizing the inserting event function works for me too~
Still a newbie to the community, pardon me if my english is not good.
Cheers!
Sir, Thank you very much for your open source contribution, found no tag when use your dependencies, can you release a version with tag? like vue.js(https://github.com/vuejs/core)
Hi,
When I try to add the image at the beginning of the text editor, If there are already any texts/words are present then it will trim the first character of that word/texts. It happens only when we add an image in the beginning. It doesn't trim character if you add the image in the middle of some words/sentences or at the end of the words. This issue is already there in the sandbox code of the QuillImageUpload.
so in the demo there is a blurred version of the image with a spinner
but that doesn't show.
my question is how to add a loading state?
Hello,
In some cases, inserting an image remove some text after the image. For example if i try to insert an image between two word, the second word will disappears. I think it's related to the insertToEditor
function that call this.quill.deleteText(range.index, 2);
to delete the placeholder image.
Thanks
Hi,
I'm trying to use this module but for some reason the File Window is not opening:
As far as I can debug, I think it has something to do with this code:
document.body.appendChild(this.fileHolder);
window.requestAnimationFrame(() => {
this.fileHolder.click(); // <-- this is not triggering
window.requestAnimationFrame(() => {
document.body.removeChild(this.fileHolder);
});
});
If I remove the requestAnimationFrame
like this:
document.body.appendChild(this.fileHolder);
this.fileHolder.click();
now it works correctly, the file window shows-up. Is there any reason why requestAnimationFrame
is preventing to show the File Window? Thanks.
The declaration file for module 'quill-image-uploader' cannot be found.
hey Noel,
Could you set the source to user
when using insertEmbed here?
https://github.com/NoelOConnell/quill-image-uploader/blob/master/src/quill.imageUploader.js#L81
I'm using this plugin (it's great — thanks!) with ngx-quill (angular wrapper). The issue we've identified is if you upload an image using this plugin, you'll see it in the editor … but if we save the image is missing. I think ngx-quill does not pass the latest editor contents through, because the image insert isn't flagged as a user change. I'm guessing that means quill doesn't trigger the event that ngx-quill relies on.
I'm going off the explanation of user source here: https://quilljs.com/docs/api/#text-change
Changes may occur through an API but as long as they originate from the user, the provided source should still be "user". For example, when a user clicks on the toolbar, technically the toolbar module calls a Quill API to effect the change. But source is still "user" since the origin of the change was the user’s click.
APIs causing text to change may also be called with a "silent" source, in which case text-change will not be emitted. This is not recommended as it will likely break the undo stack and other functions that rely on a full record of text changes.
I think user is a good choice, but if you want to keep it open perhaps it could be a config setting?
Happy to send a PR if that helps.
cheers
Ben
I added the following code to my app
imageUploader: {
upload: async (file) => {
if (!this.$utils.checkUploadFileSize(file)) { // If over 1MB
this.$snackbar.show("can not upload file over 1MB");
return "/img/no-image.png";
}
return await storage.articleImage.upload(file);
},
},
If file size is over 1MB, then I want the behavior as below
<img src="/img/no-image.png">
But the image-loader dosen't disappear (and it appears forever).
Because quill-image-uploader seems to need seconds delay before return path.
I want to return path with no delay.
Hey there, a great quill module, thanks for it!
The problem
One thing I ran into while developing an app with react in webpack: you depend on global Quill var to register the module to.
Proposal
Since you are using es6 import/export, wouldn't it make more sense to export the module and let the user to register the module?
export default ImageUploader;
import Quill from 'quill';
import ImageUploader 'quill-image-uploader';
Quill.register('module/imageUploader, ImageUploader)
Note
I can fork the repo and make PR if you dont have time but want the feature :).
<QuillEditor
v-model:content="form.content"
:toolbar="toolbar"
:modules="modules"
ref="qlEditorRef"
content-type="html"
theme="snow"
style="height: 250px; overflow: hidden;"
/>
import { QuillEditor } from '@vueup/vue-quill'
import BlotFormatter from 'quill-blot-formatter';
import ImageUploader from "quill-image-uploader";
import '@vueup/vue-quill/dist/vue-quill.snow.css';
const toolbar = [
[{ 'align': [ '', 'center', 'right', 'justify'] }],
['image']
]
const modules = [
{
name: 'imageUploader',
module: ImageUploader,
options: {
name: 'image',
upload: file => {
console.log(file)
return new Promise((resolve, reject)=>{
setTimeout(() => {
resolve('https://bt-hangzhou.oss-cn-hangzhou.aliyuncs.com/jungong/20230627/test2a341f04c96084c0e8775d78361be088b.jpg')
}, 3500);
})
}
}
}
]
"quill": "^1.3.7",
"quill-blot-formatter": "^1.0.5",
"quill-image-uploader": "^1.3.0",
报这个错怎么解决,救救我
i am adding quill as client plugin and it works good but i cant add this module for it:
QuillEditor.client.ts
import { defineNuxtPlugin } from "#app";
import { QuillEditor } from '@vueup/vue-quill'
export default defineNuxtPlugin(
nuxtApp => {
nuxtApp.vueApp.component('QuillEditor', QuillEditor);
})
main component code:
<template>
<client-only>
<QuillEditor :modules="modules" toolbar="full" />
</client-only>
</template>
<script>
import ImageUploader from 'quill-image-uploader';
export default ({
setup: () => {
const modules = {
name: 'imageUploader',
module: ImageUploader,
options: {
upload: file => {
return new Promise((resolve, reject) => {
const formData = new FormData();
formData.append("image", file);
$fetch.post('/upload-image', formData)
.then(res => {
console.log(res)
resolve(res.data.url);
})
.catch(err => {
reject("Upload failed");
console.error("Error:", err)
})
})
}
}
};
return { modules }
}
})
</script>
I have tried to reject the promise, but it still upload the picture with base64 string.
I'm uploading images with ImageUploader and using 'Undo' and 'Redo' buttons from Quill Toolbar.
And it turns out that the image gets into the history stack when it is in the loading state. Thats why I'm getting permanent loading image when navigating via 'Undo' and 'Redo' buttons from Quill Toolbar.
Is there a possibility to change source when inserting loading image?
Did anyone get to run jest test successfully in a component that imports quill-image-uploader
?
Test suite failed to run
({"Object.":function(module,exports,require,__dirname,__filename,global,jest){import './blots/image';
^^^^^^^^^^^^^^^
SyntaxError: Unexpected string
3 | import { connect } from 'react-redux'
4 | import ReactQuill, { Quill } from 'react-quill'
5 | import ImageUploader from 'quill-image-uploader'
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.