@writergate/quill-image-uploader-nextjs 0.0.3 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.babelrc CHANGED
@@ -1,14 +1,14 @@
1
- {
2
- "presets": [
3
- [
4
- "env",
5
- {
6
- "targets": {
7
- "browsers": ["last 3 versions", "safari >= 6"]
8
- },
9
- "modules": false
10
- }
11
- ]
12
- ],
13
- "plugins": []
14
- }
1
+ {
2
+ "presets": [
3
+ [
4
+ "env",
5
+ {
6
+ "targets": {
7
+ "browsers": ["last 3 versions", "safari >= 6"]
8
+ },
9
+ "modules": false
10
+ }
11
+ ]
12
+ ],
13
+ "plugins": []
14
+ }
@@ -1,3 +1,3 @@
1
- {
2
- "eslint.enable": false
1
+ {
2
+ "eslint.enable": false
3
3
  }
package/README.md CHANGED
@@ -1,58 +1,58 @@
1
- # Quill ImageHandler Module for NextJS
2
-
3
- A modifed alternative of [Quill Image Upload Plugin](https://github.com/noeloconnell/quill-image-uploader) to support NextJS
4
-
5
- The original plugin uses css import in node_modules, which is not supported by the latest NextJS.
6
-
7
- ## Credits
8
- The full credit for the editor plugin goes to [Quill Image Upload Plugin](https://github.com/noeloconnell/quill-image-uploader) and this is a modificaion to support the NextJS.
9
-
10
- Therefore, keep upto date on its issue tracker whether the issue is fixed.
11
-
12
- ### Install
13
-
14
- Install with npm:
15
-
16
- ```bash
17
- npm install @writergate/quill-image-uploader-nextjs --save
18
- ```
19
-
20
- ### Webpack/ES6
21
-
22
- ```javascript
23
- import Quill from "quill";
24
- import ImageUploader from "quill.imageUploader.js";
25
- import '@writergate/dist/quill.imageUploader.min.css';
26
-
27
- Quill.register("modules/imageUploader", ImageUploader);
28
-
29
- const quill = new Quill(editor, {
30
- // ...
31
- modules: {
32
- // ...
33
- imageUploader: {
34
- upload: (file) => {
35
- return new Promise((resolve, reject) => {
36
- setTimeout(() => {
37
- resolve(
38
- "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/JavaScript-logo.png/480px-JavaScript-logo.png"
39
- );
40
- }, 3500);
41
- });
42
- },
43
- },
44
- },
45
- });
46
- ```
47
- **Note**: It's also important that you create a quill component and dynamically import the component with SSR: false for NextJS.
48
-
49
- e.g: No SSR Editor component includes all the above code.
50
-
51
- ```javascript
52
-
53
- const QuillNoSSR = dynamic(
54
- () => import('src/components/no-ssr-editor').then(md => md.default),
55
- { ssr: false }
56
- );
57
-
1
+ # Quill ImageHandler Module for NextJS
2
+
3
+ A modifed alternative of [Quill Image Upload Plugin](https://github.com/noeloconnell/quill-image-uploader) to support NextJS
4
+
5
+ The original plugin uses css import in node_modules, which is not supported by the latest NextJS.
6
+
7
+ ## Credits
8
+ The full credit for the editor plugin goes to [Quill Image Upload Plugin](https://github.com/noeloconnell/quill-image-uploader) and this is a modificaion to support the NextJS.
9
+
10
+ Therefore, keep upto date on its issue tracker whether the issue is fixed.
11
+
12
+ ### Install
13
+
14
+ Install with npm:
15
+
16
+ ```bash
17
+ npm install @writergate/quill-image-uploader-nextjs --save
18
+ ```
19
+
20
+ ### Webpack/ES6
21
+
22
+ ```javascript
23
+ import Quill from "quill";
24
+ import ImageUploader from "quill.imageUploader.js";
25
+ import '@writergate/quill-image-uploader-nextjs/dist/quill.imageUploader.min.css';
26
+
27
+ Quill.register("modules/imageUploader", ImageUploader);
28
+
29
+ const quill = new Quill(editor, {
30
+ // ...
31
+ modules: {
32
+ // ...
33
+ imageUploader: {
34
+ upload: (file) => {
35
+ return new Promise((resolve, reject) => {
36
+ setTimeout(() => {
37
+ resolve(
38
+ "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/JavaScript-logo.png/480px-JavaScript-logo.png"
39
+ );
40
+ }, 3500);
41
+ });
42
+ },
43
+ },
44
+ },
45
+ });
46
+ ```
47
+ **Note**: It's also important that you create a quill component and dynamically import the component with SSR: false for NextJS.
48
+
49
+ e.g: No SSR Editor component includes all the above code.
50
+
51
+ ```javascript
52
+
53
+ const QuillNoSSR = dynamic(
54
+ () => import('src/components/no-ssr-editor').then(md => md.default),
55
+ { ssr: false }
56
+ );
57
+
58
58
  ```
@@ -1,33 +1,33 @@
1
- .image-uploading {
2
- position: relative;
3
- display: inline-block;
4
- }
5
-
6
- .image-uploading img {
7
- max-width: 98% !important;
8
- filter: blur(5px);
9
- opacity: 0.3;
10
- }
11
-
12
- .image-uploading::before {
13
- content: "";
14
- box-sizing: border-box;
15
- position: absolute;
16
- top: 50%;
17
- left: 50%;
18
- width: 30px;
19
- height: 30px;
20
- margin-top: -15px;
21
- margin-left: -15px;
22
- border-radius: 50%;
23
- border: 3px solid #ccc;
24
- border-top-color: #1e986c;
25
- z-index: 1;
26
- animation: spinner 0.6s linear infinite;
27
- }
28
-
29
- @keyframes spinner {
30
- to {
31
- transform: rotate(360deg);
32
- }
33
- }
1
+ .image-uploading {
2
+ position: relative;
3
+ display: inline-block;
4
+ }
5
+
6
+ .image-uploading img {
7
+ max-width: 98% !important;
8
+ filter: blur(5px);
9
+ opacity: 0.3;
10
+ }
11
+
12
+ .image-uploading::before {
13
+ content: "";
14
+ box-sizing: border-box;
15
+ position: absolute;
16
+ top: 50%;
17
+ left: 50%;
18
+ width: 30px;
19
+ height: 30px;
20
+ margin-top: -15px;
21
+ margin-left: -15px;
22
+ border-radius: 50%;
23
+ border: 3px solid #ccc;
24
+ border-top-color: #1e986c;
25
+ z-index: 1;
26
+ animation: spinner 0.6s linear infinite;
27
+ }
28
+
29
+ @keyframes spinner {
30
+ to {
31
+ transform: rotate(360deg);
32
+ }
33
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@writergate/quill-image-uploader-nextjs",
3
- "version": "0.0.3",
3
+ "version": "0.0.7",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/enlear/quill-image-uploader-nextjs.git"
@@ -1,30 +1,30 @@
1
- import Quill from "quill";
2
-
3
- const InlineBlot = Quill.import("blots/block");
4
-
5
- class LoadingImage extends InlineBlot {
6
- static create(src) {
7
- const node = super.create(src);
8
- if (src === true) return node;
9
-
10
- const image = document.createElement("img");
11
- image.setAttribute("src", src);
12
- node.appendChild(image);
13
- return node;
14
- }
15
- deleteAt(index, length) {
16
- super.deleteAt(index, length);
17
- this.cache = {};
18
- }
19
- static value(domNode) {
20
- const { src, custom } = domNode.dataset;
21
- return { src, custom };
22
- }
23
- }
24
-
25
- LoadingImage.blotName = "imageBlot";
26
- LoadingImage.className = "image-uploading";
27
- LoadingImage.tagName = "span";
28
- Quill.register({ "formats/imageBlot": LoadingImage });
29
-
1
+ import Quill from "quill";
2
+
3
+ const InlineBlot = Quill.import("blots/block");
4
+
5
+ class LoadingImage extends InlineBlot {
6
+ static create(src) {
7
+ const node = super.create(src);
8
+ if (src === true) return node;
9
+
10
+ const image = document.createElement("img");
11
+ image.setAttribute("src", src);
12
+ node.appendChild(image);
13
+ return node;
14
+ }
15
+ deleteAt(index, length) {
16
+ super.deleteAt(index, length);
17
+ this.cache = {};
18
+ }
19
+ static value(domNode) {
20
+ const { src, custom } = domNode.dataset;
21
+ return { src, custom };
22
+ }
23
+ }
24
+
25
+ LoadingImage.blotName = "imageBlot";
26
+ LoadingImage.className = "image-uploading";
27
+ LoadingImage.tagName = "span";
28
+ Quill.register({ "formats/imageBlot": LoadingImage });
29
+
30
30
  export default LoadingImage;
package/src/demo.js CHANGED
@@ -1,66 +1,66 @@
1
- import Quill from "quill";
2
- import ImageUploader from "./quill.imageUploader.js";
3
-
4
- Quill.debug("warn");
5
- Quill.register("modules/imageUploader", ImageUploader);
6
-
7
- const fullToolbarOptions = [
8
- [{ header: [1, 2, 3, false] }],
9
- ["bold", "italic"],
10
- ["clean"],
11
- ["image"],
12
- ];
13
- var quill = new Quill("#editor", {
14
- theme: "snow",
15
- modules: {
16
- toolbar: {
17
- container: fullToolbarOptions,
18
- },
19
- imageUploader: {
20
- upload: (file) => {
21
- const fileReader = new FileReader();
22
- return new Promise((resolve, reject) => {
23
- fileReader.addEventListener(
24
- "load",
25
- () => {
26
- let base64ImageSrc = fileReader.result;
27
- setTimeout(() => {
28
- resolve(base64ImageSrc);
29
- //reject('Issue uploading file');
30
- }, 1500);
31
- },
32
- false
33
- );
34
-
35
- if (file) {
36
- fileReader.readAsDataURL(file);
37
- } else {
38
- reject("No file selected");
39
- }
40
- });
41
- },
42
- },
43
- },
44
- });
45
-
46
- quill.on("text-change", function(delta, oldDelta, source) {
47
- if (source == "api") {
48
- console.log("An API call triggered this change.");
49
- } else if (source == "user") {
50
- console.log("A user action triggered this change.");
51
- }
52
- console.log(oldDelta, delta);
53
- });
54
-
55
- quill.on("selection-change", function(range, oldRange, source) {
56
- if (range) {
57
- if (range.length == 0) {
58
- console.log("User cursor is on", range.index);
59
- } else {
60
- var text = quill.getText(range.index, range.length);
61
- console.log("User has highlighted", text);
62
- }
63
- } else {
64
- console.log("Cursor not in the editor");
65
- }
1
+ import Quill from "quill";
2
+ import ImageUploader from "./quill.imageUploader.js";
3
+
4
+ Quill.debug("warn");
5
+ Quill.register("modules/imageUploader", ImageUploader);
6
+
7
+ const fullToolbarOptions = [
8
+ [{ header: [1, 2, 3, false] }],
9
+ ["bold", "italic"],
10
+ ["clean"],
11
+ ["image"],
12
+ ];
13
+ var quill = new Quill("#editor", {
14
+ theme: "snow",
15
+ modules: {
16
+ toolbar: {
17
+ container: fullToolbarOptions,
18
+ },
19
+ imageUploader: {
20
+ upload: (file) => {
21
+ const fileReader = new FileReader();
22
+ return new Promise((resolve, reject) => {
23
+ fileReader.addEventListener(
24
+ "load",
25
+ () => {
26
+ let base64ImageSrc = fileReader.result;
27
+ setTimeout(() => {
28
+ resolve(base64ImageSrc);
29
+ //reject('Issue uploading file');
30
+ }, 1500);
31
+ },
32
+ false
33
+ );
34
+
35
+ if (file) {
36
+ fileReader.readAsDataURL(file);
37
+ } else {
38
+ reject("No file selected");
39
+ }
40
+ });
41
+ },
42
+ },
43
+ },
44
+ });
45
+
46
+ quill.on("text-change", function(delta, oldDelta, source) {
47
+ if (source == "api") {
48
+ console.log("An API call triggered this change.");
49
+ } else if (source == "user") {
50
+ console.log("A user action triggered this change.");
51
+ }
52
+ console.log(oldDelta, delta);
53
+ });
54
+
55
+ quill.on("selection-change", function(range, oldRange, source) {
56
+ if (range) {
57
+ if (range.length == 0) {
58
+ console.log("User cursor is on", range.index);
59
+ } else {
60
+ var text = quill.getText(range.index, range.length);
61
+ console.log("User has highlighted", text);
62
+ }
63
+ } else {
64
+ console.log("Cursor not in the editor");
65
+ }
66
66
  });
@@ -1,33 +1,33 @@
1
- .image-uploading {
2
- position: relative;
3
- display: inline-block;
4
- }
5
-
6
- .image-uploading img {
7
- max-width: 98% !important;
8
- filter: blur(5px);
9
- opacity: 0.3;
10
- }
11
-
12
- .image-uploading::before {
13
- content: "";
14
- box-sizing: border-box;
15
- position: absolute;
16
- top: 50%;
17
- left: 50%;
18
- width: 30px;
19
- height: 30px;
20
- margin-top: -15px;
21
- margin-left: -15px;
22
- border-radius: 50%;
23
- border: 3px solid #ccc;
24
- border-top-color: #1e986c;
25
- z-index: 1;
26
- animation: spinner 0.6s linear infinite;
27
- }
28
-
29
- @keyframes spinner {
30
- to {
31
- transform: rotate(360deg);
32
- }
33
- }
1
+ .image-uploading {
2
+ position: relative;
3
+ display: inline-block;
4
+ }
5
+
6
+ .image-uploading img {
7
+ max-width: 98% !important;
8
+ filter: blur(5px);
9
+ opacity: 0.3;
10
+ }
11
+
12
+ .image-uploading::before {
13
+ content: "";
14
+ box-sizing: border-box;
15
+ position: absolute;
16
+ top: 50%;
17
+ left: 50%;
18
+ width: 30px;
19
+ height: 30px;
20
+ margin-top: -15px;
21
+ margin-left: -15px;
22
+ border-radius: 50%;
23
+ border: 3px solid #ccc;
24
+ border-top-color: #1e986c;
25
+ z-index: 1;
26
+ animation: spinner 0.6s linear infinite;
27
+ }
28
+
29
+ @keyframes spinner {
30
+ to {
31
+ transform: rotate(360deg);
32
+ }
33
+ }
@@ -1,174 +1,206 @@
1
- import LoadingImage from "./blots/image.js";
2
-
3
- class ImageUploader {
4
- constructor(quill, options) {
5
- this.quill = quill;
6
- this.options = options;
7
- this.range = null;
8
-
9
- if (typeof this.options.upload !== "function")
10
- console.warn(
11
- "[Missing config] upload function that returns a promise is required"
12
- );
13
-
14
- var toolbar = this.quill.getModule("toolbar");
15
- toolbar.addHandler("image", this.selectLocalImage.bind(this));
16
-
17
- this.handleDrop = this.handleDrop.bind(this);
18
- this.handlePaste = this.handlePaste.bind(this);
19
-
20
- this.quill.root.addEventListener("drop", this.handleDrop, false);
21
- this.quill.root.addEventListener("paste", this.handlePaste, false);
22
- }
23
-
24
- selectLocalImage() {
25
- this.range = this.quill.getSelection();
26
- this.fileHolder = document.createElement("input");
27
- this.fileHolder.setAttribute("type", "file");
28
- this.fileHolder.setAttribute("accept", "image/*");
29
- this.fileHolder.setAttribute("style", "visibility:hidden");
30
-
31
- this.fileHolder.onchange = this.fileChanged.bind(this);
32
-
33
- document.body.appendChild(this.fileHolder);
34
-
35
- this.fileHolder.click();
36
-
37
- window.requestAnimationFrame(() => {
38
- document.body.removeChild(this.fileHolder);
39
- });
40
- }
41
-
42
- handleDrop(evt) {
43
- evt.stopPropagation();
44
- evt.preventDefault();
45
- if (
46
- evt.dataTransfer &&
47
- evt.dataTransfer.files &&
48
- evt.dataTransfer.files.length
49
- ) {
50
- if (document.caretRangeFromPoint) {
51
- const selection = document.getSelection();
52
- const range = document.caretRangeFromPoint(evt.clientX, evt.clientY);
53
- if (selection && range) {
54
- selection.setBaseAndExtent(
55
- range.startContainer,
56
- range.startOffset,
57
- range.startContainer,
58
- range.startOffset
59
- );
60
- }
61
- } else {
62
- const selection = document.getSelection();
63
- const range = document.caretPositionFromPoint(evt.clientX, evt.clientY);
64
- if (selection && range) {
65
- selection.setBaseAndExtent(
66
- range.offsetNode,
67
- range.offset,
68
- range.offsetNode,
69
- range.offset
70
- );
71
- }
72
- }
73
-
74
- this.range = this.quill.getSelection();
75
- let file = evt.dataTransfer.files[0];
76
-
77
- setTimeout(() => {
78
- this.range = this.quill.getSelection();
79
- this.readAndUploadFile(file);
80
- }, 0);
81
- }
82
- }
83
-
84
- handlePaste(evt) {
85
- let clipboard = evt.clipboardData || window.clipboardData;
86
-
87
- // IE 11 is .files other browsers are .items
88
- if (clipboard && (clipboard.items || clipboard.files)) {
89
- let items = clipboard.items || clipboard.files;
90
- const IMAGE_MIME_REGEX = /^image\/(jpe?g|gif|png|svg|webp)$/i;
91
-
92
- for (let i = 0; i < items.length; i++) {
93
- if (IMAGE_MIME_REGEX.test(items[i].type)) {
94
- let file = items[i].getAsFile ? items[i].getAsFile() : items[i];
95
-
96
- if (file) {
97
- this.range = this.quill.getSelection();
98
- evt.preventDefault();
99
- setTimeout(() => {
100
- this.range = this.quill.getSelection();
101
- this.readAndUploadFile(file);
102
- }, 0);
103
- }
104
- }
105
- }
106
- }
107
- }
108
-
109
- readAndUploadFile(file) {
110
- let isUploadReject = false;
111
-
112
- const fileReader = new FileReader();
113
-
114
- fileReader.addEventListener(
115
- "load",
116
- () => {
117
- if (!isUploadReject) {
118
- let base64ImageSrc = fileReader.result;
119
- this.insertBase64Image(base64ImageSrc);
120
- }
121
- },
122
- false
123
- );
124
-
125
- if (file) {
126
- fileReader.readAsDataURL(file);
127
- }
128
-
129
- this.options.upload(file).then(
130
- (imageUrl) => {
131
- this.insertToEditor(imageUrl);
132
- },
133
- (error) => {
134
- isUploadReject = true;
135
- this.removeBase64Image();
136
- console.warn(error);
137
- }
138
- );
139
- }
140
-
141
- fileChanged() {
142
- const file = this.fileHolder.files[0];
143
- this.readAndUploadFile(file);
144
- }
145
-
146
- insertBase64Image(url) {
147
- const range = this.range;
148
- this.quill.insertEmbed(
149
- range.index,
150
- LoadingImage.blotName,
151
- `${url}`,
152
- "user"
153
- );
154
- }
155
-
156
- insertToEditor(url) {
157
- const range = this.range;
158
- // Delete the placeholder image
159
- this.quill.deleteText(range.index, 3, "user");
160
- // Insert the server saved image
161
- this.quill.insertEmbed(range.index, "image", `${url}`, "user");
162
-
163
- range.index++;
164
- this.quill.setSelection(range, "user");
165
- }
166
-
167
- removeBase64Image() {
168
- const range = this.range;
169
- this.quill.deleteText(range.index, 3, "user");
170
- }
171
- }
172
-
173
- window.ImageUploader = ImageUploader;
1
+ import LoadingImage from "./blots/image.js";
2
+
3
+ class ImageUploader {
4
+ constructor(quill, options) {
5
+ this.quill = quill;
6
+ this.options = options;
7
+ this.range = null;
8
+
9
+ if (typeof this.options.upload !== "function")
10
+ console.warn(
11
+ "[Missing config] upload function that returns a promise is required"
12
+ );
13
+
14
+ var toolbar = this.quill.getModule("toolbar");
15
+ toolbar.addHandler("image", this.selectLocalImage.bind(this));
16
+ toolbar.addHandler("code-block", this.fixHighlighter.bind(this));
17
+
18
+ this.handleDrop = this.handleDrop.bind(this);
19
+ this.handlePaste = this.handlePaste.bind(this);
20
+
21
+ this.quill.root.addEventListener("drop", this.handleDrop, false);
22
+ this.quill.root.addEventListener("paste", this.handlePaste, false);
23
+
24
+ }
25
+
26
+ fixHighlighter() {
27
+ const range = this.quill.getSelection(true);
28
+ const formats = this.quill.getFormat(range);
29
+ // if its not a code-block yet, turn it into one.
30
+ if (!formats['code-block']) {
31
+ return quill.formatLine(range.index, 'code-block', 'user');
32
+ };
33
+
34
+ // if it was a code-block, and the user meant to remove it
35
+ // then do all the work we did up top in the keybinding function
36
+ this.quill.formatLine(range.index, 'code-block', false, 'user');
37
+ const { domNode } = this.quill.getLine(range.index)[0];
38
+ let nodes = [domNode];
39
+
40
+ while (nodes.length > 0) {
41
+ const node = nodes.shift();
42
+ // first append children to queue
43
+ nodes = nodes.concat(Array.from(node.children));
44
+
45
+ // go through class list of current node removing its "hljs" classes
46
+ for (let i = 0; i < node.classList.length; i++) {
47
+ const c = node.classList[i];
48
+ if (c.indexOf('hljs') >= 0) {
49
+ node.classList.remove(c);
50
+ i--;
51
+ }
52
+ }
53
+ }
54
+ }
55
+
56
+ selectLocalImage() {
57
+ this.range = this.quill.getSelection();
58
+ this.fileHolder = document.createElement("input");
59
+ this.fileHolder.setAttribute("type", "file");
60
+ this.fileHolder.setAttribute("accept", "image/*");
61
+ this.fileHolder.setAttribute("style", "visibility:hidden");
62
+
63
+ this.fileHolder.onchange = this.fileChanged.bind(this);
64
+
65
+ document.body.appendChild(this.fileHolder);
66
+
67
+ this.fileHolder.click();
68
+
69
+ window.requestAnimationFrame(() => {
70
+ document.body.removeChild(this.fileHolder);
71
+ });
72
+ }
73
+
74
+ handleDrop(evt) {
75
+ evt.stopPropagation();
76
+ evt.preventDefault();
77
+ if (
78
+ evt.dataTransfer &&
79
+ evt.dataTransfer.files &&
80
+ evt.dataTransfer.files.length
81
+ ) {
82
+ if (document.caretRangeFromPoint) {
83
+ const selection = document.getSelection();
84
+ const range = document.caretRangeFromPoint(evt.clientX, evt.clientY);
85
+ if (selection && range) {
86
+ selection.setBaseAndExtent(
87
+ range.startContainer,
88
+ range.startOffset,
89
+ range.startContainer,
90
+ range.startOffset
91
+ );
92
+ }
93
+ } else {
94
+ const selection = document.getSelection();
95
+ const range = document.caretPositionFromPoint(evt.clientX, evt.clientY);
96
+ if (selection && range) {
97
+ selection.setBaseAndExtent(
98
+ range.offsetNode,
99
+ range.offset,
100
+ range.offsetNode,
101
+ range.offset
102
+ );
103
+ }
104
+ }
105
+
106
+ this.range = this.quill.getSelection();
107
+ let file = evt.dataTransfer.files[0];
108
+
109
+ setTimeout(() => {
110
+ this.range = this.quill.getSelection();
111
+ this.readAndUploadFile(file);
112
+ }, 0);
113
+ }
114
+ }
115
+
116
+ handlePaste(evt) {
117
+ let clipboard = evt.clipboardData || window.clipboardData;
118
+
119
+ // IE 11 is .files other browsers are .items
120
+ if (clipboard && (clipboard.items || clipboard.files)) {
121
+ let items = clipboard.items || clipboard.files;
122
+ const IMAGE_MIME_REGEX = /^image\/(jpe?g|gif|png|svg|webp)$/i;
123
+
124
+ for (let i = 0; i < items.length; i++) {
125
+ if (IMAGE_MIME_REGEX.test(items[i].type)) {
126
+ let file = items[i].getAsFile ? items[i].getAsFile() : items[i];
127
+
128
+ if (file) {
129
+ this.range = this.quill.getSelection();
130
+ evt.preventDefault();
131
+ setTimeout(() => {
132
+ this.range = this.quill.getSelection();
133
+ this.readAndUploadFile(file);
134
+ }, 0);
135
+ }
136
+ }
137
+ }
138
+ }
139
+ }
140
+
141
+ readAndUploadFile(file) {
142
+ let isUploadReject = false;
143
+
144
+ const fileReader = new FileReader();
145
+
146
+ fileReader.addEventListener(
147
+ "load",
148
+ () => {
149
+ if (!isUploadReject) {
150
+ let base64ImageSrc = fileReader.result;
151
+ this.insertBase64Image(base64ImageSrc);
152
+ }
153
+ },
154
+ false
155
+ );
156
+
157
+ if (file) {
158
+ fileReader.readAsDataURL(file);
159
+ }
160
+
161
+ this.options.upload(file).then(
162
+ (imageUrl) => {
163
+ this.insertToEditor(imageUrl);
164
+ },
165
+ (error) => {
166
+ isUploadReject = true;
167
+ this.removeBase64Image();
168
+ console.warn(error);
169
+ }
170
+ );
171
+ }
172
+
173
+ fileChanged() {
174
+ const file = this.fileHolder.files[0];
175
+ this.readAndUploadFile(file);
176
+ }
177
+
178
+ insertBase64Image(url) {
179
+ const range = this.range;
180
+ this.quill.insertEmbed(
181
+ range.index,
182
+ LoadingImage.blotName,
183
+ `${url}`,
184
+ "user"
185
+ );
186
+ }
187
+
188
+ insertToEditor(url) {
189
+ const range = this.range;
190
+ // Delete the placeholder image
191
+ this.quill.deleteText(range.index, 3, "user");
192
+ // Insert the server saved image
193
+ this.quill.insertEmbed(range.index, "image", `${url}`, "user");
194
+
195
+ range.index++;
196
+ this.quill.setSelection(range, "user");
197
+ }
198
+
199
+ removeBase64Image() {
200
+ const range = this.range;
201
+ this.quill.deleteText(range.index, 3, "user");
202
+ }
203
+ }
204
+
205
+ window.ImageUploader = ImageUploader;
174
206
  export default ImageUploader;
package/webpack.config.js CHANGED
@@ -1,56 +1,56 @@
1
- const path = require("path");
2
- const TerserPlugin = require("terser-webpack-plugin");
3
- const ExtractTextPlugin = require("extract-text-webpack-plugin");
4
-
5
- module.exports = [{
6
- entry: {
7
- "quill.imageUploader": "./src/quill.imageUploader.js"
8
- },
9
- output: {
10
- filename: "[name].min.js",
11
- path: path.resolve(__dirname, "dist"),
12
- },
13
- devServer: {
14
- //contentBase: './src',
15
- https: true,
16
- },
17
- externals: {
18
- quill: "Quill",
19
- },
20
- optimization: {
21
- minimize: true,
22
- minimizer: [
23
- new TerserPlugin({
24
- extractComments: true,
25
- cache: true,
26
- parallel: true,
27
- sourceMap: true, // Must be set to true if using source-maps in production
28
- terserOptions: {
29
- // https://github.com/webpack-contrib/terser-webpack-plugin#terseroptions
30
- extractComments: "all",
31
- compress: {
32
- drop_console: false,
33
- },
34
- },
35
- }),
36
- ],
37
- },
38
- module: {
39
- rules: [{
40
- test: /\.css$/,
41
- use: ExtractTextPlugin.extract({
42
- use: [{
43
- loader: "css-loader",
44
- }, ],
45
- }),
46
- },
47
- {
48
- test: /\.js$/,
49
- exclude: /node_modules/,
50
- use: {
51
- loader: "babel-loader",
52
- },
53
- },
54
- ],
55
- }
1
+ const path = require("path");
2
+ const TerserPlugin = require("terser-webpack-plugin");
3
+ const ExtractTextPlugin = require("extract-text-webpack-plugin");
4
+
5
+ module.exports = [{
6
+ entry: {
7
+ "quill.imageUploader": "./src/quill.imageUploader.js"
8
+ },
9
+ output: {
10
+ filename: "[name].min.js",
11
+ path: path.resolve(__dirname, "dist"),
12
+ },
13
+ devServer: {
14
+ //contentBase: './src',
15
+ https: true,
16
+ },
17
+ externals: {
18
+ quill: "Quill",
19
+ },
20
+ optimization: {
21
+ minimize: true,
22
+ minimizer: [
23
+ new TerserPlugin({
24
+ extractComments: true,
25
+ cache: true,
26
+ parallel: true,
27
+ sourceMap: true, // Must be set to true if using source-maps in production
28
+ terserOptions: {
29
+ // https://github.com/webpack-contrib/terser-webpack-plugin#terseroptions
30
+ extractComments: "all",
31
+ compress: {
32
+ drop_console: false,
33
+ },
34
+ },
35
+ }),
36
+ ],
37
+ },
38
+ module: {
39
+ rules: [{
40
+ test: /\.css$/,
41
+ use: ExtractTextPlugin.extract({
42
+ use: [{
43
+ loader: "css-loader",
44
+ }, ],
45
+ }),
46
+ },
47
+ {
48
+ test: /\.js$/,
49
+ exclude: /node_modules/,
50
+ use: {
51
+ loader: "babel-loader",
52
+ },
53
+ },
54
+ ],
55
+ }
56
56
  }, ];