1

在此处输入图像描述

我想用tiptap扩展实现图像和可编辑标题

https://discuss.prosemirror.net/t/figure-and-editable-caption/462
ProseMirror有一个很好的例子,但是用tiptap很难实现吗?
如果可能的话,请告诉我你应该写什么代码。

我附上我在下面写的代码。
图片和标题已成功添加,但标题尚无法编辑。

// ./CustomImage.ts
// @ts-ignore
import { Node, Plugin } from 'tiptap'
// @ts-ignore
import { nodeInputRule } from 'tiptap-commands'

const IMAGE_INPUT_REGEX = /!\[(.+|:?)\]\((\S+)(?:(?:\s+)["'](\S+)["'])?\)/

export default class CustomImage extends Node {
  get name () {
    return 'customImage'
  }

  get schema () {
    return {
      attrs: {
        src: {
          default: null
        },
        alt: {
          default: null
        },
        title: {
          default: null
        },
        caption: {
          default: null
        }
      },
      group: 'block',
      selectable: false,
      draggable: true,
      parseDOM: [
        {
          tag: 'figure'
        },
        [
          {
            tag: 'img[src]',
            getAttrs: (dom: any) => ({
              src: dom.getAttribute('src'),
              title: dom.getAttribute('title'),
              alt: dom.getAttribute('alt')
            })
          },
          {
            tag: 'figcaption'
          }
        ]
      ],
      toDOM: (node: any) => [
        'figure',
        [
          'img',
          {
            src: node.attrs.src,
            title: node.attrs.title,
            alt: node.attrs.alt
          }
        ],
        [
          'figcaption',
          {
            contenteditable: 'true'
          },
          node.attrs.caption
        ]
      ]
    }
  }

  commands ({ type }: any) {
    return (attrs: any) => (state: any, dispatch: any) => {
      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 }: any) {
    return [
      nodeInputRule(IMAGE_INPUT_REGEX, type, (match: any) => {
        const [, alt, src, title] = match
        return {
          src,
          alt,
          title
        }
      })
    ]
  }

  get plugins () {
    return [
      new Plugin({
        props: {
          handleDOMEvents: {
            drop (view: any, event: any) {
              const hasFiles = event.dataTransfer &&
              event.dataTransfer.files &&
              event.dataTransfer.files.length

              if (!hasFiles) {
                return
              }

              const images = Array
                .from(event.dataTransfer.files)
                .filter((file: any) => (/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((image: any) => {
                const reader = new FileReader()

                reader.onload = (readerEvent: any) => {
                  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)
              })
            }
          }
        }
      })
    ]
  }
}

4

1 回答 1

1

您在图形标题中缺少一个“洞”以使其可编辑。请参阅https://prosemirror.net/docs/ref/#model.NodeSpec.toDOM。我实现了提到的 ProseMirror 线程中提到的解决方案之一;但是,光标仍然可以在 image 和 figurecaption 之间输入文本。我建议改用最后一个示例和 3 个模式。

  get schema() {
    return {
      content: "inline*",
      attrs: {src: {default: ""}, title: {default: ""}},
      group: 'block',
      draggable: true,
      isolating: true,
      parseDOM: [{
        tag: "figure",
        contentElement: "figcaption",
        getAttrs(dom) {
          let img = dom.querySelector("img")
          console.log(img, img.getAttribute('src'), img.getAttribute('alt'));
          return {src: img.getAttribute('src'), title: img.getAttribute('alt')}
        }
      }],
      toDOM: node => ["figure", ["img", node.attrs], ["figurecaption", 0]],
    }
  }
于 2019-12-10T19:14:56.497 回答