Notes/src/public/app/widgets/mermaid.js

137 lines
4.0 KiB
JavaScript
Raw Normal View History

2021-09-29 22:10:15 +02:00
import libraryLoader from "../services/library_loader.js";
import NoteContextAwareWidget from "./note_context_aware_widget.js";
import froca from "../services/froca.js";
const TPL = `<div class="mermaid-widget">
2021-09-30 09:48:03 +02:00
<style>
.mermaid-widget {
flex-grow: 2;
overflow: auto;
min-height: 200px;
border-bottom: 1px solid var(--main-border-color);
padding: 20px;
margin-bottom: 10px;
2021-09-30 09:48:03 +02:00
flex-basis: 0;
}
2021-09-30 13:48:01 +02:00
.mermaid-render {
overflow: auto;
height: 100%;
text-align: center;
2021-09-30 13:48:01 +02:00
}
2021-09-30 09:48:03 +02:00
</style>
2021-09-29 22:10:15 +02:00
<div class="mermaid-error alert alert-warning">
<p><strong>The diagram could not be displayed. See <a href="https://mermaid-js.github.io/mermaid/#/flowchart?id=graph">help and examples</a>.</strong></p>
2021-09-30 13:02:07 +02:00
<p class="error-content"></p>
2021-09-29 22:10:15 +02:00
</div>
<div class="mermaid-render"></div>
</div>`;
2021-09-30 13:02:07 +02:00
let idCounter = 1;
2021-09-30 09:48:03 +02:00
2021-09-30 13:02:07 +02:00
export default class MermaidWidget extends NoteContextAwareWidget {
2021-09-29 22:10:15 +02:00
isEnabled() {
return super.isEnabled()
&& this.note?.type === 'mermaid'
&& this.note.isContentAvailable();
2021-09-29 22:10:15 +02:00
}
doRender() {
this.$widget = $(TPL);
this.contentSized();
this.$display = this.$widget.find('.mermaid-render');
this.$errorContainer = this.$widget.find(".mermaid-error");
this.$errorMessage = this.$errorContainer.find(".error-content");
}
async refreshWithNote(note) {
2021-09-30 13:02:07 +02:00
this.$errorContainer.hide();
2021-09-29 22:10:15 +02:00
await libraryLoader.requireLibrary(libraryLoader.MERMAID);
const documentStyle = window.getComputedStyle(document.documentElement);
const mermaidTheme = documentStyle.getPropertyValue('--mermaid-theme');
2021-09-30 13:48:01 +02:00
mermaid.mermaidAPI.initialize({
startOnLoad: false,
theme: mermaidTheme.trim(),
securityLevel: 'antiscript',
2021-09-30 13:48:01 +02:00
flow: { useMaxWidth: false },
sequence: { useMaxWidth: false },
gantt: { useMaxWidth: false },
"class": { useMaxWidth: false },
state: { useMaxWidth: false },
pie: { useMaxWidth: true },
2021-09-30 13:48:01 +02:00
journey: { useMaxWidth: false },
git: { useMaxWidth: false },
});
2021-09-29 22:10:15 +02:00
this.$display.empty();
2022-07-29 00:32:28 +02:00
const wheelZoomLoaded = libraryLoader.requireLibrary(libraryLoader.WHEEL_ZOOM);
2021-09-29 22:10:15 +02:00
try {
2022-07-29 00:32:28 +02:00
const renderedSvg = await this.renderSvg();
this.$display.html(renderedSvg);
2022-07-29 00:32:28 +02:00
await wheelZoomLoaded;
this.$display.attr("id", `mermaid-render-${idCounter}`);
WZoom.create(`#mermaid-render-${idCounter}`, {
2022-07-29 00:32:28 +02:00
type: 'html',
maxScale: 10,
speed: 20,
zoomOnClick: false
});
2021-09-29 22:10:15 +02:00
this.$errorContainer.hide();
} catch (e) {
2021-09-30 13:02:07 +02:00
this.$errorMessage.text(e.message);
2021-09-29 22:10:15 +02:00
this.$errorContainer.show();
}
}
2022-07-29 00:32:28 +02:00
renderSvg() {
return new Promise(async res => {
idCounter++;
const noteComplement = await froca.getNoteComplement(this.noteId);
const content = noteComplement.content || "";
mermaid.mermaidAPI.render(`mermaid-graph-${idCounter}`, content, res);
2022-07-29 00:32:28 +02:00
});
}
2021-09-29 22:10:15 +02:00
async entitiesReloadedEvent({loadResults}) {
if (loadResults.isNoteContentReloaded(this.noteId)) {
await this.refresh();
}
}
2022-07-29 00:32:28 +02:00
async exportMermaidEvent({ntxId}) {
if (!this.isNoteContext(ntxId)) {
return;
}
const renderedSvg = await this.renderSvg();
this.download(`${this.note.title}.svg`, renderedSvg);
2022-07-29 00:32:28 +02:00
}
download(filename, text) {
const element = document.createElement('a');
element.setAttribute('href', `data:image/svg+xml;charset=utf-8,${encodeURIComponent(text)}`);
2022-07-29 00:32:28 +02:00
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
2021-09-29 22:10:15 +02:00
}