Last active
June 9, 2025 07:55
-
Star
(134)
You must be signed in to star a gist -
Fork
(17)
You must be signed in to fork a gist
-
-
Save slava-vishnyakov/16076dff1a77ddaca93c4bccd4ec4521 to your computer and use it in GitHub Desktop.
Revisions
-
slava-vishnyakov revised this gist
Nov 19, 2020 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -194,6 +194,7 @@ props: { }); } else { const reader = new FileReader(); reader.onload = readerEvent => { const node = schema.nodes.image.create({ src: readerEvent.target.result, -
slava-vishnyakov revised this gist
Jan 28, 2020 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -140,7 +140,7 @@ export default class Image extends Node { ```js import Image from './Image'; async function upload(file) { ... } @@ -154,7 +154,7 @@ new Editor({ 3) Implement the `upload` function: ```js async function upload(file) { let formData = new FormData(); formData.append('file', file); const headers = {'Content-Type': 'multipart/form-data'}; -
slava-vishnyakov revised this gist
Oct 24, 2019 . 1 changed file with 3 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -177,12 +177,12 @@ This `POST`s using `axios` to `/upload` and expects a JSON back of this form: props: { handlePaste(view, event, slice) { const items = (event.clipboardData || event.originalEvent.clipboardData).items; for (const item of items) { if (item.type.indexOf("image") === 0) { event.preventDefault(); const { schema } = view.state; const image = item.getAsFile(); if(upload) { upload(image).then(src => { -
slava-vishnyakov revised this gist
Oct 24, 2019 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -207,6 +207,6 @@ props: { } } return false; }, handleDOMEvents: { ``` -
slava-vishnyakov revised this gist
Oct 24, 2019 . 1 changed file with 11 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -171,11 +171,11 @@ This `POST`s using `axios` to `/upload` and expects a JSON back of this form: 5) Implement server-side logic for `/upload` 6) If you want to support pasting of images, modify `Image.js` starting at `props:`, ending at `handleDOMEvents` (re-factor common parts if you want to) ```js props: { handlePaste(view, event, slice) { const items = (event.clipboardData || event.originalEvent.clipboardData).items; for (let i = 0; i < items.length; i++) { if (items[i].type.indexOf("image") === 0) { @@ -185,11 +185,14 @@ props: { const image = items[i].getAsFile(); if(upload) { upload(image).then(src => { const node = schema.nodes.image.create({ src: src, }); const transaction = view.state.tr.replaceSelectionWith(node); view.dispatch(transaction) }); } else { reader.onload = readerEvent => { const node = schema.nodes.image.create({ @@ -203,6 +206,7 @@ props: { } } return false; } handleDOMEvents: { ``` -
slava-vishnyakov revised this gist
Oct 24, 2019 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -171,7 +171,7 @@ This `POST`s using `axios` to `/upload` and expects a JSON back of this form: 5) Implement server-side logic for `/upload` 6) (!! This doesn't work fully yet, prevents paste of text) If you want to support pasting of images, modify `Image.js` starting at `props:`, ending at `handleDOMEvents` (re-factor common parts if you want to) ```js props: { -
slava-vishnyakov revised this gist
Oct 24, 2019 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -171,7 +171,7 @@ This `POST`s using `axios` to `/upload` and expects a JSON back of this form: 5) Implement server-side logic for `/upload` 6) (/!\ This doesn't work fully yet, prevents paste of text) If you want to support pasting of images, modify `Image.js` starting at `props:`, ending at `handleDOMEvents` (re-factor common parts if you want to) ```js props: { -
slava-vishnyakov revised this gist
Oct 24, 2019 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -171,7 +171,7 @@ This `POST`s using `axios` to `/upload` and expects a JSON back of this form: 5) Implement server-side logic for `/upload` 6) ((!) Doesn't work fully yet, prevents paste of text) If you want to support pasting of images, modify `Image.js` starting at `props:`, ending at `handleDOMEvents` (re-factor common parts if you want to) ```js props: { -
slava-vishnyakov revised this gist
Oct 24, 2019 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -171,7 +171,7 @@ This `POST`s using `axios` to `/upload` and expects a JSON back of this form: 5) Implement server-side logic for `/upload` 6) If you want to support pasting of images, modify `Image.js` starting at `props:`, ending at `handleDOMEvents` (re-factor common parts if you want to) ```js props: { -
slava-vishnyakov revised this gist
Oct 24, 2019 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -176,8 +176,8 @@ This `POST`s using `axios` to `/upload` and expects a JSON back of this form: ```js props: { async handlePaste(view, event, slice) { const items = (event.clipboardData || event.originalEvent.clipboardData).items; for (let i = 0; i < items.length; i++) { if (items[i].type.indexOf("image") === 0) { event.preventDefault(); const { schema } = view.state; -
slava-vishnyakov revised this gist
Oct 24, 2019 . 1 changed file with 37 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -169,4 +169,40 @@ This `POST`s using `axios` to `/upload` and expects a JSON back of this form: {"src": "https://yoursite.com/images/uploadedimage.jpg"} ``` 5) Implement server-side logic for `/upload` 6) If you want to support pasting of images, modify `Image.js` startings at `props:`, ending at `handleDOMEvents` (re-factor common parts if you want to) ```js props: { async handlePaste(view, event, slice) { var items = (event.clipboardData || event.originalEvent.clipboardData).items; for (var i = 0; i < items.length; i++) { if (items[i].type.indexOf("image") === 0) { event.preventDefault(); const { schema } = view.state; const image = items[i].getAsFile(); if(upload) { const node = schema.nodes.image.create({ src: await upload(image), }); const transaction = view.state.tr.replaceSelectionWith(node); view.dispatch(transaction) } else { reader.onload = readerEvent => { const node = schema.nodes.image.create({ src: readerEvent.target.result, }); const transaction = view.state.tr.replaceSelectionWith(node); view.dispatch(transaction) }; reader.readAsDataURL(image) } } } }, handleDOMEvents: { ``` -
slava-vishnyakov revised this gist
Oct 24, 2019 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,5 @@ 1) Create a file `Image.js` from the source below (it is almost a copy of [Image.js from tiptap-extensions](https://github.com/scrumpy/tiptap/blob/master/packages/tiptap-extensions/src/nodes/Image.js) except that it has a constructor that accepts `uploadFunc` (function to be called with `image` being uploaded) and additional logic `if(upload) { ... } else { ... previous base64 logic .. }` in the `new Plugin` section. ```js import {Node, Plugin} from 'tiptap' -
slava-vishnyakov revised this gist
Oct 24, 2019 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,4 @@ 1) Create a file `Image.js` from the source below (it is almost a copy of [Image.js from tiptap-extensions](https://github.com/scrumpy/tiptap/blob/master/packages/tiptap-extensions/src/nodes/Image.js) except that it has a constructor that accepts `uploadFunc` (function to be called with `image` being uploaded) and additional logic `if(upload) { ... } else { ... previous base64 logic .. }` in `new Plugin` section. ```js -
slava-vishnyakov revised this gist
Oct 24, 2019 . 1 changed file with 6 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -137,17 +137,21 @@ export default class Image extends Node { 2) Import it: ```js import Image from './Image'; async upload(file) { ... } new Editor({ extensions: [ ... new Image(null, null, upload), ... ``` 3) Implement the `upload` function: ```js async upload(file) { -
slava-vishnyakov revised this gist
Oct 24, 2019 . No changes.There are no files selected for viewing
-
slava-vishnyakov revised this gist
Oct 24, 2019 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,5 @@ 1) Create a file `Image.js` from source below (it is almost a copy of [Image.js from tiptap-extensions](https://github.com/scrumpy/tiptap/blob/master/packages/tiptap-extensions/src/nodes/Image.js) except that it has a constructor that accepts `uploadFunc` (function to be called with `image` being uploaded) and additional logic `if(upload) { ... } else { ... previous base64 logic .. }` in `new Plugin` section. ```js import {Node, Plugin} from 'tiptap' -
slava-vishnyakov created this gist
Oct 24, 2019 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,168 @@ 1) Create a file Image.js (it is almost a copy of [Image.js from tiptap-extensions](https://github.com/scrumpy/tiptap/blob/master/packages/tiptap-extensions/src/nodes/Image.js) except that it has a constructor that accepts `uploadFunc` (function to be called with `image` being uploaded). ```js import {Node, Plugin} from 'tiptap' import {nodeInputRule} from 'tiptap-commands' /** * Matches following attributes in Markdown-typed image: [, alt, src, title] * * Example: *  -> [, "Lorem", "image.jpg"] *  -> [, "", "image.jpg", "Ipsum"] *  -> [, "Lorem", "image.jpg", "Ipsum"] */ const IMAGE_INPUT_REGEX = /!\[(.+|:?)\]\((\S+)(?:(?:\s+)["'](\S+)["'])?\)/; export default class Image extends Node { constructor(name, parent, uploadFunc = null) { super(name, parent); this.uploadFunc = uploadFunc; } get name() { return 'image' } get schema() { return { inline: true, attrs: { src: {}, alt: { default: null, }, title: { default: null, }, }, group: 'inline', draggable: true, parseDOM: [ { tag: 'img[src]', getAttrs: dom => ({ src: dom.getAttribute('src'), title: dom.getAttribute('title'), alt: dom.getAttribute('alt'), }), }, ], toDOM: node => ['img', node.attrs], } } commands({ type }) { return attrs => (state, dispatch) => { const { selection } = state; const position = selection.$cursor ? selection.$cursor.pos : selection.$to.pos; const node = type.create(attrs); const transaction = state.tr.insert(position, node); dispatch(transaction) } } inputRules({ type }) { return [ nodeInputRule(IMAGE_INPUT_REGEX, type, match => { const [, alt, src, title] = match; return { src, alt, title, } }), ] } get plugins() { const upload = this.uploadFunc; return [ new Plugin({ props: { handleDOMEvents: { drop(view, event) { const hasFiles = event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files.length; if (!hasFiles) { return } const images = Array .from(event.dataTransfer.files) .filter(file => (/image/i).test(file.type)); if (images.length === 0) { return } event.preventDefault(); const { schema } = view.state; const coordinates = view.posAtCoords({ left: event.clientX, top: event.clientY }); images.forEach(async image => { const reader = new FileReader(); if(upload) { const node = schema.nodes.image.create({ src: await upload(image), }); const transaction = view.state.tr.insert(coordinates.pos, node); view.dispatch(transaction) } else { reader.onload = readerEvent => { const node = schema.nodes.image.create({ src: readerEvent.target.result, }); const transaction = view.state.tr.insert(coordinates.pos, node); view.dispatch(transaction) }; reader.readAsDataURL(image) } }) }, }, }, }), ] } } ``` 2) Import it: ``` import Image from './Image'; new Editor({ extensions: [ ... new Image(null, null, upload), ... ``` 3) Create `upload` function: ```js async upload(file) { let formData = new FormData(); formData.append('file', file); const headers = {'Content-Type': 'multipart/form-data'}; const response = await axios.post('/upload', formData, {headers: headers} ); return response.data.src; }, ``` This `POST`s using `axios` to `/upload` and expects a JSON back of this form: ``` {"src": "https://yoursite.com/images/uploadedimage.jpg"} ``` 5) Implement server-side logic for `/upload`