diff --git a/packages/mermaid/src/diagrams/flowchart/flowDb.ts b/packages/mermaid/src/diagrams/flowchart/flowDb.ts index 632633730..ff7249511 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowDb.ts +++ b/packages/mermaid/src/diagrams/flowchart/flowDb.ts @@ -207,7 +207,17 @@ export class FlowDB implements DiagramDB { } if (doc?.label) { - vertex.text = doc?.label; + // Convert newlines to
tags for HTML rendering (except for YAML pipe syntax which preserves \n) + let labelText = doc.label; + if ( + typeof labelText === 'string' && + labelText.includes('\n') && + !labelText.endsWith('\n') + ) { + // This is a quoted multiline string, convert \n to
+ labelText = labelText.replace(/\n/g, '
'); + } + vertex.text = labelText; } if (doc?.icon) { vertex.icon = doc?.icon; diff --git a/packages/mermaid/src/diagrams/flowchart/parser/antlr/antlr-parser.ts b/packages/mermaid/src/diagrams/flowchart/parser/antlr/antlr-parser.ts index a7ddd9bc7..597aa3116 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/antlr/antlr-parser.ts +++ b/packages/mermaid/src/diagrams/flowchart/parser/antlr/antlr-parser.ts @@ -443,13 +443,76 @@ class FlowchartListener implements ParseTreeListener { yamlContent = yamlContent.substring(1, yamlContent.length - 1).trim(); } - // Normalize YAML indentation to fix inconsistent whitespace + // Handle YAML content more carefully to preserve multiline strings const lines = yamlContent.split('\n'); - const normalizedLines = lines - .map((line) => line.trim()) // Remove leading/trailing whitespace - .filter((line) => line.length > 0); // Remove empty lines - shapeDataYaml = normalizedLines.join('\n'); + // Check if this contains YAML pipe syntax (|) which needs special handling + const hasPipeSyntax = yamlContent.includes('|'); + + // Check if this contains quoted multiline strings that need
conversion + const hasQuotedMultiline = + yamlContent.includes('"') && + yamlContent.includes('\n') && + /label:\s*"[^"]*\n[^"]*"/.test(yamlContent); + + if (hasQuotedMultiline) { + // Handle quoted multiline strings - convert newlines to
before YAML processing + let processedYaml = yamlContent; + + // Find quoted multiline strings and replace newlines with
+ processedYaml = processedYaml.replace( + /label:\s*"([^"]*\n[^"]*?)"/g, + (_match: string, content: string) => { + const convertedContent = content.replace(/\n\s*/g, '
'); + return `label: "${convertedContent}"`; + } + ); + + // Normalize the processed YAML + const processedLines = processedYaml.split('\n'); + const normalizedLines = processedLines + .map((line: string) => line.trim()) + .filter((line: string) => line.length > 0); + + shapeDataYaml = normalizedLines.join('\n'); + } else if (hasPipeSyntax) { + // For pipe syntax, preserve the structure but fix indentation + // The pipe syntax requires proper indentation to work + let minIndent = Infinity; + const nonEmptyLines = lines.filter((line: string) => line.trim().length > 0); + + // Find minimum indentation (excluding the first line which might be "label: |") + for (let i = 1; i < nonEmptyLines.length; i++) { + const line = nonEmptyLines[i]; + const match = line.match(/^(\s*)/); + if (match && line.trim().length > 0) { + minIndent = Math.min(minIndent, match[1].length); + } + } + + // Normalize indentation while preserving structure + const normalizedLines = lines.map((line: string, index: number) => { + if (line.trim().length === 0) return ''; // Keep empty lines + if (index === 0 || line.includes(':')) { + // First line or lines with colons (property definitions) + return line.trim(); + } else { + // Content lines - preserve relative indentation + const currentIndent = line.match(/^(\s*)/)?.[1]?.length || 0; + const relativeIndent = Math.max(0, currentIndent - minIndent); + return ' '.repeat(relativeIndent) + line.trim(); + } + }); + + shapeDataYaml = normalizedLines.join('\n'); + } else { + // For regular YAML, normalize as before + const normalizedLines = lines + .map((line: string) => line.trim()) // Remove leading/trailing whitespace + .filter((line: string) => line.length > 0); // Remove empty lines + + shapeDataYaml = normalizedLines.join('\n'); + } } // Add vertex to database