Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug/4391 make markdown auto wrapping optional #4856

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

NODE_OPTIONS=--max_old_space_size=8192 pnpm run pre-commit
NODE_OPTIONS="--max_old_space_size=8192" pnpm run pre-commit
12 changes: 12 additions & 0 deletions cypress/integration/rendering/flowchart-v2.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,18 @@ end
);
});
});

it('should not auto wrap when markdownAutoWrap is false', () => {
imgSnapshotTest(
`flowchart TD
angular_velocity["\`**angular_velocity**
*angular_displacement / duration*
[rad/s, 1/s]
{vector}\`"]
frequency["frequency\n(1 / period_duration)\n[Hz, 1/s]"]`,
{ markdownAutoWrap: false }
);
});
});
describe('Subgraph title margins', () => {
it('Should render subgraphs with title margins set (LR)', () => {
Expand Down
2 changes: 1 addition & 1 deletion docs/config/setup/modules/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Pushes in a directive to the configuration
| --------- | ------------------------- | ----------- | ------------------------------ |
| getConfig | Obtains the currentConfig | Get Request | Any Values from current Config |

**Notes**: Returns **any** the currentConfig
**Notes**: Avoid calling this function repeatedly. Instead, store the result in a variable and use it, and pass it down to function calls.

#### Returns

Expand Down
10 changes: 10 additions & 0 deletions docs/syntax/flowchart.md
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,16 @@ Formatting:

This feature is applicable to node labels, edge labels, and subgraph labels.

The auto wrapping can be disabled by using

```
---
config:
markdownAutoWrap: false
---
graph LR
```

## Interaction

It is possible to bind a click event to a node, the click can lead to either a javascript callback or to a link which will be opened in a new browser tab.
Expand Down
2 changes: 1 addition & 1 deletion packages/mermaid/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export const setConfig = (conf: MermaidConfig): MermaidConfig => {
* | --------- | ------------------------- | ----------- | ------------------------------ |
* | getConfig | Obtains the currentConfig | Get Request | Any Values from current Config |
*
* **Notes**: Returns **any** the currentConfig
* **Notes**: Avoid calling this function repeatedly. Instead, store the result in a variable and use it, and pass it down to function calls.
*
* @returns The currentConfig
*/
Expand Down
1 change: 1 addition & 0 deletions packages/mermaid/src/config.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ export interface MermaidConfig {
dompurifyConfig?: DOMPurifyConfiguration;
wrap?: boolean;
fontSize?: number;
markdownAutoWrap?: boolean;
/**
* Suppresses inserting 'Syntax error' diagram in the DOM.
* This is useful when you want to control how to handle syntax errors in your application.
Expand Down
2 changes: 1 addition & 1 deletion packages/mermaid/src/dagre-wrapper/clusters.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const rect = (parent, node) => {
// .appendChild(createLabel(node.labelText, node.labelStyle, undefined, true));
const text =
node.labelType === 'markdown'
? createText(label, node.labelText, { style: node.labelStyle, useHtmlLabels })
? createText(label, node.labelText, { style: node.labelStyle, useHtmlLabels }, siteConfig)
: label.node().appendChild(createLabel(node.labelText, node.labelStyle, undefined, true));

// Get the size of the label
Expand Down
18 changes: 12 additions & 6 deletions packages/mermaid/src/dagre-wrapper/edges.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,21 @@ export const clear = () => {
};

export const insertEdgeLabel = (elem, edge) => {
const useHtmlLabels = evaluate(getConfig().flowchart.htmlLabels);
const config = getConfig();
const useHtmlLabels = evaluate(config.flowchart.htmlLabels);
// Create the actual text element
const labelElement =
edge.labelType === 'markdown'
? createText(elem, edge.label, {
style: edge.labelStyle,
useHtmlLabels,
addSvgBackground: true,
})
? createText(
elem,
edge.label,
{
style: edge.labelStyle,
useHtmlLabels,
addSvgBackground: true,
},
config
)
: createLabel(edge.label, edge.labelStyle);

// Create outer g, edgeLabel, this will be positioned after graph layout
Expand Down
31 changes: 16 additions & 15 deletions packages/mermaid/src/dagre-wrapper/shapes/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import { evaluate, sanitizeText } from '../../diagrams/common/common.js';
import { decodeEntities } from '../../utils.js';

export const labelHelper = async (parent, node, _classes, isNode) => {
const config = getConfig();
let classes;
const useHtmlLabels = node.useHtmlLabels || evaluate(getConfig().flowchart.htmlLabels);
const useHtmlLabels = node.useHtmlLabels || evaluate(config.flowchart.htmlLabels);
if (!_classes) {
classes = 'node default';
} else {
Expand Down Expand Up @@ -35,26 +36,26 @@ export const labelHelper = async (parent, node, _classes, isNode) => {
let text;
if (node.labelType === 'markdown') {
// text = textNode;
text = createText(label, sanitizeText(decodeEntities(labelText), getConfig()), {
useHtmlLabels,
width: node.width || getConfig().flowchart.wrappingWidth,
classes: 'markdown-node-label',
});
text = createText(
label,
sanitizeText(decodeEntities(labelText), config),
{
useHtmlLabels,
width: node.width || config.flowchart.wrappingWidth,
classes: 'markdown-node-label',
},
config
);
} else {
text = textNode.appendChild(
createLabel(
sanitizeText(decodeEntities(labelText), getConfig()),
node.labelStyle,
false,
isNode
)
createLabel(sanitizeText(decodeEntities(labelText), config), node.labelStyle, false, isNode)
);
}
// Get the size of the label
let bbox = text.getBBox();
const halfPadding = node.padding / 2;

if (evaluate(getConfig().flowchart.htmlLabels)) {
if (evaluate(config.flowchart.htmlLabels)) {
const div = text.children[0];
const dv = select(text);

Expand All @@ -76,8 +77,8 @@ export const labelHelper = async (parent, node, _classes, isNode) => {

if (noImgText) {
// default size if no text
const bodyFontSize = getConfig().fontSize
? getConfig().fontSize
const bodyFontSize = config.fontSize
? config.fontSize
: window.getComputedStyle(document.body).fontSize;
const enlargingFactor = 5;
const width = parseInt(bodyFontSize, 10) * enlargingFactor + 'px';
Expand Down
6 changes: 2 additions & 4 deletions packages/mermaid/src/diagrams/common/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,11 +346,9 @@ export const renderKatex = async (text: string, config: MermaidConfig): Promise<
.split(lineBreakRegex)
.map((line) =>
hasKatex(line)
? `
<div style="display: flex; align-items: center; justify-content: center; white-space: nowrap;">
? `<div style="display: flex; align-items: center; justify-content: center; white-space: nowrap;">
${line}
</div>
`
</div>`
: `<div>${line}</div>`
)
.join('')
Expand Down
15 changes: 10 additions & 5 deletions packages/mermaid/src/diagrams/mindmap/svgDraw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,16 @@ export const drawNode = function (
// Create the wrapped text element
const textElem = nodeElem.append('g');
const description = node.descr.replace(/(<br\/*>)/g, '\n');
const newEl = createText(textElem, description, {
useHtmlLabels: htmlLabels,
width: node.width,
classes: 'mindmap-node-label',
});
const newEl = createText(
textElem,
description,
{
useHtmlLabels: htmlLabels,
width: node.width,
classes: 'mindmap-node-label',
},
conf
);

if (!htmlLabels) {
textElem
Expand Down
10 changes: 10 additions & 0 deletions packages/mermaid/src/docs/syntax/flowchart.md
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,16 @@ Formatting:

This feature is applicable to node labels, edge labels, and subgraph labels.

The auto wrapping can be disabled by using

```
---
config:
markdownAutoWrap: false
---
graph LR
```

## Interaction

It is possible to bind a click event to a node, the click can lead to either a javascript callback or to a link which will be opened in a new browser tab.
Expand Down
14 changes: 7 additions & 7 deletions packages/mermaid/src/rendering-util/createText.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
// @ts-nocheck TODO: Fix types
import type { MermaidConfig } from '../config.type.js';
import type { Group } from '../diagram-api/types.js';
import type { D3TSpanElement, D3TextElement } from '../diagrams/common/commonTypes.js';
import { log } from '../logger.js';
Expand All @@ -21,8 +22,7 @@ function addHtmlSpan(element, node, width, classes, addBackground = false) {
const label = node.label;
const labelClass = node.isNode ? 'nodeLabel' : 'edgeLabel';
div.html(
`
<span class="${labelClass} ${classes}" ` +
`<span class="${labelClass} ${classes}" ` +
(node.labelStyle ? 'style="' + node.labelStyle + '"' : '') +
'>' +
label +
Expand Down Expand Up @@ -181,14 +181,14 @@ export const createText = (
isNode = true,
width = 200,
addSvgBackground = false,
} = {}
} = {},
config: MermaidConfig
) => {
log.info('createText', text, style, isTitle, classes, useHtmlLabels, isNode, addSvgBackground);
if (useHtmlLabels) {
// TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that?
// text = text.replace(/\\n|\n/g, '<br />');
const htmlText = markdownToHTML(text);
// log.info('markdownToHTML' + text, markdownToHTML(text));

const htmlText = markdownToHTML(text, config);
const node = {
isNode,
label: decodeEntities(htmlText).replace(
Expand All @@ -200,7 +200,7 @@ export const createText = (
const vertexNode = addHtmlSpan(el, node, width, classes, addSvgBackground);
return vertexNode;
} else {
const structuredText = markdownToLines(text);
const structuredText = markdownToLines(text, config);
const svgLabel = createFormattedText(width, el, structuredText, addSvgBackground);
return svgLabel;
}
Expand Down
36 changes: 36 additions & 0 deletions packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-irregular-whitespace */
import { markdownToLines, markdownToHTML } from './handle-markdown-text.js';
import { test, expect } from 'vitest';

Expand Down Expand Up @@ -203,6 +204,31 @@ Word!`;
expect(output).toEqual(expectedOutput);
});

test('markdownToLines - No auto wrapping', () => {
expect(
markdownToLines(
`Hello, how do
you do?`,
{ markdownAutoWrap: false }
)
).toMatchInlineSnapshot(`
[
[
{
"content": "Hello, how do",
"type": "normal",
},
],
[
{
"content": "you do?",
"type": "normal",
},
],
]
`);
});

test('markdownToHTML - Basic test', () => {
const input = `This is regular text
Here is a new line
Expand Down Expand Up @@ -262,3 +288,13 @@ test('markdownToHTML - Unsupported formatting', () => {
- l3`)
).toMatchInlineSnapshot('"<p>Hello</p>Unsupported markdown: list"');
});

test('markdownToHTML - no auto wrapping', () => {
expect(
markdownToHTML(
`Hello, how do
you do?`,
{ markdownAutoWrap: false }
)
).toMatchInlineSnapshot('"<p>Hello,&nbsp;how&nbsp;do<br/>you&nbsp;do?</p>"');
});
15 changes: 11 additions & 4 deletions packages/mermaid/src/rendering-util/handle-markdown-text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,28 @@ import type { Content } from 'mdast';
import { fromMarkdown } from 'mdast-util-from-markdown';
import { dedent } from 'ts-dedent';
import type { MarkdownLine, MarkdownWordType } from './types.js';
import type { MermaidConfig } from '../config.type.js';

/**
* @param markdown - markdown to process
* @returns processed markdown
*/
function preprocessMarkdown(markdown: string): string {
function preprocessMarkdown(markdown: string, { markdownAutoWrap }: MermaidConfig): string {
// Replace multiple newlines with a single newline
const withoutMultipleNewlines = markdown.replace(/\n{2,}/g, '\n');
// Remove extra spaces at the beginning of each line
const withoutExtraSpaces = dedent(withoutMultipleNewlines);
if (markdownAutoWrap === false) {
return withoutExtraSpaces.replace(/ /g, '&nbsp;');
}
return withoutExtraSpaces;
}

/**
* @param markdown - markdown to split into lines
*/
export function markdownToLines(markdown: string): MarkdownLine[] {
const preprocessedMarkdown = preprocessMarkdown(markdown);
export function markdownToLines(markdown: string, config: MermaidConfig = {}): MarkdownLine[] {
const preprocessedMarkdown = preprocessMarkdown(markdown, config);
const { children } = fromMarkdown(preprocessedMarkdown);
const lines: MarkdownLine[] = [[]];
let currentLine = 0;
Expand Down Expand Up @@ -56,11 +60,14 @@ export function markdownToLines(markdown: string): MarkdownLine[] {
return lines;
}

export function markdownToHTML(markdown: string) {
export function markdownToHTML(markdown: string, { markdownAutoWrap }: MermaidConfig = {}) {
const { children } = fromMarkdown(markdown);

function output(node: Content): string {
if (node.type === 'text') {
if (markdownAutoWrap === false) {
return node.value.replace(/\n/g, '<br/>').replace(/ /g, '&nbsp;');
}
return node.value.replace(/\n/g, '<br/>');
} else if (node.type === 'strong') {
return `<strong>${node.children.map(output).join('')}</strong>`;
Expand Down
3 changes: 3 additions & 0 deletions packages/mermaid/src/schemas/config.schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,9 @@ properties:
fontSize:
type: number
default: 16
markdownAutoWrap:
type: boolean
sidharthv96 marked this conversation as resolved.
Show resolved Hide resolved
default: true
suppressErrorRendering:
type: boolean
default: false
Expand Down
Loading