添加 html 视频标签时 insertContentAt 不起作用

问题描述 投票:0回答:1

我们有以下 Tiptap 扩展来处理 video 节点:

import { mergeAttributes, Node, nodeInputRule } from "@tiptap/core";

export interface VideoOptions {
  url: string;
  width: number;
  height: number;
  HTMLAttributes: Record<string, any>;
}

declare module "@tiptap/core" {
  interface Commands<ReturnType> {
    video: {
      /**
       * Set a video node
       * @param options.updateSelection set to true will select the newly inserted content
       */
      setVideo: (
        id: string,
        src: string,
        width?: number,
        height?: number,
        controls?: boolean,
        controlslist?: string,
        options?: { updateSelection: boolean }
      ) => ReturnType;
      /**
       * Toggle a video
       */
      toggleVideo: (src: string) => ReturnType;
    };
  }
}

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

export const Video = Node.create({
  name: "video",
  group: "block",
  draggable: true,
  selectable: true,

  addAttributes() {
    return {
      src: {
        default: null,
        parseHTML: (el: any) => (el as HTMLSpanElement).getAttribute("src"),
        renderHTML: (attrs: any) => ({ src: attrs.src }),
      },
      controls: {
        default: true,
        renderHTML: (attrs: any) => ({ controls: attrs.controls }),
        parseHTML: (el: any) => {
          if ((el as HTMLSpanElement).getAttribute("controls")) {
            return (el as HTMLSpanElement).getAttribute("controls");
          } else if ((el as HTMLSpanElement).hasAttribute("controls")) {
            return true;
          } else {
            return false;
          }
        },
      },
      controlslist: {
        default: "",
        renderHTML: (attributes: any) => {
          return { controlslist: attributes.controlslist };
        },
        parseHTML: (element: any) => element.getAttribute("controlslist"),
      },
      documentId: {
        default: "",
        renderHTML: (attributes: any) => {
          return { "data-document-id": attributes.documentId };
        },
        parseHTML: (element: any) => element.getAttribute("data-document-id"),
      },
      videoResolution: {
        default: "404x720",
        renderHTML: (attributes: any) => {
          return { "data-video-resolution": attributes.videoResolution };
        },
        parseHTML: (element: any) =>
          element.getAttribute("data-video-resolution"),
      },
      width: {
        renderHTML: (attributes: any) => {
          return {
            width: parseInt(attributes.width),
          };
        },
        parseHTML: (element) => element.getAttribute("width"),
      },
      height: {
        renderHTML: (attributes: any) => {
          return {
            height: parseInt(attributes.height),
          };
        },
        parseHTML: (element) => element.getAttribute("height"),
      },
    };
  },

  parseHTML() {
    return [
      {
        tag: "div.video-wrapper>video,video",
        getAttrs: (el: any) => ({
          src: (el as HTMLVideoElement).getAttribute("src"),
        }),
      },
    ];
  },

  renderHTML({ HTMLAttributes }) {
    return [
      "div",
      { class: "video-wrapper" },
      ["video", mergeAttributes(HTMLAttributes)],
    ];
  },

  addCommands() {
    return {
      setVideo:
        (
          id,
          src,
          width = 640,
          height = 480,
          controls = true,
          controlslist = "nodownload",
          options
        ) =>
        ({ commands, state }) => {
          return commands.insertContentAt(
            state.selection,
            `<video 
              controls="${controls}" 
              controlslist="${controlslist}"
              src="${src}" 
              width="${width}"
              height="${height}"
              data-document-id="${id}" 
              data-video-resolution="${width}x${height}" />`,
            options
          );
        },

      toggleVideo:
        () =>
        ({ commands }) =>
          commands.toggleNode(this.name, "paragraph"),
    };
  },

  addInputRules() {
    return [
      nodeInputRule({
        find: VIDEO_INPUT_REGEX,
        type: this.type,
        getAttributes: (match) => {
          const [, , src] = match;

          return { src };
        },
      }),
    ];
  },
});

我们想要插入具有给定实体的新视频:

if (asset.mime.includes("video")) {
          const { id, src, width, height } = getUpdatedVideo(asset);

          if (!forceInsert)
            editor.chain().focus().setVideo(String(id), src, width, height);
          else editor.commands.setVideo(String(id), src, width, height);
        }

setCommand
被执行了,我们通过
congole.log
检查了它,但是它的节点从未插入到文档中,因此,文档永远不会更新。

我们添加了一个具有类似结构的音频扩展,并且我们以相同的方式执行它

为什么会失败?

html reactjs editor tiptap prose-mirror
1个回答
0
投票

我们正在调用该函数,因此我们总是设置日志,但我们没有运行它:

editor
              .chain()
              .focus()
              .setVideo(String(id), src, width, height)
              .run();

run()
是执行动作的指令。

© www.soinside.com 2019 - 2024. All rights reserved.