mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-09 10:36:43 +02:00
Compare commits
8 Commits
6784-edge-
...
6671-code-
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f8e71102fd | ||
![]() |
642b781317 | ||
![]() |
4d26480075 | ||
![]() |
f35aae313c | ||
![]() |
d0cabd080f | ||
![]() |
c9eae01d06 | ||
![]() |
df9abe0be9 | ||
![]() |
c33484f9bc |
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Render newlines as spaces in class diagrams
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Ensure edge label color is applied when using classDef with edge IDs
|
114
.github/workflows/e2e.yml
vendored
114
.github/workflows/e2e.yml
vendored
@@ -38,6 +38,8 @@ jobs:
|
||||
options: --user 1001
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
@@ -55,6 +57,7 @@ jobs:
|
||||
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ env.targetHash }}
|
||||
|
||||
- name: Install dependencies
|
||||
@@ -83,6 +86,8 @@ jobs:
|
||||
containers: [1, 2, 3, 4, 5]
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
# uses version from "packageManager" field in package.json
|
||||
@@ -137,13 +142,118 @@ jobs:
|
||||
SPLIT_INDEX: ${{ strategy.job-index }}
|
||||
SPLIT_FILE: 'cypress/timings.json'
|
||||
VITEST_COVERAGE: true
|
||||
- name: Debug coverage generation
|
||||
if: ${{ steps.cypress.conclusion == 'success' }}
|
||||
run: |
|
||||
echo "Checking if coverage files were generated:"
|
||||
ls -la coverage/ || echo "No coverage directory"
|
||||
ls -la coverage/cypress/ || echo "No coverage/cypress directory"
|
||||
echo "Looking for any .info files:"
|
||||
find . -name "*.info" -type f | head -10 || echo "No .info files found"
|
||||
- name: Prepare coverage artifacts
|
||||
if: ${{ steps.cypress.conclusion == 'success' }}
|
||||
run: |
|
||||
mkdir -p coverage/cypress
|
||||
if [ -f coverage/cypress/coverage-final.json ]; then
|
||||
cp coverage/cypress/coverage-final.json coverage/cypress/coverage-final-${{ matrix.containers }}.json
|
||||
echo "Created coverage-final-${{ matrix.containers }}.json"
|
||||
ls -la coverage/cypress/coverage-final-${{ matrix.containers }}.json
|
||||
else
|
||||
echo "Error: coverage/cypress/coverage-final.json not found"
|
||||
exit 1
|
||||
fi
|
||||
- name: Upload e2e coverage artifact
|
||||
if: ${{ steps.cypress.conclusion == 'success' }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: e2e-coverage-${{ matrix.containers }}
|
||||
path: coverage/cypress/coverage-final-${{ matrix.containers }}.json
|
||||
|
||||
coverage-merge:
|
||||
runs-on: ubuntu-latest
|
||||
needs: e2e
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
- name: Download e2e coverage shards
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: e2e-coverage-*
|
||||
path: coverage/e2e-shards
|
||||
merge-multiple: true
|
||||
- name: Debug downloaded artifacts
|
||||
run: |
|
||||
echo "Contents of coverage/e2e-shards:"
|
||||
find coverage/e2e-shards -type f -name "*.info" | head -20
|
||||
echo "All files in coverage/e2e-shards:"
|
||||
ls -la coverage/e2e-shards/
|
||||
echo "Directory structure:"
|
||||
find coverage/e2e-shards -type f | head -20
|
||||
echo "Looking for coverage-final.json files:"
|
||||
find coverage/e2e-shards -name "coverage-final.json" | head -20
|
||||
- name: Install dependencies for merging
|
||||
run: pnpm install --frozen-lockfile
|
||||
env:
|
||||
CYPRESS_CACHE_FOLDER: .cache/Cypress
|
||||
- name: Prepare coverage files for merge script
|
||||
run: |
|
||||
mkdir -p coverage/vitest coverage/cypress
|
||||
# Copy E2E coverage-final.json files to the structure expected by scripts/coverage.ts
|
||||
for i in {1..5}; do
|
||||
if [ -f "coverage/e2e-shards/coverage-final-$i.json" ]; then
|
||||
cp "coverage/e2e-shards/coverage-final-$i.json" "coverage/cypress/coverage-final.json"
|
||||
echo "Copied coverage-final-$i.json to cypress/"
|
||||
break
|
||||
fi
|
||||
done
|
||||
# Create a minimal but valid vitest coverage-final.json
|
||||
echo '{"type":"Coverage","version":"1.1","data":{}}' > coverage/vitest/coverage-final.json
|
||||
echo "Prepared coverage files:"
|
||||
ls -la coverage/vitest/
|
||||
ls -la coverage/cypress/
|
||||
echo "Checking file contents:"
|
||||
echo "Vitest coverage file:"
|
||||
cat coverage/vitest/coverage-final.json
|
||||
echo "Cypress coverage file:"
|
||||
cat coverage/cypress/coverage-final.json
|
||||
echo "Validating JSON files:"
|
||||
if jq . coverage/vitest/coverage-final.json > /dev/null; then
|
||||
echo "✓ Vitest coverage file is valid JSON"
|
||||
else
|
||||
echo "✗ Vitest coverage file is invalid JSON"
|
||||
exit 1
|
||||
fi
|
||||
if jq . coverage/cypress/coverage-final.json > /dev/null; then
|
||||
echo "✓ Cypress coverage file is valid JSON"
|
||||
else
|
||||
echo "✗ Cypress coverage file is invalid JSON"
|
||||
exit 1
|
||||
fi
|
||||
- name: Generate LCOV from coverage data
|
||||
run: |
|
||||
mkdir -p coverage/combined
|
||||
# Convert coverage-final.json to LCOV format using nyc
|
||||
if [ -f coverage/cypress/coverage-final.json ]; then
|
||||
echo "Converting Cypress coverage to LCOV..."
|
||||
npx nyc report --reporter=lcov --report-dir=coverage/combined --cwd=. --temp-dir=coverage/cypress
|
||||
echo "LCOV generation completed"
|
||||
ls -la coverage/combined/
|
||||
else
|
||||
echo "No Cypress coverage file found"
|
||||
exit 1
|
||||
fi
|
||||
- name: Upload Coverage to Codecov
|
||||
uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1
|
||||
# Run step only pushes to develop and pull_requests
|
||||
if: ${{ steps.cypress.conclusion == 'success' && (github.event_name == 'pull_request' || github.ref == 'refs/heads/develop')}}
|
||||
if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/develop'}}
|
||||
with:
|
||||
files: coverage/cypress/lcov.info
|
||||
files: coverage/combined/lcov.info
|
||||
flags: e2e
|
||||
name: mermaid-codecov
|
||||
fail_ci_if_error: false
|
||||
|
3
.github/workflows/test.yml
vendored
3
.github/workflows/test.yml
vendored
@@ -10,6 +10,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
# uses version from "packageManager" field in package.json
|
||||
@@ -41,7 +43,6 @@ jobs:
|
||||
- name: Verify out-of-tree build with TypeScript
|
||||
run: |
|
||||
pnpm test:check:tsc
|
||||
|
||||
- name: Upload Coverage to Codecov
|
||||
uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1
|
||||
# Run step only pushes to develop and pull_requests
|
||||
|
14
.nycrc
Normal file
14
.nycrc
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"reporter": ["text", "lcov", "json", "html"],
|
||||
"exclude": [
|
||||
"node_modules/**/*",
|
||||
"cypress/**/*",
|
||||
"coverage/**/*",
|
||||
"**/*.spec.js",
|
||||
"**/*.spec.ts",
|
||||
"**/*.test.js",
|
||||
"**/*.test.ts"
|
||||
],
|
||||
"all": true,
|
||||
"check-coverage": false
|
||||
}
|
27
codecov.yml
Normal file
27
codecov.yml
Normal file
@@ -0,0 +1,27 @@
|
||||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
target: auto
|
||||
threshold: 1%
|
||||
patch:
|
||||
default:
|
||||
target: auto
|
||||
threshold: 1%
|
||||
|
||||
comment:
|
||||
layout: 'reach,diff,flags,tree'
|
||||
behavior: default
|
||||
require_changes: false
|
||||
|
||||
flags:
|
||||
unit:
|
||||
paths:
|
||||
- packages/
|
||||
e2e:
|
||||
paths:
|
||||
- packages/
|
||||
|
||||
# Wait for both unit and e2e coverage uploads before finalizing
|
||||
notify:
|
||||
after_n_builds: 2
|
@@ -15,6 +15,13 @@ export default eyesPlugin(
|
||||
setupNodeEvents(on, config) {
|
||||
coverage(on, config);
|
||||
cypressSplit(on, config);
|
||||
|
||||
// Ensure coverage generates LCOV format
|
||||
on('task', {
|
||||
coverage: () => {
|
||||
return null;
|
||||
},
|
||||
});
|
||||
on('before:browser:launch', (browser, launchOptions) => {
|
||||
if (browser.name === 'chrome' && browser.isHeadless) {
|
||||
launchOptions.args.push('--window-size=1440,1024', '--force-device-scale-factor=1');
|
||||
|
@@ -524,18 +524,5 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
it('should handle an empty class body with empty braces', () => {
|
||||
imgSnapshotTest(
|
||||
` classDiagram
|
||||
class FooBase~T~ {}
|
||||
class Bar {
|
||||
+Zip
|
||||
+Zap()
|
||||
}
|
||||
FooBase <|-- Ba
|
||||
`,
|
||||
{ flowchart: { defaultRenderer: 'elk' } }
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -1186,17 +1186,4 @@ end
|
||||
imgSnapshotTest(graph, { htmlLabels: false });
|
||||
});
|
||||
});
|
||||
|
||||
it('V2 - 17: should apply class def colour to edge label', () => {
|
||||
imgSnapshotTest(
|
||||
` graph LR
|
||||
id1(Start) link@-- "Label" -->id2(Stop)
|
||||
style id1 fill:#f9f,stroke:#333,stroke-width:4px
|
||||
|
||||
class id2 myClass
|
||||
classDef myClass fill:#bbf,stroke:#f66,stroke-width:2px,color:white,stroke-dasharray: 5 5
|
||||
class link myClass
|
||||
`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@@ -6,7 +6,7 @@
|
||||
|
||||
# Frequently Asked Questions
|
||||
|
||||
1. [How to add title to flowchart?](https://github.com/mermaid-js/mermaid/issues/1433#issuecomment-1991554712)
|
||||
1. [How to add title to flowchart?](https://github.com/mermaid-js/mermaid/issues/556#issuecomment-363182217)
|
||||
2. [How to specify custom CSS file?](https://github.com/mermaidjs/mermaid.cli/pull/24#issuecomment-373402785)
|
||||
3. [How to fix tooltip misplacement issue?](https://github.com/mermaid-js/mermaid/issues/542#issuecomment-3343564621)
|
||||
4. [How to specify gantt diagram xAxis format?](https://github.com/mermaid-js/mermaid/issues/269#issuecomment-373229136)
|
||||
|
@@ -1070,14 +1070,6 @@ describe('given a class diagram with members and methods ', function () {
|
||||
|
||||
parser.parse(str);
|
||||
});
|
||||
it('should handle an empty class body with {}', function () {
|
||||
const str = 'classDiagram\nclass EmptyClass {}';
|
||||
parser.parse(str);
|
||||
const actual = parser.yy.getClass('EmptyClass');
|
||||
expect(actual.label).toBe('EmptyClass');
|
||||
expect(actual.members.length).toBe(0);
|
||||
expect(actual.methods.length).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@@ -293,7 +293,6 @@ classStatement
|
||||
: classIdentifier
|
||||
| classIdentifier STYLE_SEPARATOR alphaNumToken {yy.setCssClass($1, $3);}
|
||||
| classIdentifier STRUCT_START members STRUCT_STOP {yy.addMembers($1,$3);}
|
||||
| classIdentifier STRUCT_START STRUCT_STOP {}
|
||||
| classIdentifier STYLE_SEPARATOR alphaNumToken STRUCT_START members STRUCT_STOP {yy.setCssClass($1, $3);yy.addMembers($1,$5);}
|
||||
;
|
||||
|
||||
@@ -302,15 +301,8 @@ classIdentifier
|
||||
| CLASS className classLabel {$$=$2; yy.addClass($2);yy.setClassLabel($2, $3);}
|
||||
;
|
||||
|
||||
|
||||
emptyBody
|
||||
:
|
||||
| SPACE emptyBody
|
||||
| NEWLINE emptyBody
|
||||
;
|
||||
|
||||
annotationStatement
|
||||
: ANNOTATION_START alphaNumToken ANNOTATION_END className { yy.addAnnotation($4,$2); }
|
||||
:ANNOTATION_START alphaNumToken ANNOTATION_END className { yy.addAnnotation($4,$2); }
|
||||
;
|
||||
|
||||
members
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# Frequently Asked Questions
|
||||
|
||||
1. [How to add title to flowchart?](https://github.com/mermaid-js/mermaid/issues/1433#issuecomment-1991554712)
|
||||
1. [How to add title to flowchart?](https://github.com/mermaid-js/mermaid/issues/556#issuecomment-363182217)
|
||||
1. [How to specify custom CSS file?](https://github.com/mermaidjs/mermaid.cli/pull/24#issuecomment-373402785)
|
||||
1. [How to fix tooltip misplacement issue?](https://github.com/mermaid-js/mermaid/issues/542#issuecomment-3343564621)
|
||||
1. [How to specify gantt diagram xAxis format?](https://github.com/mermaid-js/mermaid/issues/269#issuecomment-373229136)
|
||||
|
@@ -25,7 +25,7 @@ import {
|
||||
import rough from 'roughjs';
|
||||
import createLabel from './createLabel.js';
|
||||
import { addEdgeMarkers } from './edgeMarker.ts';
|
||||
import { isLabelStyle, styles2String } from './shapes/handDrawnShapeStyles.js';
|
||||
import { isLabelStyle } from './shapes/handDrawnShapeStyles.js';
|
||||
|
||||
const edgeLabels = new Map();
|
||||
const terminalLabels = new Map();
|
||||
@@ -43,10 +43,8 @@ export const getLabelStyles = (styleArray) => {
|
||||
export const insertEdgeLabel = async (elem, edge) => {
|
||||
let useHtmlLabels = evaluate(getConfig().flowchart.htmlLabels);
|
||||
|
||||
const { labelStyles } = styles2String(edge);
|
||||
edge.labelStyle = labelStyles;
|
||||
const labelElement = await createText(elem, edge.label, {
|
||||
style: edge.labelStyle,
|
||||
style: getLabelStyles(edge.labelStyle),
|
||||
useHtmlLabels,
|
||||
addSvgBackground: true,
|
||||
isNode: false,
|
||||
|
@@ -20,11 +20,7 @@ export const compileStyles = (node: Node) => {
|
||||
// the array is the styles of node from the classes it is using
|
||||
// node.cssStyles is an array of styles directly set on the node
|
||||
// concat the arrays and remove duplicates such that the values from node.cssStyles are used if there are duplicates
|
||||
const stylesMap = styles2Map([
|
||||
...(node.cssCompiledStyles || []),
|
||||
...(node.cssStyles || []),
|
||||
...(node.labelStyle || []),
|
||||
]);
|
||||
const stylesMap = styles2Map([...(node.cssCompiledStyles || []), ...(node.cssStyles || [])]);
|
||||
return { stylesMap, stylesArray: [...stylesMap] };
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user