feat(chat): add Mermaid fullscreen preview and harden file preview paths (#490)

* feat(chat): add mermaid preview popups and fullscreen diagram viewer

Enable opening Mermaid diagrams from markdown and file attachments with a dedicated fullscreen dialog, while tightening preview loading behavior and sizing for more reliable interaction.

* refactor(chat): extract shared preview overlay hooks

Centralize fullscreen preview transition and viewport lifecycle logic so image and Mermaid dialogs stay behaviorally aligned while reducing maintenance overhead.

* fix(security): enforce workspace boundaries for fs read endpoints

Validate /api/fs/read and /api/fs/raw paths against active workspace roots and canonical realpaths to block traversal and symlink escapes before serving file contents.

* fix(chat): remove dead Mermaid copy component

Drop an unused merge-leftover component in MarkdownRenderer to keep lint clean without changing Mermaid preview behavior.
This commit is contained in:
Iuliia Ivashko
2026-02-24 01:49:06 +02:00
committed by GitHub
parent b2101acfbf
commit d2d39c48ac
11 changed files with 882 additions and 157 deletions
+63
View File
@@ -867,6 +867,69 @@ html:not(.dark) .chat-scroll {
/* Mermaid block: position context for controls wrapper. */
[data-streamdown="mermaid-block"] {
position: relative;
border-radius: 0.75rem;
border: 1px solid var(--interactive-border);
background: var(--surface-elevated);
padding: 0.5rem;
}
[data-streamdown="mermaid-block"] [data-streamdown="mermaid"] {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
[data-streamdown="mermaid-block"] [data-streamdown="mermaid"] svg {
width: 100% !important;
max-width: none !important;
height: auto !important;
}
[data-streamdown="mermaid-block"] svg {
display: block;
background: var(--surface-elevated);
}
/* Fullscreen Mermaid popup: scale diagrams to fill available viewport panel area. */
.streamdown-mermaid-fullscreen {
height: 100%;
width: 100%;
}
.streamdown-mermaid-fullscreen .streamdown-content {
height: 100%;
width: 100%;
}
.streamdown-mermaid-fullscreen [data-streamdown="mermaid-block"] {
width: 100%;
height: 100%;
min-height: 100%;
padding: 0;
border: 0;
border-radius: 0;
background: var(--surface-elevated);
display: flex;
align-items: center;
justify-content: center;
}
.streamdown-mermaid-fullscreen [data-streamdown="mermaid-block"] [data-streamdown="mermaid"] {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.streamdown-mermaid-fullscreen [data-streamdown="mermaid-block"] svg {
width: 100% !important;
height: 100% !important;
max-width: 100% !important;
max-height: 100% !important;
display: block;
background: transparent;
}
/* Hide system caret in terminal - targets both Ghostty internal input and our custom touch input */