Wie füge ich Rich-Text-Editor-Unterstützung zu meiner Markdown-Erweiterung hinzu?

Ich habe eine Erweiterung erstellt, die einige BBCode-Tags hinzufügt, um Snapblocks zu rendern. Als der Rich-Text-Editor eingeführt wurde, hat dies meine Erweiterung irgendwie kaputt gemacht oder sie ist zumindest mit dem Rich-Text-Editor unbrauchbar. Ich möchte Unterstützung für den Rich-Text-Editor hinzufügen, also habe ich mir die fehlerhafte Erweiterung angesehen, um zu sehen, wie sie funktioniert, und habe sie derzeit einigermaßen zum Laufen gebracht. Ich kann die Snapblocks tatsächlich in den Beitrag im Rich-Text-Editor einfügen, aber es scheint mir nicht zu gelingen, vorhandene Snapblocks-Tags in den Rich-Text-Editor zu konvertieren.

Hier ist, was ich bisher habe.

Im Moment konzentriere ich mich speziell auf die eigentliche Konvertierung. Ich habe eine grundlegende Vermutung, wie es funktioniert, aber bisher erhalte ich keine Ergebnisse. Wie funktioniert also das Parsen?

1 „Gefällt mir“

Nach viel Kopfzerbrechen und dem Hinzufügen vieler console.log()s zu Discourse habe ich entdeckt, warum es nicht funktionierte und wie es zum Laufen gebracht werden kann.

Das Parsen erfolgt nicht mit dem gerenderten HTML, sondern mit den Markdown-Tokens. Ich hatte state.push(html_raw) in der replace()-Funktion verwendet, um meine [snapblocks] BBCode-Tags zu rendern.

// assets/javascripts/lib/discourse-markdown/snapblocks-discourse.js

export function(helper) {
  md.block.bbcode.ruler.push("snapblocks", {
      tag: "snapblocks",
      replace(state, tagInfo, content) {
        let token = state.push('html_raw', '', 0)
        token.content = `<pre class="snapblocks-blocks">${content}</pre>`
      },
    });
}

Das Problem war, dass der Token-Typ html_raw vom Rich-Text-Editor-Konverter ignoriert wird. Das bedeutet, dass Sie dies nicht verwenden können, wenn Sie Unterstützung für den Rich-Text-Editor wünschen.

Ich habe herausgefunden, dass es durch die Verwendung von bbcode_open, text und bbcode_close funktioniert.

// assets/javascripts/lib/discourse-markdown/snapblocks-discourse.js

export function(helper) {
  md.block.bbcode.ruler.push("snapblocks", {
      tag: "snapblocks",
      replace(state, tagInfo, content) {
        let token = state.push('bbcode_open', 'pre', 1)
        token.attrs = [['class', 'snapblocks-discourse']]

        token = state.push('text', '', 0)
        token.content = content

        token = token.push('bbcode_close', 'pre', -1)
        token.attrs = [['class', 'snapblocks-discourse']] // für spätere Prüfungen benötigt
      },
    });
}

Sobald dies erledigt ist, wird es nicht mehr ignoriert.

Wenn Sie zu rich-text-editor-extension.js wechseln, machen Sie Folgendes.

// assets/javascripts/lib/rich-text-editor-extension.js

import { i18n } from "discourse-i18n";

const SNAPBLOCKS_NODES = ["inline_snapblocks", "snapblocks"];

/** @type {RichEditorExtension} */
const extension = {
    snapblocks: {
      attrs: { rendered: { default: true } },
      code: true,
      group: "block",
      content: "text*", // Dies ist erforderlich
      createGapCursor: true,
      parseDOM:[{ tag: "pre.snapblocks-blocks" }],
      toDOM: () => ["pre", { class: "snapblocks-blocks" }, 0],
    },
  },
  parse: {
    bbcode_open(state, token) {
      // Der Token hier ist dasselbe `bbcode_open`-Token-Objekt
      // aus dem vorherigen Code
      if (token.attrGet('class') === 'snapblocks-blocks') {
        state.openNode(state.schema.nodes.snapblocks, {
          open: token.attrGet("open") !== null,
        });
        return true;
      }
    },
    bbcode_close(state, token) {
      if (token.attrGet('class') === 'snapblocks-blocks') {
        state.closeNode();
        return true;
      }
    },
  },
  serializeNode: {
    snapblocks(state, node) {
      // Dies konvertiert es einfach zurück in einfachen Text-Markdown
      state.write("[snapblocks]\n");
      state.renderContent(node);
      state.write("\n[/snapblocks]\n\n");
    },
  },
}

Die Schlüssel in der parse-Eigenschaft sind Parser für den Token-Typ, der im Markdown-Parser verwendet werden kann.

Es steckt definitiv mehr dahinter, aber zumindest klärt dies die Dinge viel mehr als zuvor.

1 „Gefällt mir“

Nicht ganz, aber wir haben bereits die html-block-Erweiterung, die die html_raw markdown-it-Tokens verarbeitet, was eine generische Methode zur Verarbeitung von Passthrough-Inhalten ist.

Sie können alle Typen von Erweiterungen überprüfen, die über registerRichEditorExtension zugelassen sind. Es gibt viele Erweiterungen von Plugins sowie die, die standardmäßig registriert sind und als Inspiration dienen können.

Bitte lassen Sie uns wissen, wenn Sie Fragen haben.

3 „Gefällt mir“

Danke für die Klarstellung.


Ich habe jetzt ein Problem, bei dem das Umschalten der Blockversion nicht funktioniert. Ich kann Inline-Blöcke umschalten, aber nicht den Block-Level-Knoten.

Irgendwann möchte ich, dass die Blöcke gerendert werden, wenn der Cursor nicht darauf ist, aber ich denke, das kann danach kommen, wenn es einfach funktioniert.

Entschuldigung, ich verstehe nicht. Was meinen Sie mit „Umschalten der Blockversion“?

Mein bbcode-Tag hat [snapblocks] und [sb], wobei [sb] inline ist und [snapblocks] block level ist. Wenn ich auf die Schaltfläche in der Symbolleiste klicke, wird der Inline-Tag umgeschaltet, aber der Block-Level-Tag wird nicht umgeschaltet, wenn ich einen Textblock auswähle.