File tree Expand file tree Collapse file tree
packages/happy-app/sources/components/markdown Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -104,6 +104,8 @@ export const MermaidRenderer = React.memo((props: {
104104 }
105105
106106 // For iOS/Android, use WebView
107+ // Pass mermaid content via JSON to prevent XSS from HTML interpolation
108+ const mermaidContent = JSON . stringify ( props . content ) ;
107109 const html = `
108110 <!DOCTYPE html>
109111 <html>
@@ -123,25 +125,38 @@ export const MermaidRenderer = React.memo((props: {
123125 align-items: center;
124126 width: 100%;
125127 }
126- .mermaid {
127- text-align: center;
128- width: 100%;
129- }
130- .mermaid svg {
128+ #mermaid-container svg {
131129 max-width: 100%;
132130 height: auto;
133131 }
132+ .error {
133+ color: #ff6b6b;
134+ font-family: monospace;
135+ white-space: pre-wrap;
136+ }
134137 </style>
135138 </head>
136139 <body>
137- <div id="mermaid-container" class="mermaid">
138- ${ props . content }
139- </div>
140+ <div id="mermaid-container"></div>
140141 <script>
141- mermaid.initialize({
142- startOnLoad: true,
143- theme: 'dark'
144- });
142+ (async function() {
143+ const content = ${ mermaidContent } ;
144+ const container = document.getElementById('mermaid-container');
145+
146+ try {
147+ mermaid.initialize({
148+ startOnLoad: false,
149+ theme: 'dark'
150+ });
151+
152+ const { svg } = await mermaid.render('mermaid-diagram', content);
153+ container.innerHTML = svg;
154+ } catch (error) {
155+ container.innerHTML = '<div class="error">Diagram error: ' +
156+ (error.message || String(error)).replace(/</g, '<').replace(/>/g, '>') +
157+ '</div>';
158+ }
159+ })();
145160 </script>
146161 </body>
147162 </html>
You can’t perform that action at this time.
0 commit comments