Compare commits

..

4 Commits

Author SHA1 Message Date
darshanr0107
383f5b5bec fix: refactor code
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-12-15 17:10:37 +05:30
darshanr0107
efff583bb0 fix: another approach for markdown issue
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-12-15 16:24:58 +05:30
Shubham P
d435ac6fe1 Merge pull request #7228 from mermaid-js/renovate/peter-evans-create-pull-request-digest
chore(deps): update peter-evans/create-pull-request digest to 0979079
2025-12-15 06:47:12 +00:00
renovate[bot]
09c60be450 chore(deps): update peter-evans/create-pull-request digest to 0979079 2025-12-10 10:49:20 +00:00
7 changed files with 119 additions and 18 deletions

View File

@@ -58,7 +58,7 @@ jobs:
echo "EOF" >> $GITHUB_OUTPUT
- name: Commit and create pull request
uses: peter-evans/create-pull-request@84ae59a2cdc2258d6fa0732dd66352dddae2a412
uses: peter-evans/create-pull-request@0979079bc20c05bbbb590a56c21c4e2b1d1f1bbe
with:
add-paths: |
cypress/timings.json

View File

@@ -89,7 +89,7 @@ jobs:
continue-on-error: ${{ github.event_name == 'push' }}
run: pnpm run docs:verify
- uses: testomatio/check-tests@8d7e741fd2c9e46c8e8a3b27207731b0658e0fbe # stable
- uses: testomatio/check-tests@0ea638fcec1820cf2e7b9854fdbdd04128a55bd4 # stable
with:
framework: cypress
tests: './cypress/e2e/**/**.spec.js'

View File

@@ -1012,6 +1012,7 @@ You have to call mermaid.initialize.`
const baseNode = {
id: vertex.id,
label: vertex.text,
labelType: vertex.labelType,
labelStyle: '',
parentId,
padding: config.flowchart?.padding || 8,
@@ -1119,6 +1120,7 @@ You have to call mermaid.initialize.`
end: rawEdge.end,
type: rawEdge.type ?? 'normal',
label: rawEdge.text,
labelType: rawEdge.labelType,
labelpos: 'c',
thickness: rawEdge.stroke,
minlen: rawEdge.length,

View File

@@ -1,4 +1,4 @@
import { markdownToLines, markdownToHTML } from './handle-markdown-text.js';
import { markdownToLines, markdownToHTML, hasMarkdownSyntax } from './handle-markdown-text.js';
import { test, expect } from 'vitest';
test('markdownToLines - Basic test', () => {
@@ -311,3 +311,35 @@ test('markdownToHTML - auto wrapping', () => {
)
).toMatchInlineSnapshot('"<p>Hello, how do<br/>you do?</p>"');
});
test('hasMarkdownSyntax - detects bold text', () => {
expect(hasMarkdownSyntax('This is **bold** text')).toBe(true);
expect(hasMarkdownSyntax('**Bold**')).toBe(true);
expect(hasMarkdownSyntax('Text with **bold** in middle')).toBe(true);
});
test('hasMarkdownSyntax - detects italic text', () => {
expect(hasMarkdownSyntax('This is *italic* text')).toBe(true);
expect(hasMarkdownSyntax('*Italic*')).toBe(true);
expect(hasMarkdownSyntax('Text with *italic* in middle')).toBe(true);
});
test('hasMarkdownSyntax - detects mixed formatting', () => {
expect(hasMarkdownSyntax('*Italic* and **bold**')).toBe(true);
expect(hasMarkdownSyntax('The dog in **the** hog')).toBe(true);
});
test('hasMarkdownSyntax - returns false for plain text', () => {
expect(hasMarkdownSyntax('This is plain text')).toBe(false);
expect(hasMarkdownSyntax('The dog in the hog')).toBe(false);
expect(hasMarkdownSyntax('Simple label')).toBe(false);
expect(hasMarkdownSyntax('')).toBe(false);
});
test('hasMarkdownSyntax - handles edge cases', () => {
expect(hasMarkdownSyntax(null as any)).toBe(false);
expect(hasMarkdownSyntax(undefined as any)).toBe(false);
expect(hasMarkdownSyntax(' ')).toBe(false);
expect(hasMarkdownSyntax('Text with asterisks * but not italic')).toBe(false);
expect(hasMarkdownSyntax('Text with ** but not bold')).toBe(false);
});

View File

@@ -70,6 +70,42 @@ export function markdownToLines(markdown: string, config: MermaidConfig = {}): M
return lines;
}
/**
* Checks if text contains actual markdown syntax (bold, italic, etc.)
* This helps validate that labels marked as 'markdown' actually contain markdown
* @param text - text to check
* @returns true if text contains markdown syntax, false otherwise
*/
export function hasMarkdownSyntax(text: string): boolean {
if (!text || typeof text !== 'string') {
return false;
}
try {
const nodes = marked.lexer(text);
// Check if any node contains markdown formatting
function hasMarkdownInNode(node: Token): boolean {
if (node.type === 'strong' || node.type === 'em') {
return true;
}
if (node.type === 'paragraph' && node.tokens) {
return node.tokens.some(hasMarkdownInNode);
}
if ('tokens' in node && node.tokens) {
return node.tokens.some(hasMarkdownInNode);
}
return false;
}
return nodes.some(hasMarkdownInNode);
} catch (error) {
// If parsing fails, assume it's not markdown
log.debug('Failed to parse text as markdown:', error);
return false;
}
}
export function markdownToHTML(markdown: string, { markdownAutoWrap }: MermaidConfig = {}) {
const nodes = marked.lexer(markdown);

View File

@@ -45,16 +45,29 @@ export const getLabelStyles = (styleArray) => {
};
export const insertEdgeLabel = async (elem, edge) => {
let useHtmlLabels = evaluate(getConfig().flowchart.htmlLabels);
const config = getConfig();
let useHtmlLabels = evaluate(config.flowchart.htmlLabels);
// Only process as markdown if labelType is explicitly 'markdown'
// This ensures only labels properly delimited with ["`...`"] are processed as markdown
// This validation is restricted to flowcharts only
const isFlowchart = config.flowchart !== undefined;
const shouldProcessAsMarkdown = isFlowchart && edge.labelType === 'markdown';
const { labelStyles } = styles2String(edge);
edge.labelStyle = labelStyles;
const labelElement = await createText(elem, edge.label, {
style: edge.labelStyle,
useHtmlLabels,
addSvgBackground: true,
isNode: false,
});
let labelElement;
if (shouldProcessAsMarkdown) {
labelElement = await createText(elem, edge.label, {
style: edge.labelStyle,
useHtmlLabels,
addSvgBackground: true,
isNode: false,
});
} else {
labelElement = await createLabel(edge.label, edge.labelStyle, undefined, false);
}
log.info('abc82', edge, edge.labelType);
// Create outer g, edgeLabel, this will be positioned after graph layout

View File

@@ -6,6 +6,7 @@ import defaultConfig from '../../../defaultConfig.js';
import { evaluate, sanitizeText } from '../../../diagrams/common/common.js';
import { decodeEntities, handleUndefinedAttr, parseFontSize } from '../../../utils.js';
import type { D3Selection, Point } from '../../../types.js';
import createLabel from '../createLabel.js';
export const labelHelper = async <T extends SVGGraphicsElement>(
parent: D3Selection<T>,
@@ -40,14 +41,31 @@ export const labelHelper = async <T extends SVGGraphicsElement>(
label = typeof node.label === 'string' ? node.label : node.label[0];
}
const text = await createText(labelEl, sanitizeText(decodeEntities(label), getConfig()), {
useHtmlLabels,
width: node.width || getConfig().flowchart?.wrappingWidth,
// @ts-expect-error -- This is currently not used. Should this be `classes` instead?
cssClasses: 'markdown-node-label',
style: node.labelStyle,
addSvgBackground: !!node.icon || !!node.img,
});
// Only process as markdown if labelType is explicitly 'markdown'
// This ensures only labels properly delimited with ["`...`"] are processed as markdown
// This validation is restricted to flowcharts only
const config = getConfig();
const isFlowchart = config.flowchart !== undefined;
const shouldProcessAsMarkdown = isFlowchart && node.labelType === 'markdown';
let text;
if (shouldProcessAsMarkdown) {
text = await createText(labelEl, sanitizeText(decodeEntities(label), config), {
useHtmlLabels,
width: node.width || config.flowchart?.wrappingWidth,
// @ts-expect-error -- This is currently not used. Should this be `classes` instead?
cssClasses: 'markdown-node-label',
style: node.labelStyle,
addSvgBackground: !!node.icon || !!node.img,
});
} else {
const labelElement = await createLabel(
sanitizeText(decodeEntities(label), config),
node.labelStyle,
false,
true
);
text = labelEl.node()?.appendChild(labelElement);
}
// Get the size of the label
let bbox = text.getBBox();
const halfPadding = (node?.padding ?? 0) / 2;