简体   繁体   中英

Trying to extend rich markdown editor

I'm working on trying to extend this markdown editor library - which itself extends Prosemirror . I'd like to build my own Node which has the following schema:

attrs: {
  id: number
}

and returns the following HTML

<div class=`story-block ${attrs.id}`>
  <div contenteditable="false">
    <button>Story</button>
  </div>
  <div>
    <p>Text that we can edit</p>
  </div>
</div>

The trick here is that since the editor saves to markdown. We need some way to understand this is a special type of node, a Story , but wrapping it in a unique set of characters, I'm using %%% . This is similar to how the library I'm extending using ::: as a signal for their Notice node

I am able to add a new Story node, and it renders my buttons and styles correctly. When I go to save everything saves correctly and I get markdown that looks like

%%%123 // the id
Whatever text I write

%%%

However, when I want to render than markdown back into DOM elements it fails and I get plain text in the document again. Specifically, the DOM looks like

<p>%%%123
Whatever text I write</p>
<p>%%%</p>

Code for the customer node is below. Has anyone successfully extended this library or can show me what I'm doing wrong? Thanks

import { wrappingInputRule } from "prosemirror-inputrules";
import toggleWrap from "../commands/toggleWrap"; //Rule file from library
import Node from "./Node";
export default class Story extends Node {
  get name() {
    return "container_story";
  }

  get schema() {
    return {
      attrs: {
        id: {
          default: "story",
        },
      },
      content: "block+",
      group: "block",
      defining: true,
      draggable: true,
      parseDOM: [
        {
          tag: "div.story-block",
          preserveWhitespace: "full",
          contentElement: "div:last-child",
          getAttrs: () => ({
            id: "story",
          }),
        },
      ],
      toDOM: node => {
        node.attrs.id =
          node.attrs.id === "story"
            ? Math.round(Math.random() * 10000)
            : node.attrs.id;
        console.log(node.attrs.id);

        const button = document.createElement("button");
        button.innerText = "Story";
        button.id = node.attrs.id;
        button.addEventListener(
          "click",
          (function () {
            return function (e) {
              alert(`Story ${e.target.id} clicked!`);
            };
          })(),
          false
        );

        return [
          "div",
          { class: `story-block ${node.attrs.id}` },
          ["div", { contentEditable: false }, button],
          ["div", { class: "content story-content" }, 0],
        ];
      },
    };
  }

  commands({ type }) {
    return attrs => toggleWrap(type, attrs);
  }

  inputRules({ type }) {
    return [wrappingInputRule(/^%%%$/, type)];
  }

  toMarkdown(state, node) {
    state.write("\n%%%" + "story" + "\n");
    state.renderContent(node);
    state.ensureNewLine();
    state.write("%%%");
    state.closeBlock(node);
    console.log(state);
  }

  parseMarkdown() {
    return {
      block: "container_story",
      getAttrs: tok => {
        console.log(tok.attrGet("id"));
        ({ id: tok.attrGet("id") });
      },
    };
  }
}

It looks like you are missing a configuration for the markdown rules.

You can add a file in /src/lib/markdown , something like story.ts , with this content (copy/paste from notice.ts)

import customFence from "markdown-it-container";

export default function story(md): void {
  return customFence(md, "story", {
    marker: "%",
    validate: () => true,
  });
}

And in the rules.ts file (same dir), you use the new rule

import markdownit from "markdown-it";
...
import storyPlugin from "./story";

export default function rules({ embeds }) {
  return markdownit("default", {
    breaks: false,
    html: false,
  })
    ...
    .use(noticesPlugin)
    .use(storyPlugin);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM