feat: Add mermaidjs integration (#3679)
* feat: Add mermaidjs integration (#3523) * Add mermaidjs to dependencies and CodeFenceNode * Fix diagram id for mermaidjs diagrams * Fix typescript compiler errors on mermaid integration * Fix id generation for mermaid diagrams * Refactor mermaidjs integration into prosemirror plugin * Remove unnecessary class attribute in mermaidjs integration * Change mermaidjs label to singular * Change decorator.inline to decorator.node for mermaid diagram id * Fix diagram toggle state * Add border and background to mermaid diagrams * Stop mermaidjs from overwriting fontFamily inside diagrams * Add stable diagramId to mermaid diagrams * Separate text for hide/show diagram Use uuid as diagramId, avoid storing in state Fix cursor on diagrams * fix: Base diagram visibility off presence of source * fix: More cases where our font-family is ignored * Disable HTML labels * fix: Button styling – not technically required but now we have a third button this felt all the more needed closes #3116 * named chunks * Upgrade mermaid 9.1.3 Co-authored-by: Jan Niklas Richter <5812215+ArcticXWolf@users.noreply.github.com>
This commit is contained in:
@@ -38,6 +38,7 @@ import { Dictionary } from "~/hooks/useDictionary";
|
||||
|
||||
import toggleBlockType from "../commands/toggleBlockType";
|
||||
import { MarkdownSerializerState } from "../lib/markdown/serializer";
|
||||
import Mermaid from "../plugins/Mermaid";
|
||||
import Prism, { LANGUAGES } from "../plugins/Prism";
|
||||
import isInCode from "../queries/isInCode";
|
||||
import { Dispatch } from "../types";
|
||||
@@ -114,7 +115,7 @@ export default class CodeFence extends Node {
|
||||
],
|
||||
toDOM: (node) => {
|
||||
const button = document.createElement("button");
|
||||
button.innerText = "Copy";
|
||||
button.innerText = this.options.dictionary.copy;
|
||||
button.type = "button";
|
||||
button.addEventListener("click", this.handleCopyToClipboard);
|
||||
|
||||
@@ -135,9 +136,30 @@ export default class CodeFence extends Node {
|
||||
select.appendChild(option);
|
||||
});
|
||||
|
||||
// For the Mermaid language we add an extra button to toggle between
|
||||
// source code and a rendered diagram view.
|
||||
if (node.attrs.language === "mermaidjs") {
|
||||
const showSourceButton = document.createElement("button");
|
||||
showSourceButton.innerText = this.options.dictionary.showSource;
|
||||
showSourceButton.type = "button";
|
||||
showSourceButton.classList.add("show-source-button");
|
||||
showSourceButton.addEventListener("click", this.handleToggleDiagram);
|
||||
actions.prepend(showSourceButton);
|
||||
|
||||
const showDiagramButton = document.createElement("button");
|
||||
showDiagramButton.innerText = this.options.dictionary.showDiagram;
|
||||
showDiagramButton.type = "button";
|
||||
showDiagramButton.classList.add("show-digram-button");
|
||||
showDiagramButton.addEventListener("click", this.handleToggleDiagram);
|
||||
actions.prepend(showDiagramButton);
|
||||
}
|
||||
|
||||
return [
|
||||
"div",
|
||||
{ class: "code-block", "data-language": node.attrs.language },
|
||||
{
|
||||
class: "code-block",
|
||||
"data-language": node.attrs.language,
|
||||
},
|
||||
["div", { contentEditable: "false" }, actions],
|
||||
["pre", ["code", { spellCheck: "false" }, 0]],
|
||||
];
|
||||
@@ -222,20 +244,46 @@ export default class CodeFence extends Node {
|
||||
|
||||
if (result) {
|
||||
const language = element.value;
|
||||
|
||||
const transaction = tr
|
||||
.setSelection(Selection.near(view.state.doc.resolve(result.inside)))
|
||||
.setNodeMarkup(result.inside, undefined, {
|
||||
language,
|
||||
});
|
||||
|
||||
view.dispatch(transaction);
|
||||
|
||||
localStorage?.setItem(PERSISTENCE_KEY, language);
|
||||
}
|
||||
};
|
||||
|
||||
handleToggleDiagram = (event: InputEvent) => {
|
||||
const { view } = this.editor;
|
||||
const { tr } = view.state;
|
||||
const element = event.currentTarget;
|
||||
if (!(element instanceof HTMLButtonElement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { top, left } = element.getBoundingClientRect();
|
||||
const result = view.posAtCoords({ top, left });
|
||||
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
const diagramId = element
|
||||
.closest(".code-block")
|
||||
?.getAttribute("data-diagram-id");
|
||||
if (!diagramId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const transaction = tr.setMeta("mermaid", { toggleDiagram: diagramId });
|
||||
view.dispatch(transaction);
|
||||
};
|
||||
|
||||
get plugins() {
|
||||
return [Prism({ name: this.name })];
|
||||
return [Prism({ name: this.name }), Mermaid({ name: this.name })];
|
||||
}
|
||||
|
||||
inputRules({ type }: { type: NodeType }) {
|
||||
|
||||
Reference in New Issue
Block a user