Add images - display, paste + uploading

This commit is contained in:
Sinclair Chen 2022-07-06 19:04:42 -07:00
parent 3f30becb93
commit ac436480f5
5 changed files with 36 additions and 2 deletions

View File

@ -8,6 +8,7 @@
},
"sideEffects": false,
"dependencies": {
"@tiptap/extension-image": "^2.0.0-beta.30",
"@tiptap/starter-kit": "^2.0.0-beta.190",
"lodash": "4.17.21"
},

View File

@ -1,6 +1,7 @@
import { MAX_TAG_LENGTH } from '../contract'
import { generateText, JSONContent, Extension } from '@tiptap/core'
import * as StarterKit from '@tiptap/starter-kit' // needed for cjs import to work on firebase
import { Image } from '@tiptap/extension-image'
export function parseTags(text: string) {
const regex = /(?:^|\s)(?:[#][a-z0-9_]+)/gi
@ -33,5 +34,5 @@ export function parseWordsAsTags(text: string) {
export function richTextToString(text: JSONContent | string) {
return typeof text === 'string'
? text
: generateText(text, [StarterKit as unknown as Extension])
: generateText(text, [StarterKit as unknown as Extension, Image])
}

View File

@ -2,9 +2,11 @@ import CharacterCount from '@tiptap/extension-character-count'
import Placeholder from '@tiptap/extension-placeholder'
import { useEditor, EditorContent, JSONContent, Content } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import { Image } from '@tiptap/extension-image'
import clsx from 'clsx'
import { useEffect } from 'react'
import { Linkify } from './linkify'
import { uploadImage } from 'web/lib/firebase/storage'
const LINE_HEIGHT = 2
@ -26,11 +28,35 @@ export function useTextEditor(props: {
attributes: {
class: clsx(proseClass, rowsClass, 'textarea textarea-bordered'),
},
handlePaste(view, event) {
const files = Array.from(event.clipboardData?.files ?? []).filter(
(file) => file.type.startsWith('image')
)
if (!files.length) {
return // if no files pasted, use default paste handler
}
event.preventDefault()
;(async () => {
// TODO: show loading state, compress large images
const urls = await Promise.all(
files.map((file) => uploadImage('default', file))
)
let trans = view.state.tr
urls.forEach((src: any) => {
const node = view.state.schema.nodes.image.create({ src })
trans = trans.insert(view.state.selection.to, node)
})
view.dispatch(trans)
})()
},
},
extensions: [
StarterKit,
Placeholder.configure({ placeholder }),
CharacterCount.configure({ limit: max }),
Image,
],
content: defaultValue,
})
@ -46,7 +72,7 @@ function RichContent(props: { content: JSONContent }) {
const { content } = props
const editor = useEditor({
editorProps: { attributes: { class: proseClass } },
extensions: [StarterKit],
extensions: [StarterKit, Image],
content,
editable: false,
})

View File

@ -25,6 +25,7 @@
"@nivo/line": "0.74.0",
"@react-query-firebase/firestore": "0.4.2",
"@tiptap/extension-character-count": "^2.0.0-beta.31",
"@tiptap/extension-image": "^2.0.0-beta.30",
"@tiptap/extension-placeholder": "^2.0.0-beta.53",
"@tiptap/react": "^2.0.0-beta.114",
"@tiptap/starter-kit": "^2.0.0-beta.190",

View File

@ -2974,6 +2974,11 @@
dependencies:
prosemirror-state "1.4.1"
"@tiptap/extension-image@^2.0.0-beta.30":
version "2.0.0-beta.30"
resolved "https://registry.yarnpkg.com/@tiptap/extension-image/-/extension-image-2.0.0-beta.30.tgz#60c6cfd09bfd017a3d8b1feaf0931462ffd71a60"
integrity sha512-VhEmgiKkZMiKR7hbpJgIlIUS/QNjSGI5ER7mKDAbuV1IB5yb6nGjZ6o3Exrr2/CaTaW5hQarBC1z2Xgdu05EGg==
"@tiptap/extension-italic@^2.0.0-beta.28":
version "2.0.0-beta.28"
resolved "https://registry.yarnpkg.com/@tiptap/extension-italic/-/extension-italic-2.0.0-beta.28.tgz#bf88ecae64c8f2f69f1f508b802c1efd7454a84e"