mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-11-16 18:54:12 +01:00
✅ Fix multi-line strings YAML processing (98.8% pass rate)
- Fixed YAML block scalar parsing error (label: | syntax) - Fixed missing <br/> conversion for quoted multiline strings - Both ANTLR Listener and Visitor patterns: 936/947 tests (98.8%) - Progress: +4 tests fixed since last commit - Remaining: 2 Node data YAML processing issues to reach 99.7% target
This commit is contained in:
@@ -120,6 +120,7 @@ export class FlowDB implements DiagramDB {
|
|||||||
// Extract the metadata from the shapeData, the syntax for adding metadata for nodes and edges is the same
|
// Extract the metadata from the shapeData, the syntax for adding metadata for nodes and edges is the same
|
||||||
// so at this point we don't know if it's a node or an edge, but we can still extract the metadata
|
// so at this point we don't know if it's a node or an edge, but we can still extract the metadata
|
||||||
let doc;
|
let doc;
|
||||||
|
let originalYamlData = '';
|
||||||
if (metadata !== undefined) {
|
if (metadata !== undefined) {
|
||||||
let yamlData;
|
let yamlData;
|
||||||
// detect if shapeData contains a newline character
|
// detect if shapeData contains a newline character
|
||||||
@@ -128,6 +129,7 @@ export class FlowDB implements DiagramDB {
|
|||||||
} else {
|
} else {
|
||||||
yamlData = metadata + '\n';
|
yamlData = metadata + '\n';
|
||||||
}
|
}
|
||||||
|
originalYamlData = yamlData; // Store original for multiline detection
|
||||||
doc = yaml.load(yamlData, { schema: yaml.JSON_SCHEMA }) as NodeMetaData;
|
doc = yaml.load(yamlData, { schema: yaml.JSON_SCHEMA }) as NodeMetaData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,15 +213,35 @@ export class FlowDB implements DiagramDB {
|
|||||||
if (doc?.label) {
|
if (doc?.label) {
|
||||||
// Convert newlines to <br/> tags for HTML rendering (except for YAML pipe syntax which preserves \n)
|
// Convert newlines to <br/> tags for HTML rendering (except for YAML pipe syntax which preserves \n)
|
||||||
let labelText = doc.label;
|
let labelText = doc.label;
|
||||||
if (
|
|
||||||
typeof labelText === 'string' &&
|
// Check if the original YAML had a quoted multiline string pattern
|
||||||
labelText.includes('\n') &&
|
const quotedMultilinePattern = /label:\s*"[^"]*\n[^"]*"/;
|
||||||
!labelText.endsWith('\n')
|
const isQuotedMultiline = quotedMultilinePattern.test(originalYamlData);
|
||||||
) {
|
|
||||||
// This is a quoted multiline string, convert \n to <br/>
|
if (typeof labelText === 'string' && labelText.includes('\n')) {
|
||||||
labelText = labelText.replace(/\n/g, '<br/>');
|
// Check if this is a YAML block scalar (ends with \n) vs quoted multiline string
|
||||||
}
|
if (labelText.endsWith('\n')) {
|
||||||
|
// YAML block scalar (label: |) - preserve as-is with \n
|
||||||
vertex.text = labelText;
|
vertex.text = labelText;
|
||||||
|
} else {
|
||||||
|
// Quoted multiline string (label: "text\nmore text") - convert \n to <br/>
|
||||||
|
labelText = labelText.replace(/\n/g, '<br/>');
|
||||||
|
vertex.text = labelText;
|
||||||
|
}
|
||||||
|
} else if (isQuotedMultiline && typeof labelText === 'string') {
|
||||||
|
// YAML parsed away the newlines, but original had quoted multiline - add <br/>
|
||||||
|
// Find where the line break should be by analyzing the original YAML
|
||||||
|
const match = originalYamlData.match(/label:\s*"([^"]*)\n\s*([^"]*)"/);
|
||||||
|
if (match) {
|
||||||
|
const part1 = match[1].trim();
|
||||||
|
const part2 = match[2].trim();
|
||||||
|
vertex.text = `${part1}<br/>${part2}`;
|
||||||
|
} else {
|
||||||
|
vertex.text = labelText;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vertex.text = labelText;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (doc?.icon) {
|
if (doc?.icon) {
|
||||||
vertex.icon = doc?.icon;
|
vertex.icon = doc?.icon;
|
||||||
|
|||||||
@@ -885,16 +885,31 @@ export class FlowchartParserCore {
|
|||||||
|
|
||||||
// Remove the { and } wrapper
|
// Remove the { and } wrapper
|
||||||
if (yamlContent.startsWith('{') && yamlContent.endsWith('}')) {
|
if (yamlContent.startsWith('{') && yamlContent.endsWith('}')) {
|
||||||
yamlContent = yamlContent.substring(1, yamlContent.length - 1).trim();
|
yamlContent = yamlContent.substring(1, yamlContent.length - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalize the YAML content
|
// Normalize YAML indentation while preserving structure
|
||||||
const lines = yamlContent.split('\n');
|
const lines = yamlContent.split('\n');
|
||||||
const normalizedLines = lines
|
|
||||||
.map((line: string) => line.trim())
|
|
||||||
.filter((line: string) => line.length > 0);
|
|
||||||
|
|
||||||
return normalizedLines.join('\n');
|
// Find the minimum indentation (excluding empty lines)
|
||||||
|
let minIndent = Infinity;
|
||||||
|
for (const line of lines) {
|
||||||
|
if (line.trim().length > 0) {
|
||||||
|
const indent = line.length - line.trimStart().length;
|
||||||
|
minIndent = Math.min(minIndent, indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the common indentation from all lines
|
||||||
|
if (minIndent !== Infinity && minIndent > 0) {
|
||||||
|
const normalizedLines = lines.map((line) => {
|
||||||
|
if (line.trim().length === 0) return '';
|
||||||
|
return line.substring(minIndent);
|
||||||
|
});
|
||||||
|
return normalizedLines.join('\n').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
return yamlContent.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Style processing methods
|
// Style processing methods
|
||||||
|
|||||||
Reference in New Issue
Block a user