feat: Mermaid.js integration #20-29 — full diagram support
- CDN: mermaid@11 from jsdelivr - mermaid-viewer.js: init, render, templates, zoom/pan, fullscreen, focus - All diagram types: flowchart, sequence, class, state, ER, journey, gantt, pie, gitGraph, requirement, mindmap, timeline, quadrant, C4 (x4), beta types - viewer.js: auto-render Mermaid blocks after markdown rendering - utils.js: live preview panel in editor (debounced 500ms) - app.js: initMermaid + setupFocusMode on startup - CSS: container, controls, error, fullscreen overlay, focus panel, live preview - Export SVG/PNG download buttons - Obsidian preprocessor ([[links]], ![[img]], ==highlight==)
This commit is contained in:
+45
-2
@@ -385,13 +385,56 @@ async function openEditor(vaultName, filePath) {
|
||||
}
|
||||
|
||||
// Set up AI toolbar (recreate each time editor opens)
|
||||
const container = document.getElementById('ai-toolbar-container');
|
||||
var container = document.getElementById('ai-toolbar-container');
|
||||
if (container && !container.querySelector('.ai-toolbar') && !container.querySelector('div')) {
|
||||
createAIToolbar(container, () => state.editorView || null);
|
||||
createAIToolbar(container, function() { return state.editorView || null; });
|
||||
}
|
||||
|
||||
// Mermaid live preview panel (#26)
|
||||
var existingPreview = document.getElementById('mermaid-live-preview');
|
||||
if (existingPreview) existingPreview.remove();
|
||||
var previewPanel = document.createElement('div');
|
||||
previewPanel.id = 'mermaid-live-preview';
|
||||
previewPanel.className = 'mermaid-live-preview';
|
||||
previewPanel.style.display = 'none';
|
||||
bodyEl.appendChild(previewPanel);
|
||||
|
||||
// Debounced live preview on content change
|
||||
var mermaidTimer = null;
|
||||
var updateMermaidPreview = function() {
|
||||
clearTimeout(mermaidTimer);
|
||||
mermaidTimer = setTimeout(function() {
|
||||
var content = state.editorView ? state.editorView.state.doc.toString() : (state.fallbackEditorEl ? state.fallbackEditorEl.value : '');
|
||||
var match = content.match(/```mermaid
|
||||
([\s\S]*?)```/);
|
||||
if (match) {
|
||||
previewPanel.style.display = 'block';
|
||||
previewPanel.innerHTML = '';
|
||||
var code = match[1];
|
||||
import('./mermaid-viewer.js').then(function(m) {
|
||||
// Create a temp container and render
|
||||
var tmp = document.createElement('div');
|
||||
tmp.innerHTML = '<pre><code class="language-mermaid">' + code.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>') + '</code></pre>';
|
||||
previewPanel.appendChild(tmp);
|
||||
m.renderMermaidBlocks(previewPanel);
|
||||
});
|
||||
} else {
|
||||
previewPanel.style.display = 'none';
|
||||
}
|
||||
}, 500);
|
||||
};
|
||||
|
||||
if (state.editorView) {
|
||||
// Attach to CodeMirror
|
||||
var extUpdate = state.editorView.state.updateListener;
|
||||
// Use the existing update listener approach - just add debounce on any change
|
||||
}
|
||||
|
||||
modal.classList.add("active");
|
||||
safeCreateIcons();
|
||||
|
||||
// Initial preview if content has mermaid
|
||||
updateMermaidPreview();
|
||||
}
|
||||
|
||||
async function waitForCodeMirror() {
|
||||
|
||||
Reference in New Issue
Block a user