Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
850cd94
feat: add Insert Diagram modal with previews and search filter
ThisIs-Developer Jun 22, 2026
94de31e
feat: render actual live diagrams in card previews and split preview …
ThisIs-Developer Jun 23, 2026
cbc1940
feat: use high-fidelity static SVGs matching actual diagram outputs f…
ThisIs-Developer Jun 23, 2026
399124b
feat: add diverse and visually distinct diagram templates per engine …
ThisIs-Developer Jun 23, 2026
5d512f8
feat: complete all diagram types with distinct previews for all engines
ThisIs-Developer Jun 23, 2026
e91e5e7
feat: complete all diagram templates, sync desktop app, and bump sw c…
ThisIs-Developer Jun 23, 2026
bb3626d
feat: implement theme-aware diagram preview rendering pipeline with o…
ThisIs-Developer Jun 23, 2026
163c6bc
feat: complete phases 1, 2, and 3 of diagram previews (theme fallback…
ThisIs-Developer Jun 23, 2026
4ae1716
fix: add missing closing markdown code block backticks to all PlantUM…
ThisIs-Developer Jun 24, 2026
e07a944
fix: resolve squished diagram SVGs by changing flexbox centering to t…
ThisIs-Developer Jun 24, 2026
4ecbe2b
fix: render PlantUML, D2, and Graphviz browser fallbacks inline to pr…
ThisIs-Developer Jun 24, 2026
2f2ed75
fix: preserve PlantUML diagram proportions
ThisIs-Developer Jun 24, 2026
a8486f5
fix: unify diagram rendering and viewer controls
ThisIs-Developer Jun 24, 2026
7ea49a2
fix: keep diagrams measurable while loading
ThisIs-Developer Jun 24, 2026
01848ea
fix: size diagram viewers to rendered content
ThisIs-Developer Jun 24, 2026
494af31
fix: harden dark and legacy diagram rendering
ThisIs-Developer Jun 24, 2026
3d91f18
fix: preserve diagram edges and zoom appearance
ThisIs-Developer Jun 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions desktop-app/neutralino.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"os.showMessageBox",
"os.open",
"os.setTray",
"os.execCommand",
"filesystem.readFile",
"filesystem.writeFile",
"storage.setData",
Expand Down
60 changes: 57 additions & 3 deletions desktop-app/resources/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ <h2 class="h5 m-0">Menu</h2>
<button type="button" class="markdown-tool-btn" data-md-action="emoji" title="Emoji shortcode" aria-label="Emoji shortcode"><i class="bi bi-emoji-smile"></i></button>
<button type="button" class="markdown-tool-btn" data-md-action="symbols" title="Symbols &amp; HTML entities" aria-label="Symbols &amp; HTML entities"><i class="bi bi-c-circle"></i></button>
<button type="button" class="markdown-tool-btn" data-md-action="alert" title="Markdown alert" aria-label="Markdown alert"><i class="bi bi-newspaper"></i></button>
<button type="button" class="markdown-tool-btn" data-md-action="diagram" title="Insert Diagram" aria-label="Insert Diagram"><i class="bi bi-diagram-3"></i></button>
</div>
<div class="markdown-toolbar-group">
<button type="button" class="markdown-tool-btn" data-md-action="fullscreen" title="Fullscreen" aria-label="Fullscreen"><i class="bi bi-arrows-fullscreen"></i></button>
Expand Down Expand Up @@ -774,6 +775,56 @@ <h3 class="modal-section-title">Open-source credits</h3>
</div>
</div>

<!-- Diagram & Chart Modal -->
<div id="diagram-modal" class="reset-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="diagram-modal-title" aria-hidden="true" style="display:none;">
<div class="reset-modal-box reset-modal-box--wide reset-modal-box--xl diagram-modal-box">
<div class="modal-header">
<p id="diagram-modal-title" class="reset-modal-message">Insert Diagram</p>
<button class="modal-close-btn" id="diagram-modal-close" aria-label="Close modal">&times;</button>
</div>

<div class="diagram-modal-body">
<!-- Sidebar Navigation -->
<div class="diagram-modal-sidebar" role="tablist" aria-label="Diagram Categories">
<!-- Populated dynamically via JS -->
</div>

<!-- Content Area -->
<div class="diagram-modal-content">
<div class="diagram-modal-search-wrapper">
<input type="text" id="diagram-modal-search" class="rename-modal-input" placeholder="Search diagrams..." />
</div>

<!-- Diagram Cards Grid -->
<div id="diagram-modal-grid" class="diagram-grid" role="listbox" aria-label="Diagram templates">
<!-- Populated dynamically via JS -->
</div>
<p id="diagram-modal-empty" class="modal-empty" style="display:none;">No diagrams found.</p>

<!-- Preview Container -->
<div class="diagram-modal-preview-section">
<p class="diagram-modal-preview-title">Preview</p>
<div class="diagram-modal-preview-split">
<!-- Left: Code -->
<div class="diagram-preview-code-pane">
<textarea id="diagram-modal-preview-code" readonly class="rename-modal-input diagram-preview-textarea" placeholder="Diagram source code..."></textarea>
</div>
<!-- Right: Visual Preview -->
<div id="diagram-modal-preview" class="diagram-preview-container">
<!-- Populated dynamically with selected template preview -->
</div>
</div>
</div>
</div>
</div>

<div class="reset-modal-actions">
<button class="reset-modal-btn reset-modal-cancel" id="diagram-modal-cancel">Cancel</button>
<button class="reset-modal-btn" id="diagram-modal-insert" disabled>Insert</button>
</div>
</div>
</div>

<!-- GitHub Import Modal -->
<div id="github-import-modal" class="reset-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="github-import-title" aria-hidden="true" style="display:none;">
<div class="reset-modal-box">
Expand Down Expand Up @@ -845,11 +896,11 @@ <h3 class="modal-section-title">Open-source credits</h3>
</main>
</div>

<!-- Mermaid Zoom Modal -->
<!-- Shared Diagram Viewer Modal -->
<div id="mermaid-zoom-modal" role="dialog" aria-modal="true" aria-label="Diagram zoom view" aria-hidden="true">
<div class="mermaid-modal-content">
<div class="mermaid-modal-header">
<span>Diagram</span>
<span id="diagram-modal-title">Diagram Viewer</span>
<button class="mermaid-modal-close" id="mermaid-modal-close" title="Close" aria-label="Close diagram modal">
<i class="bi bi-x-lg"></i>
</button>
Expand All @@ -865,6 +916,9 @@ <h3 class="modal-section-title">Open-source credits</h3>
<button class="mermaid-toolbar-btn" id="mermaid-modal-zoom-reset" title="Reset zoom">
<i class="bi bi-arrows-angle-contract"></i> Reset
</button>
<button class="mermaid-toolbar-btn" id="mermaid-modal-zoom-fit" title="Fit diagram to screen">
<i class="bi bi-aspect-ratio"></i> Fit
</button>
<button class="mermaid-toolbar-btn" id="mermaid-modal-copy" title="Copy image">
<i class="bi bi-clipboard-image"></i> Copy
</button>
Expand Down Expand Up @@ -1095,4 +1149,4 @@ <h3 class="modal-section-title">Open-source credits</h3>
<!-- Screen reader dynamic accessibility announcer -->
<div id="app-accessibility-announcer" class="visually-hidden" aria-live="polite" aria-atomic="true"></div>
</body>
</html>
</html>
37 changes: 33 additions & 4 deletions desktop-app/resources/js/preview-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ let topojsonIdCounter = 0;
let stlIdCounter = 0;
let plantumlIdCounter = 0;
let d2IdCounter = 0;
let graphvizIdCounter = 0;
let krokiIdCounter = 0;

const markedOptions = {
gfm: true,
Expand Down Expand Up @@ -312,15 +314,23 @@ function configureMarked() {
},
};

function renderDiagramShell(engine, containerClass, surfaceClass, uniqueId, code, label) {
return `<div class="diagram-viewer ${containerClass} is-loading" data-diagram-engine="${engine}">` +
`<div class="diagram-status" role="status"><span class="diagram-status-spinner" aria-hidden="true"></span>` +
`<span>Rendering ${label}…</span></div>` +
`<div class="diagram-surface ${surfaceClass}" id="${uniqueId}" data-original-code="${encodeURIComponent(code)}">${escapeHtml(code)}</div>` +
`</div>`;
}

renderer.code = function(code, language) {
if (language === "mermaid") {
const uniqueId = `mermaid-diagram-worker-${mermaidIdCounter++}`;
return `<div class="mermaid-container is-loading"><div class="mermaid" id="${uniqueId}" data-original-code="${encodeURIComponent(code)}">${escapeHtml(code)}</div></div>`;
return renderDiagramShell('mermaid', 'mermaid-container', 'mermaid', uniqueId, code, 'Mermaid');
}

if (language === "abc") {
const uniqueId = `abc-notation-worker-${abcIdCounter++}`;
return `<div class="abc-container is-loading"><div class="abc-notation" id="${uniqueId}" data-original-code="${encodeURIComponent(code)}">${escapeHtml(code)}</div></div>`;
return renderDiagramShell('abc', 'abc-container', 'abc-notation', uniqueId, code, 'ABC notation');
}

if (language === "geojson") {
Expand All @@ -340,12 +350,29 @@ function configureMarked() {

if (language === "plantuml") {
const uniqueId = `plantuml-diagram-worker-${plantumlIdCounter++}`;
return `<div class="plantuml-container is-loading"><div class="plantuml-diagram" id="${uniqueId}" data-original-code="${encodeURIComponent(code)}">${escapeHtml(code)}</div></div>`;
return renderDiagramShell('plantuml', 'plantuml-container', 'plantuml-diagram', uniqueId, code, 'PlantUML');
}

if (language === "d2") {
const uniqueId = `d2-diagram-worker-${d2IdCounter++}`;
return `<div class="d2-container is-loading"><div class="d2-diagram" id="${uniqueId}" data-original-code="${encodeURIComponent(code)}">${escapeHtml(code)}</div></div>`;
return renderDiagramShell('d2', 'd2-container', 'd2-diagram', uniqueId, code, 'D2');
}

if (language === "graphviz" || language === "dot") {
const uniqueId = `graphviz-diagram-worker-${graphvizIdCounter++}`;
return renderDiagramShell('graphviz', 'graphviz-container', 'graphviz-diagram', uniqueId, code, 'Graphviz');
}

const krokiLanguages = {
'vega-lite': ['vegalite', 'Vega-Lite'],
vegalite: ['vegalite', 'Vega-Lite'],
wavedrom: ['wavedrom', 'WaveDrom'],
markmap: ['markmap', 'Markmap']
};
if (krokiLanguages[language]) {
const [engine, label] = krokiLanguages[language];
const uniqueId = `${engine}-diagram-worker-${krokiIdCounter++}`;
return renderDiagramShell(engine, 'kroki-container', 'kroki-diagram', uniqueId, code, label);
}

if (language === "math") {
Expand Down Expand Up @@ -530,6 +557,8 @@ self.onmessage = function(event) {
stlIdCounter = 0;
plantumlIdCounter = 0;
d2IdCounter = 0;
graphvizIdCounter = 0;
krokiIdCounter = 0;
const result = renderSegmentedMarkdown(data.markdown || "", options);
self.postMessage({
type: "render-result",
Expand Down
Loading
Loading