mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-12-25 21:56:25 +01:00
Compare commits
21 Commits
sidv/testA
...
fix/5646
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
590784221a | ||
|
|
46d612d135 | ||
|
|
b1b480a13b | ||
|
|
3681a7a4c1 | ||
|
|
587c3c8884 | ||
|
|
8b5b1d4701 | ||
|
|
70dcfc83e6 | ||
|
|
3698c2b1e4 | ||
|
|
df872427af | ||
|
|
720aef6ff0 | ||
|
|
d71fe28a35 | ||
|
|
644199d0d0 | ||
|
|
207bc7c090 | ||
|
|
4bb75e5e37 | ||
|
|
84b51792d6 | ||
|
|
cc6eae22b3 | ||
|
|
7afff877e5 | ||
|
|
4eba114c8b | ||
|
|
4434cf39a7 | ||
|
|
8bdd37ca44 | ||
|
|
0d110350f4 |
8
.github/workflows/e2e.yml
vendored
8
.github/workflows/e2e.yml
vendored
@@ -117,7 +117,7 @@ jobs:
|
||||
id: cypress
|
||||
# If CYPRESS_RECORD_KEY is set, run in parallel on all containers
|
||||
# Otherwise (e.g. if running from fork), we run on a single container only
|
||||
if: ${{ env.shouldRunParallel || ( matrix.containers == 1 ) }}
|
||||
if: ${{ env.shouldRunParallel == 'true' || ( matrix.containers == 1 ) }}
|
||||
with:
|
||||
install: false
|
||||
start: pnpm run dev:coverage
|
||||
@@ -125,14 +125,14 @@ jobs:
|
||||
browser: chrome
|
||||
# Disable recording if we don't have an API key
|
||||
# e.g. if this action was run from a fork
|
||||
record: ${{ env.shouldRunParallel }}
|
||||
parallel: ${{ env.shouldRunParallel }}
|
||||
record: ${{ env.shouldRunParallel == 'true' }}
|
||||
parallel: ${{ env.shouldRunParallel == 'true' }}
|
||||
env:
|
||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
||||
VITEST_COVERAGE: true
|
||||
CYPRESS_COMMIT: ${{ github.sha }}
|
||||
ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
|
||||
ARGOS_PARALLEL: ${{ env.shouldRunParallel }}
|
||||
ARGOS_PARALLEL: ${{ env.shouldRunParallel == 'true' }}
|
||||
ARGOS_PARALLEL_TOTAL: 4
|
||||
ARGOS_PARALLEL_INDEX: ${{ matrix.containers }}
|
||||
|
||||
|
||||
@@ -10,6 +10,15 @@ describe('packet structure', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should render a simple packet diagram without ranges', () => {
|
||||
imgSnapshotTest(
|
||||
`packet-beta
|
||||
0: "h"
|
||||
1: "i"
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
it('should render a complex packet diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`packet-beta
|
||||
|
||||
@@ -20,7 +20,7 @@ describe('Quadrant Chart', () => {
|
||||
quadrant-2 Need to promote
|
||||
quadrant-3 Re-evaluate
|
||||
quadrant-4 May be improved
|
||||
Campaign A: [0.3, 0.61]
|
||||
Campaign A: [0.3, 0.6]
|
||||
Campaign B: [0.45, 0.23]
|
||||
Campaign C: [0.57, 0.69]
|
||||
Campaign D: [0.78, 0.34]
|
||||
@@ -54,7 +54,7 @@ describe('Quadrant Chart', () => {
|
||||
x-axis Low Reach --> High Reach
|
||||
y-axis Low Engagement --> High Engagement
|
||||
quadrant-1 We should expand
|
||||
quadrant-2 Need to promot
|
||||
quadrant-2 Need to promote
|
||||
quadrant-3 Re-evaluate
|
||||
quadrant-4 May be improved
|
||||
`,
|
||||
|
||||
@@ -205,7 +205,7 @@ describe('XY Chart', () => {
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||
y-axis "Revenue (in $)" 4000 --> 11000
|
||||
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6010]
|
||||
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||
`,
|
||||
{}
|
||||
@@ -239,15 +239,15 @@ describe('XY Chart', () => {
|
||||
config:
|
||||
xyChart:
|
||||
xAxis:
|
||||
showTick: true
|
||||
showTick: false
|
||||
yAxis:
|
||||
showTick: true
|
||||
showTick: false
|
||||
---
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||
y-axis "Revenue (in $)" 4000 --> 11000
|
||||
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 5000]
|
||||
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||
`,
|
||||
{}
|
||||
@@ -268,7 +268,7 @@ describe('XY Chart', () => {
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||
y-axis "Revenue (in $)" 4000 --> 11000
|
||||
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6001]
|
||||
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||
`,
|
||||
{}
|
||||
|
||||
@@ -483,8 +483,8 @@ a _[valid CSS property name](https://www.w3.org/TR/CSS/#properties)_ followed by
|
||||
|
||||
Here is an example of a classDef with just one property-value pair:
|
||||
|
||||
```
|
||||
classDef movement font-style:italic;
|
||||
```txt
|
||||
classDef movement font-style:italic;
|
||||
```
|
||||
|
||||
where
|
||||
@@ -496,8 +496,8 @@ If you want to have more than one _property-value pair_ then you put a comma (`,
|
||||
|
||||
Here is an example with three property-value pairs:
|
||||
|
||||
```
|
||||
classDef badBadEvent fill:#f00,color:white,font-weight:bold,stroke-width:2px,stroke:yellow
|
||||
```txt
|
||||
classDef badBadEvent fill:#f00,color:white,font-weight:bold,stroke-width:2px,stroke:yellow
|
||||
```
|
||||
|
||||
where
|
||||
@@ -522,7 +522,7 @@ There are two ways to apply a `classDef` style to a state:
|
||||
A `class` statement tells Mermaid to apply the named classDef to one or more classes. The form is:
|
||||
|
||||
```txt
|
||||
class [one or more state names, separated by commas] [name of a style defined with classDef]
|
||||
class [one or more state names, separated by commas] [name of a style defined with classDef]
|
||||
```
|
||||
|
||||
Here is an example applying the `badBadEvent` style to a state named `Crash`:
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
"katex": "^0.16.9",
|
||||
"khroma": "^2.1.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mdast-util-from-markdown": "^2.0.0",
|
||||
"marked": "^13.0.2",
|
||||
"stylis": "^4.3.1",
|
||||
"ts-dedent": "^2.2.0",
|
||||
"uuid": "^9.0.1"
|
||||
|
||||
@@ -104,6 +104,7 @@ export const labelHelper = async (parent, node, _classes, isNode) => {
|
||||
bbox = div.getBoundingClientRect();
|
||||
dv.attr('width', bbox.width);
|
||||
dv.attr('height', bbox.height);
|
||||
dv.style('height', bbox.height + 'px');
|
||||
}
|
||||
|
||||
// Center the label
|
||||
|
||||
@@ -288,8 +288,8 @@ a _[valid CSS property name](https://www.w3.org/TR/CSS/#properties)_ followed by
|
||||
|
||||
Here is an example of a classDef with just one property-value pair:
|
||||
|
||||
```
|
||||
classDef movement font-style:italic;
|
||||
```txt
|
||||
classDef movement font-style:italic;
|
||||
```
|
||||
|
||||
where
|
||||
@@ -301,8 +301,8 @@ If you want to have more than one _property-value pair_ then you put a comma (`,
|
||||
|
||||
Here is an example with three property-value pairs:
|
||||
|
||||
```
|
||||
classDef badBadEvent fill:#f00,color:white,font-weight:bold,stroke-width:2px,stroke:yellow
|
||||
```txt
|
||||
classDef badBadEvent fill:#f00,color:white,font-weight:bold,stroke-width:2px,stroke:yellow
|
||||
```
|
||||
|
||||
where
|
||||
@@ -327,7 +327,7 @@ There are two ways to apply a `classDef` style to a state:
|
||||
A `class` statement tells Mermaid to apply the named classDef to one or more classes. The form is:
|
||||
|
||||
```txt
|
||||
class [one or more state names, separated by commas] [name of a style defined with classDef]
|
||||
class [one or more state names, separated by commas] [name of a style defined with classDef]
|
||||
```
|
||||
|
||||
Here is an example applying the `badBadEvent` style to a state named `Crash`:
|
||||
|
||||
@@ -40,11 +40,14 @@ function addHtmlSpan(element, node, width, classes, addBackground = false) {
|
||||
div.style('display', 'table');
|
||||
div.style('white-space', 'break-spaces');
|
||||
div.style('width', width + 'px');
|
||||
bbox = div.node().getBoundingClientRect();
|
||||
const newBbox = div.node().getBoundingClientRect();
|
||||
if (newBbox.height > 0) {
|
||||
bbox = newBbox;
|
||||
}
|
||||
}
|
||||
|
||||
fo.style('width', bbox.width);
|
||||
fo.style('height', bbox.height);
|
||||
fo.style('width', bbox.width + 'px');
|
||||
fo.style('height', bbox.height + 'px');
|
||||
|
||||
return fo.node();
|
||||
}
|
||||
@@ -153,7 +156,7 @@ function updateTextContentAndStyles(tspan: any, wrappedLine: MarkdownWord[]) {
|
||||
wrappedLine.forEach((word, index) => {
|
||||
const innerTspan = tspan
|
||||
.append('tspan')
|
||||
.attr('font-style', word.type === 'emphasis' ? 'italic' : 'normal')
|
||||
.attr('font-style', word.type === 'em' ? 'italic' : 'normal')
|
||||
.attr('class', 'text-inner-tspan')
|
||||
.attr('font-weight', word.type === 'strong' ? 'bold' : 'normal');
|
||||
if (index === 0) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-irregular-whitespace */
|
||||
import { markdownToLines, markdownToHTML } from './handle-markdown-text.js';
|
||||
import { test, expect } from 'vitest';
|
||||
|
||||
@@ -37,9 +36,9 @@ Here is a line *with an italic* section`;
|
||||
{ content: 'is', type: 'normal' },
|
||||
{ content: 'a', type: 'normal' },
|
||||
{ content: 'line', type: 'normal' },
|
||||
{ content: 'with', type: 'emphasis' },
|
||||
{ content: 'an', type: 'emphasis' },
|
||||
{ content: 'italic', type: 'emphasis' },
|
||||
{ content: 'with', type: 'em' },
|
||||
{ content: 'an', type: 'em' },
|
||||
{ content: 'italic', type: 'em' },
|
||||
{ content: 'section', type: 'normal' },
|
||||
],
|
||||
];
|
||||
@@ -143,7 +142,7 @@ test('markdownToLines - Only italic formatting', () => {
|
||||
{ content: 'This', type: 'normal' },
|
||||
{ content: 'is', type: 'normal' },
|
||||
{ content: 'an', type: 'normal' },
|
||||
{ content: 'italic', type: 'emphasis' },
|
||||
{ content: 'italic', type: 'em' },
|
||||
{ content: 'test', type: 'normal' },
|
||||
],
|
||||
];
|
||||
@@ -156,7 +155,7 @@ it('markdownToLines - Mixed formatting', () => {
|
||||
let input = `*Italic* and **bold** formatting`;
|
||||
let expected = [
|
||||
[
|
||||
{ content: 'Italic', type: 'emphasis' },
|
||||
{ content: 'Italic', type: 'em' },
|
||||
{ content: 'and', type: 'normal' },
|
||||
{ content: 'bold', type: 'strong' },
|
||||
{ content: 'formatting', type: 'normal' },
|
||||
@@ -167,9 +166,9 @@ it('markdownToLines - Mixed formatting', () => {
|
||||
input = `*Italic with space* and **bold ws** formatting`;
|
||||
expected = [
|
||||
[
|
||||
{ content: 'Italic', type: 'emphasis' },
|
||||
{ content: 'with', type: 'emphasis' },
|
||||
{ content: 'space', type: 'emphasis' },
|
||||
{ content: 'Italic', type: 'em' },
|
||||
{ content: 'with', type: 'em' },
|
||||
{ content: 'space', type: 'em' },
|
||||
{ content: 'and', type: 'normal' },
|
||||
{ content: 'bold', type: 'strong' },
|
||||
{ content: 'ws', type: 'strong' },
|
||||
@@ -191,9 +190,9 @@ Word!`;
|
||||
{ content: 'the', type: 'strong' },
|
||||
{ content: 'hog...', type: 'normal' },
|
||||
{ content: 'a', type: 'normal' },
|
||||
{ content: 'very', type: 'emphasis' },
|
||||
{ content: 'long', type: 'emphasis' },
|
||||
{ content: 'text', type: 'emphasis' },
|
||||
{ content: 'very', type: 'em' },
|
||||
{ content: 'long', type: 'em' },
|
||||
{ content: 'text', type: 'em' },
|
||||
{ content: 'about', type: 'normal' },
|
||||
{ content: 'it', type: 'normal' },
|
||||
],
|
||||
@@ -215,13 +214,13 @@ test('markdownToLines - No auto wrapping', () => {
|
||||
[
|
||||
[
|
||||
{
|
||||
"content": "Hello, how do",
|
||||
"content": "Hello, how do",
|
||||
"type": "normal",
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
"content": "you do?",
|
||||
"content": "you do?",
|
||||
"type": "normal",
|
||||
},
|
||||
],
|
||||
@@ -298,3 +297,13 @@ test('markdownToHTML - no auto wrapping', () => {
|
||||
)
|
||||
).toMatchInlineSnapshot('"<p>Hello, how do<br/>you do?</p>"');
|
||||
});
|
||||
|
||||
test('markdownToHTML - auto wrapping', () => {
|
||||
expect(
|
||||
markdownToHTML(
|
||||
`Hello, how do
|
||||
you do?`,
|
||||
{ markdownAutoWrap: true }
|
||||
)
|
||||
).toMatchInlineSnapshot('"<p>Hello, how do<br/>you do?</p>"');
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Content } from 'mdast';
|
||||
import { fromMarkdown } from 'mdast-util-from-markdown';
|
||||
import type { MarkedToken, Token } from 'marked';
|
||||
import { marked } from 'marked';
|
||||
import { dedent } from 'ts-dedent';
|
||||
import type { MarkdownLine, MarkdownWordType } from './types.js';
|
||||
import type { MermaidConfig } from '../config.type.js';
|
||||
@@ -24,13 +24,13 @@ function preprocessMarkdown(markdown: string, { markdownAutoWrap }: MermaidConfi
|
||||
*/
|
||||
export function markdownToLines(markdown: string, config: MermaidConfig = {}): MarkdownLine[] {
|
||||
const preprocessedMarkdown = preprocessMarkdown(markdown, config);
|
||||
const { children } = fromMarkdown(preprocessedMarkdown);
|
||||
const nodes = marked.lexer(preprocessedMarkdown);
|
||||
const lines: MarkdownLine[] = [[]];
|
||||
let currentLine = 0;
|
||||
|
||||
function processNode(node: Content, parentType: MarkdownWordType = 'normal') {
|
||||
function processNode(node: MarkedToken, parentType: MarkdownWordType = 'normal') {
|
||||
if (node.type === 'text') {
|
||||
const textLines = node.value.split('\n');
|
||||
const textLines = node.text.split('\n');
|
||||
textLines.forEach((textLine, index) => {
|
||||
if (index !== 0) {
|
||||
currentLine++;
|
||||
@@ -42,17 +42,17 @@ export function markdownToLines(markdown: string, config: MermaidConfig = {}): M
|
||||
}
|
||||
});
|
||||
});
|
||||
} else if (node.type === 'strong' || node.type === 'emphasis') {
|
||||
node.children.forEach((contentNode) => {
|
||||
processNode(contentNode, node.type);
|
||||
} else if (node.type === 'strong' || node.type === 'em') {
|
||||
node.tokens.forEach((contentNode) => {
|
||||
processNode(contentNode as MarkedToken, node.type);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
children.forEach((treeNode) => {
|
||||
nodes.forEach((treeNode) => {
|
||||
if (treeNode.type === 'paragraph') {
|
||||
treeNode.children.forEach((contentNode) => {
|
||||
processNode(contentNode);
|
||||
treeNode.tokens?.forEach((contentNode) => {
|
||||
processNode(contentNode as MarkedToken);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -61,23 +61,23 @@ export function markdownToLines(markdown: string, config: MermaidConfig = {}): M
|
||||
}
|
||||
|
||||
export function markdownToHTML(markdown: string, { markdownAutoWrap }: MermaidConfig = {}) {
|
||||
const { children } = fromMarkdown(markdown);
|
||||
const nodes = marked.lexer(markdown);
|
||||
|
||||
function output(node: Content): string {
|
||||
function output(node: Token): string {
|
||||
if (node.type === 'text') {
|
||||
if (markdownAutoWrap === false) {
|
||||
return node.value.replace(/\n/g, '<br/>').replace(/ /g, ' ');
|
||||
return node.text.replace(/\n */g, '<br/>').replace(/ /g, ' ');
|
||||
}
|
||||
return node.value.replace(/\n/g, '<br/>');
|
||||
return node.text.replace(/\n */g, '<br/>');
|
||||
} else if (node.type === 'strong') {
|
||||
return `<strong>${node.children.map(output).join('')}</strong>`;
|
||||
} else if (node.type === 'emphasis') {
|
||||
return `<em>${node.children.map(output).join('')}</em>`;
|
||||
return `<strong>${node.tokens?.map(output).join('')}</strong>`;
|
||||
} else if (node.type === 'em') {
|
||||
return `<em>${node.tokens?.map(output).join('')}</em>`;
|
||||
} else if (node.type === 'paragraph') {
|
||||
return `<p>${node.children.map(output).join('')}</p>`;
|
||||
return `<p>${node.tokens?.map(output).join('')}</p>`;
|
||||
}
|
||||
return `Unsupported markdown: ${node.type}`;
|
||||
}
|
||||
|
||||
return children.map(output).join('');
|
||||
return nodes.map(output).join('');
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export type MarkdownWordType = 'normal' | 'strong' | 'emphasis';
|
||||
export type MarkdownWordType = 'normal' | 'strong' | 'em';
|
||||
export interface MarkdownWord {
|
||||
content: string;
|
||||
type: MarkdownWordType;
|
||||
|
||||
1805
pnpm-lock.yaml
generated
1805
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -25,6 +25,7 @@ const formatBytes = (bytes: number): string => {
|
||||
if (bytes == 0) {
|
||||
return '0 Bytes';
|
||||
}
|
||||
bytes = Math.abs(bytes);
|
||||
const base = 1024;
|
||||
const decimals = 2;
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||
|
||||
Reference in New Issue
Block a user