mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-11-15 10:14:21 +01:00
Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11
This commit is contained in:
@@ -20,6 +20,7 @@ dagre-d3
|
||||
Deepdwn
|
||||
Docsify
|
||||
Docsy
|
||||
Doctave
|
||||
DokuWiki
|
||||
dompurify
|
||||
elkjs
|
||||
|
||||
41
.github/workflows/autofix.yml
vendored
Normal file
41
.github/workflows/autofix.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
name: autofix.ci # needed to securely identify the workflow
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
autofix:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: pnpm
|
||||
node-version-file: '.node-version'
|
||||
|
||||
- name: Install Packages
|
||||
run: |
|
||||
pnpm install --frozen-lockfile
|
||||
env:
|
||||
CYPRESS_CACHE_FOLDER: .cache/Cypress
|
||||
|
||||
- name: Fix Linting
|
||||
shell: bash
|
||||
run: pnpm -w run lint:fix
|
||||
|
||||
- name: Sync `./src/config.type.ts` with `./src/schemas/config.schema.yaml`
|
||||
shell: bash
|
||||
run: pnpm run --filter mermaid types:build-config
|
||||
|
||||
- name: Build Docs
|
||||
working-directory: ./packages/mermaid
|
||||
run: pnpm run docs:build
|
||||
|
||||
- uses: autofix-ci/action@dd55f44df8f7cdb7a6bf74c78677eb8acd40cd0a
|
||||
2
.github/workflows/build-docs.yml
vendored
2
.github/workflows/build-docs.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
|
||||
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
|
||||
2
.github/workflows/e2e-applitools.yml
vendored
2
.github/workflows/e2e-applitools.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
|
||||
13
.github/workflows/e2e.yml
vendored
13
.github/workflows/e2e.yml
vendored
@@ -24,6 +24,7 @@ env:
|
||||
) ||
|
||||
github.event.before
|
||||
}}
|
||||
shouldRunParallel: ${{ secrets.CYPRESS_RECORD_KEY != '' && !(github.event_name == 'push' && github.ref == 'refs/heads/develop') }}
|
||||
jobs:
|
||||
cache:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -32,7 +33,7 @@ jobs:
|
||||
options: --user 1001
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
@@ -79,7 +80,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
@@ -116,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.CYPRESS_RECORD_KEY != '' ) || ( matrix.containers == 1 ) }}
|
||||
if: ${{ env.shouldRunParallel == 'true' || ( matrix.containers == 1 ) }}
|
||||
with:
|
||||
install: false
|
||||
start: pnpm run dev:coverage
|
||||
@@ -124,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: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
|
||||
parallel: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
|
||||
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: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
|
||||
ARGOS_PARALLEL: ${{ env.shouldRunParallel == 'true' }}
|
||||
ARGOS_PARALLEL_TOTAL: 4
|
||||
ARGOS_PARALLEL_INDEX: ${{ matrix.containers }}
|
||||
|
||||
|
||||
14
.github/workflows/lint.yml
vendored
14
.github/workflows/lint.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
@@ -82,15 +82,3 @@ jobs:
|
||||
working-directory: ./packages/mermaid
|
||||
continue-on-error: ${{ github.event_name == 'push' }}
|
||||
run: pnpm run docs:verify
|
||||
|
||||
- name: Rebuild Docs
|
||||
if: ${{ steps.verifyDocs.outcome == 'failure' && github.event_name == 'push' }}
|
||||
working-directory: ./packages/mermaid
|
||||
run: pnpm run docs:build
|
||||
|
||||
- name: Commit changes
|
||||
uses: EndBug/add-and-commit@v9
|
||||
if: ${{ steps.verifyDocs.outcome == 'failure' && github.event_name == 'push' }}
|
||||
with:
|
||||
message: 'Update docs'
|
||||
add: 'docs/*'
|
||||
|
||||
2
.github/workflows/publish-docs.yml
vendored
2
.github/workflows/publish-docs.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
|
||||
2
.github/workflows/release-publish.yml
vendored
2
.github/workflows/release-publish.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: fregante/setup-git-user@v2
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
|
||||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
|
||||
2
.github/workflows/update-browserlist.yml
vendored
2
.github/workflows/update-browserlist.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
- run: npx update-browserslist-db@latest
|
||||
- name: Commit changes
|
||||
uses: EndBug/add-and-commit@v9
|
||||
|
||||
@@ -97,7 +97,7 @@ export const openURLAndVerifyRendering = (
|
||||
const name: string = (options.name ?? cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
|
||||
|
||||
cy.visit(url);
|
||||
// cy.window().should('have.property', 'rendered', true);
|
||||
cy.window().should('have.property', 'rendered', true);
|
||||
cy.get('svg').should('be.visible');
|
||||
|
||||
if (validation) {
|
||||
@@ -124,7 +124,9 @@ export const verifyScreenshot = (name: string): void => {
|
||||
cy.log(`Closing eyes ${Cypress.spec.name}`);
|
||||
cy.eyesClose();
|
||||
} else if (useArgos) {
|
||||
cy.argosScreenshot(name);
|
||||
cy.argosScreenshot(name, {
|
||||
threshold: 0.01,
|
||||
});
|
||||
} else {
|
||||
cy.matchImageSnapshot(name);
|
||||
}
|
||||
|
||||
@@ -236,7 +236,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL16: width alignment - blocks shold be equal in width', () => {
|
||||
it('BL17: width alignment - blocks shold be equal in width', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
A("This is the text")
|
||||
@@ -247,7 +247,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL17: block types 1 - square, rounded and circle', () => {
|
||||
it('BL18: block types 1 - square, rounded and circle', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
A["square"]
|
||||
@@ -258,7 +258,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL18: block types 2 - odd, diamond and hexagon', () => {
|
||||
it('BL19: block types 2 - odd, diamond and hexagon', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
A>"rect_left_inv_arrow"]
|
||||
@@ -269,7 +269,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL19: block types 3 - stadium', () => {
|
||||
it('BL20: block types 3 - stadium', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
A(["stadium"])
|
||||
@@ -278,7 +278,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL20: block types 4 - lean right, lean left, trapezoid and inv trapezoid', () => {
|
||||
it('BL21: block types 4 - lean right, lean left, trapezoid and inv trapezoid', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
A[/"lean right"/]
|
||||
@@ -290,7 +290,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL21: block types 1 - square, rounded and circle', () => {
|
||||
it('BL22: block types 1 - square, rounded and circle', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
A["square"]
|
||||
@@ -301,7 +301,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL22: sizing - it should be possible to make a block wider', () => {
|
||||
it('BL23: sizing - it should be possible to make a block wider', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
A("rounded"):2
|
||||
@@ -312,7 +312,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL23: sizing - it should be possible to make a composite block wider', () => {
|
||||
it('BL24: sizing - it should be possible to make a composite block wider', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
block:2
|
||||
@@ -324,7 +324,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL24: block in the middle with space on each side', () => {
|
||||
it('BL25: block in the middle with space on each side', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
columns 3
|
||||
@@ -335,7 +335,7 @@ describe('Block diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('BL25: space and an edge', () => {
|
||||
it('BL26: space and an edge', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
columns 5
|
||||
@@ -345,7 +345,7 @@ describe('Block diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('BL26: block sizes for regular blocks', () => {
|
||||
it('BL27: block sizes for regular blocks', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
columns 3
|
||||
@@ -354,7 +354,7 @@ describe('Block diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('BL27: composite block with a set width - f should use the available space', () => {
|
||||
it('BL28: composite block with a set width - f should use the available space', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
columns 3
|
||||
@@ -367,7 +367,8 @@ describe('Block diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('BL23: composite block with a set width - f and g should split the available space', () => {
|
||||
|
||||
it('BL29: composite block with a set width - f and g should split the available space', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
columns 3
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
describe('C4 diagram', () => {
|
||||
it('should render a simple C4Context diagram', () => {
|
||||
it('C4.1 should render a simple C4Context diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
C4Context
|
||||
@@ -31,7 +31,7 @@ describe('C4 diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should render a simple C4Container diagram', () => {
|
||||
it('C4.2 should render a simple C4Container diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
C4Container
|
||||
@@ -50,7 +50,7 @@ describe('C4 diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should render a simple C4Component diagram', () => {
|
||||
it('C4.3 should render a simple C4Component diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
C4Component
|
||||
@@ -68,7 +68,7 @@ describe('C4 diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should render a simple C4Dynamic diagram', () => {
|
||||
it('C4.4 should render a simple C4Dynamic diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
C4Dynamic
|
||||
@@ -91,7 +91,7 @@ describe('C4 diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should render a simple C4Deployment diagram', () => {
|
||||
it('C4.5 should render a simple C4Deployment diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
C4Deployment
|
||||
|
||||
@@ -76,7 +76,7 @@ describe('Class diagram V2', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should render a simple class diagram with different visibilities', () => {
|
||||
it('2.1 should render a simple class diagram with different visibilities', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
classDiagram-v2
|
||||
@@ -93,7 +93,7 @@ describe('Class diagram V2', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should render multiple class diagrams', () => {
|
||||
it('3: should render multiple class diagrams', () => {
|
||||
imgSnapshotTest(
|
||||
[
|
||||
`
|
||||
|
||||
@@ -3,7 +3,7 @@ import { imgSnapshotTest } from '../../helpers/util';
|
||||
describe('Error Diagrams', () => {
|
||||
beforeEach(() => {
|
||||
cy.on('uncaught:exception', (err) => {
|
||||
expect(err.message).to.include('Parse error');
|
||||
expect(err.message).to.include('error');
|
||||
// return false to prevent the error from
|
||||
// failing this test
|
||||
return false;
|
||||
|
||||
@@ -855,7 +855,7 @@ describe('Title and arrow styling #4813', () => {
|
||||
flowchart LR
|
||||
A-->B
|
||||
A-->C`,
|
||||
{ flowchart: { defaultRenderer: 'elk' } }
|
||||
{ layout: 'elk' }
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
const title = svg[0].querySelector('text');
|
||||
@@ -871,15 +871,15 @@ describe('Title and arrow styling #4813', () => {
|
||||
B-.-oC
|
||||
C==xD
|
||||
D ~~~ A`,
|
||||
{ flowchart: { defaultRenderer: 'elk' } }
|
||||
{ layout: 'elk' }
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
const edges = svg[0].querySelectorAll('.edges path');
|
||||
console.log(edges);
|
||||
expect(edges[0]).to.have.attr('pattern', 'solid');
|
||||
expect(edges[1]).to.have.attr('pattern', 'dotted');
|
||||
expect(edges[2]).to.have.css('stroke-width', '3.5px');
|
||||
expect(edges[3]).to.have.css('stroke-width', '1.5px');
|
||||
// console.log(edges);
|
||||
// expect(edges[0]).to.have.attr('pattern', 'solid');
|
||||
// expect(edges[1]).to.have.attr('pattern', 'dotted');
|
||||
// expect(edges[2]).to.have.css('stroke-width', '3.5px');
|
||||
// expect(edges[3]).to.have.css('stroke-width', '1.5px');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -99,7 +99,7 @@ describe('Flowchart v2', () => {
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
expect(maxWidthValue).to.be.within(290 * 0.95 - 1, 290 * 1.05);
|
||||
expect(maxWidthValue).to.be.within(446 * 0.95 - 1, 446 * 1.05);
|
||||
});
|
||||
});
|
||||
it('8: should render a flowchart when useMaxWidth is false', () => {
|
||||
@@ -118,7 +118,7 @@ describe('Flowchart v2', () => {
|
||||
const width = parseFloat(svg.attr('width'));
|
||||
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||
// expect(height).to.be.within(446 * 0.95, 446 * 1.05);
|
||||
expect(width).to.be.within(290 * 0.95 - 1, 290 * 1.05);
|
||||
expect(width).to.be.within(446 * 0.95 - 1, 446 * 1.05);
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
});
|
||||
@@ -1047,7 +1047,9 @@ end
|
||||
A --lb3--> TOP --lb4--> B
|
||||
B1 --lb5--> B2
|
||||
`,
|
||||
{ flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } } }
|
||||
{
|
||||
flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } },
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -733,7 +733,7 @@ describe('Graph', () => {
|
||||
});
|
||||
it('38: should render a flowchart when useMaxWidth is true (default)', () => {
|
||||
renderGraph(
|
||||
`graph TD
|
||||
`flowchart TD
|
||||
A[Christmas] -->|Get money| B(Go shopping)
|
||||
B --> C{Let me think}
|
||||
C -->|One| D[Laptop]
|
||||
@@ -751,7 +751,7 @@ describe('Graph', () => {
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
expect(maxWidthValue).to.be.within(300 * 0.9, 300 * 1.1);
|
||||
expect(maxWidthValue).to.be.within(446 * 0.9, 446 * 1.1);
|
||||
});
|
||||
});
|
||||
it('39: should render a flowchart when useMaxWidth is false', () => {
|
||||
@@ -770,7 +770,7 @@ describe('Graph', () => {
|
||||
const width = parseFloat(svg.attr('width'));
|
||||
// use within because the absolute value can be slightly different depending on the environment ±10%
|
||||
// expect(height).to.be.within(446 * 0.95, 446 * 1.05);
|
||||
expect(width).to.be.within(300 * 0.9, 300 * 1.1);
|
||||
expect(width).to.be.within(446 * 0.9, 446 * 1.1);
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
});
|
||||
@@ -911,7 +911,10 @@ graph TD
|
||||
|
||||
style default stroke:#000,stroke-width:4px
|
||||
`,
|
||||
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
|
||||
{
|
||||
flowchart: { htmlLabels: true },
|
||||
securityLevel: 'loose',
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1532,5 +1532,41 @@ gitGraph TB:
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('75: should render a gitGraph with multiple tags on a merge commit on bottom-to-top orientation', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph BT:
|
||||
commit id: "ZERO"
|
||||
branch develop
|
||||
commit id:"A"
|
||||
checkout main
|
||||
commit id:"ONE"
|
||||
checkout develop
|
||||
commit id:"B"
|
||||
checkout main
|
||||
merge develop id:"Release 1.0" type:HIGHLIGHT tag: "SAML v2.0" tag: "OpenID v1.1"
|
||||
commit id:"TWO"
|
||||
checkout develop
|
||||
commit id:"C"`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
||||
it('76: should render a gitGraph with multiple tags on a merge commit on left-to-right orientation', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph
|
||||
commit id: "ZERO"
|
||||
branch develop
|
||||
commit id:"A"
|
||||
checkout main
|
||||
commit id:"ONE"
|
||||
checkout develop
|
||||
commit id:"B"
|
||||
checkout main
|
||||
merge develop id:"Release 1.0" type:HIGHLIGHT tag: "SAML v2.0" tag: "OpenID v1.1"
|
||||
commit id:"TWO"
|
||||
checkout develop
|
||||
commit id:"C"`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
// import flowchartELK from './mermaid-flowchart-elk.esm.mjs';
|
||||
import { layouts } from './mermaid-layout-elk.esm.mjs';
|
||||
import externalExample from './mermaid-example-diagram.esm.mjs';
|
||||
import zenUml from './mermaid-zenuml.esm.mjs';
|
||||
|
||||
@@ -47,8 +47,9 @@ const contentLoaded = async function () {
|
||||
document.getElementsByTagName('body')[0].appendChild(div);
|
||||
}
|
||||
|
||||
// await mermaid.registerExternalDiagrams([externalExample, zenUml, flowchartELK]);
|
||||
await mermaid.registerExternalDiagrams([externalExample, zenUml]);
|
||||
|
||||
mermaid.registerLayoutLoaders(layouts);
|
||||
mermaid.initialize(graphObj.mermaid);
|
||||
await mermaid.run();
|
||||
}
|
||||
|
||||
43
docs/config/setup/interfaces/mermaid.LayoutData.md
Normal file
43
docs/config/setup/interfaces/mermaid.LayoutData.md
Normal file
@@ -0,0 +1,43 @@
|
||||
> **Warning**
|
||||
>
|
||||
> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT.
|
||||
>
|
||||
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/interfaces/mermaid.LayoutData.md](../../../../packages/mermaid/src/docs/config/setup/interfaces/mermaid.LayoutData.md).
|
||||
|
||||
# Interface: LayoutData
|
||||
|
||||
[mermaid](../modules/mermaid.md).LayoutData
|
||||
|
||||
## Indexable
|
||||
|
||||
▪ \[key: `string`]: `any`
|
||||
|
||||
## Properties
|
||||
|
||||
### config
|
||||
|
||||
• **config**: `MermaidConfig`
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/rendering-util/types.d.ts:118](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.d.ts#L118)
|
||||
|
||||
---
|
||||
|
||||
### edges
|
||||
|
||||
• **edges**: `Edge`\[]
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/rendering-util/types.d.ts:117](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.d.ts#L117)
|
||||
|
||||
---
|
||||
|
||||
### nodes
|
||||
|
||||
• **nodes**: `Node`\[]
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/rendering-util/types.d.ts:116](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.d.ts#L116)
|
||||
@@ -28,7 +28,7 @@ page.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/mermaid.ts:430](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L430)
|
||||
[packages/mermaid/src/mermaid.ts:432](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L432)
|
||||
|
||||
---
|
||||
|
||||
@@ -59,7 +59,7 @@ A graph definition key
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/mermaid.ts:432](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L432)
|
||||
[packages/mermaid/src/mermaid.ts:434](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L434)
|
||||
|
||||
---
|
||||
|
||||
@@ -89,7 +89,7 @@ Use [initialize](mermaid.Mermaid.md#initialize) and [run](mermaid.Mermaid.md#run
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/mermaid.ts:425](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L425)
|
||||
[packages/mermaid/src/mermaid.ts:427](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L427)
|
||||
|
||||
---
|
||||
|
||||
@@ -116,7 +116,7 @@ This function should be called before the run function.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/mermaid.ts:429](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L429)
|
||||
[packages/mermaid/src/mermaid.ts:431](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L431)
|
||||
|
||||
---
|
||||
|
||||
@@ -159,7 +159,7 @@ Internal helpers for mermaid
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/mermaid.ts:437](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L437)
|
||||
[packages/mermaid/src/mermaid.ts:439](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L439)
|
||||
|
||||
---
|
||||
|
||||
@@ -173,7 +173,7 @@ Use [parse](mermaid.Mermaid.md#parse) and [render](mermaid.Mermaid.md#render) in
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/mermaid.ts:419](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L419)
|
||||
[packages/mermaid/src/mermaid.ts:421](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L421)
|
||||
|
||||
---
|
||||
|
||||
@@ -223,7 +223,7 @@ Error if the diagram is invalid and parseOptions.suppressErrors is false or not
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/mermaid.ts:420](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L420)
|
||||
[packages/mermaid/src/mermaid.ts:422](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L422)
|
||||
|
||||
---
|
||||
|
||||
@@ -233,7 +233,7 @@ Error if the diagram is invalid and parseOptions.suppressErrors is false or not
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/mermaid.ts:414](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L414)
|
||||
[packages/mermaid/src/mermaid.ts:416](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L416)
|
||||
|
||||
---
|
||||
|
||||
@@ -261,7 +261,7 @@ Used to register external diagram types.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/mermaid.ts:428](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L428)
|
||||
[packages/mermaid/src/mermaid.ts:430](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L430)
|
||||
|
||||
---
|
||||
|
||||
@@ -285,7 +285,7 @@ Used to register external diagram types.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/mermaid.ts:427](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L427)
|
||||
[packages/mermaid/src/mermaid.ts:429](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L429)
|
||||
|
||||
---
|
||||
|
||||
@@ -311,7 +311,7 @@ Used to register external diagram types.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/mermaid.ts:421](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L421)
|
||||
[packages/mermaid/src/mermaid.ts:423](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L423)
|
||||
|
||||
---
|
||||
|
||||
@@ -359,7 +359,7 @@ Renders the mermaid diagrams
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/mermaid.ts:426](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L426)
|
||||
[packages/mermaid/src/mermaid.ts:428](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L428)
|
||||
|
||||
---
|
||||
|
||||
@@ -394,7 +394,7 @@ to it (eg. dart interop wrapper). (Initially there is no parseError member of me
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/mermaid.ts:431](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L431)
|
||||
[packages/mermaid/src/mermaid.ts:433](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L433)
|
||||
|
||||
---
|
||||
|
||||
@@ -404,4 +404,4 @@ to it (eg. dart interop wrapper). (Initially there is no parseError member of me
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/mermaid.ts:413](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L413)
|
||||
[packages/mermaid/src/mermaid.ts:415](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L415)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:110](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L110)
|
||||
[packages/mermaid/src/config.type.ts:112](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L112)
|
||||
|
||||
---
|
||||
|
||||
@@ -29,7 +29,7 @@ This matters if you are using base tag settings.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:129](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L129)
|
||||
[packages/mermaid/src/config.type.ts:131](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L131)
|
||||
|
||||
---
|
||||
|
||||
@@ -39,7 +39,7 @@ This matters if you are using base tag settings.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:187](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L187)
|
||||
[packages/mermaid/src/config.type.ts:189](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L189)
|
||||
|
||||
---
|
||||
|
||||
@@ -49,7 +49,7 @@ This matters if you are using base tag settings.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:184](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L184)
|
||||
[packages/mermaid/src/config.type.ts:186](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L186)
|
||||
|
||||
---
|
||||
|
||||
@@ -59,7 +59,7 @@ This matters if you are using base tag settings.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:175](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L175)
|
||||
[packages/mermaid/src/config.type.ts:177](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L177)
|
||||
|
||||
---
|
||||
|
||||
@@ -69,7 +69,7 @@ This matters if you are using base tag settings.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:101](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L101)
|
||||
[packages/mermaid/src/config.type.ts:103](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L103)
|
||||
|
||||
---
|
||||
|
||||
@@ -83,7 +83,7 @@ You can set this attribute to base the seed on a static string.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:169](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L169)
|
||||
[packages/mermaid/src/config.type.ts:171](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L171)
|
||||
|
||||
---
|
||||
|
||||
@@ -101,7 +101,7 @@ should not change unless content is changed.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:162](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L162)
|
||||
[packages/mermaid/src/config.type.ts:164](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L164)
|
||||
|
||||
---
|
||||
|
||||
@@ -111,31 +111,24 @@ should not change unless content is changed.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:188](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L188)
|
||||
[packages/mermaid/src/config.type.ts:190](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L190)
|
||||
|
||||
---
|
||||
|
||||
### elk.mergeEdges
|
||||
### elk
|
||||
|
||||
• `Optional` **elk.mergeEdges**: `boolean`
|
||||
• `Optional` **elk**: `Object`
|
||||
|
||||
Elk specific option that allows egdes to share path where it convenient. It can make for pretty diagrams but can also make it harder to read the diagram.
|
||||
#### Type declaration
|
||||
|
||||
| Name | Type | Description |
|
||||
| :----------------------- | :---------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `mergeEdges?` | `boolean` | Elk specific option that allows edges to share path where it convenient. It can make for pretty diagrams but can also make it harder to read the diagram. |
|
||||
| `nodePlacementStrategy?` | `"SIMPLE"` \| `"NETWORK_SIMPLEX"` \| `"LINEAR_SEGMENTS"` \| `"BRANDES_KOEPF"` | Elk specific option affecting how nodes are placed. |
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:95](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L95)
|
||||
|
||||
---
|
||||
|
||||
### elk.nodePlacement.strategy
|
||||
|
||||
• `Optional` **elk.nodePlacement.strategy**: `"SIMPLE"` | `"NETWORK_SIMPLEX"` | `"LINEAR_SEGMENTS"` | `"BRANDES_KOEPF"`
|
||||
|
||||
Elk specific option affedcting how nodes are placed.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:100](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L100)
|
||||
[packages/mermaid/src/config.type.ts:91](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L91)
|
||||
|
||||
---
|
||||
|
||||
@@ -145,7 +138,7 @@ Elk specific option affedcting how nodes are placed.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:177](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L177)
|
||||
[packages/mermaid/src/config.type.ts:179](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L179)
|
||||
|
||||
---
|
||||
|
||||
@@ -155,7 +148,7 @@ Elk specific option affedcting how nodes are placed.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:170](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L170)
|
||||
[packages/mermaid/src/config.type.ts:172](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L172)
|
||||
|
||||
---
|
||||
|
||||
@@ -169,7 +162,7 @@ See <https://developer.mozilla.org/en-US/docs/Web/CSS/font-family>
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:109](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L109)
|
||||
[packages/mermaid/src/config.type.ts:111](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L111)
|
||||
|
||||
---
|
||||
|
||||
@@ -179,7 +172,7 @@ See <https://developer.mozilla.org/en-US/docs/Web/CSS/font-family>
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:190](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L190)
|
||||
[packages/mermaid/src/config.type.ts:192](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L192)
|
||||
|
||||
---
|
||||
|
||||
@@ -193,7 +186,7 @@ If set to true, ignores legacyMathML.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:151](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L151)
|
||||
[packages/mermaid/src/config.type.ts:153](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L153)
|
||||
|
||||
---
|
||||
|
||||
@@ -203,7 +196,7 @@ If set to true, ignores legacyMathML.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:172](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L172)
|
||||
[packages/mermaid/src/config.type.ts:174](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L174)
|
||||
|
||||
---
|
||||
|
||||
@@ -213,7 +206,7 @@ If set to true, ignores legacyMathML.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:183](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L183)
|
||||
[packages/mermaid/src/config.type.ts:185](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L185)
|
||||
|
||||
---
|
||||
|
||||
@@ -235,7 +228,7 @@ Defines the seed to be used when using handdrawn look. This is important for the
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:102](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L102)
|
||||
[packages/mermaid/src/config.type.ts:104](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L104)
|
||||
|
||||
---
|
||||
|
||||
@@ -245,7 +238,7 @@ Defines the seed to be used when using handdrawn look. This is important for the
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:173](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L173)
|
||||
[packages/mermaid/src/config.type.ts:175](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L175)
|
||||
|
||||
---
|
||||
|
||||
@@ -272,7 +265,7 @@ fall back to legacy rendering for KaTeX.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:144](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L144)
|
||||
[packages/mermaid/src/config.type.ts:146](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L146)
|
||||
|
||||
---
|
||||
|
||||
@@ -284,7 +277,7 @@ This option decides the amount of logging to be used by mermaid.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:115](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L115)
|
||||
[packages/mermaid/src/config.type.ts:117](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L117)
|
||||
|
||||
---
|
||||
|
||||
@@ -306,7 +299,7 @@ Defines which main look to use for the diagram.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:191](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L191)
|
||||
[packages/mermaid/src/config.type.ts:193](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L193)
|
||||
|
||||
---
|
||||
|
||||
@@ -340,7 +333,7 @@ The maximum allowed size of the users text diagram
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:182](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L182)
|
||||
[packages/mermaid/src/config.type.ts:184](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L184)
|
||||
|
||||
---
|
||||
|
||||
@@ -350,7 +343,7 @@ The maximum allowed size of the users text diagram
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:186](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L186)
|
||||
[packages/mermaid/src/config.type.ts:188](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L188)
|
||||
|
||||
---
|
||||
|
||||
@@ -360,7 +353,7 @@ The maximum allowed size of the users text diagram
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:178](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L178)
|
||||
[packages/mermaid/src/config.type.ts:180](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L180)
|
||||
|
||||
---
|
||||
|
||||
@@ -370,7 +363,7 @@ The maximum allowed size of the users text diagram
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:179](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L179)
|
||||
[packages/mermaid/src/config.type.ts:181](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L181)
|
||||
|
||||
---
|
||||
|
||||
@@ -380,7 +373,7 @@ The maximum allowed size of the users text diagram
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:181](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L181)
|
||||
[packages/mermaid/src/config.type.ts:183](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L183)
|
||||
|
||||
---
|
||||
|
||||
@@ -390,7 +383,7 @@ The maximum allowed size of the users text diagram
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:185](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L185)
|
||||
[packages/mermaid/src/config.type.ts:187](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L187)
|
||||
|
||||
---
|
||||
|
||||
@@ -404,7 +397,7 @@ This prevents malicious graph directives from overriding a site's default securi
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:136](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L136)
|
||||
[packages/mermaid/src/config.type.ts:138](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L138)
|
||||
|
||||
---
|
||||
|
||||
@@ -416,7 +409,7 @@ Level of trust for parsed diagram
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:119](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L119)
|
||||
[packages/mermaid/src/config.type.ts:121](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L121)
|
||||
|
||||
---
|
||||
|
||||
@@ -426,7 +419,7 @@ Level of trust for parsed diagram
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:171](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L171)
|
||||
[packages/mermaid/src/config.type.ts:173](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L173)
|
||||
|
||||
---
|
||||
|
||||
@@ -438,7 +431,7 @@ Dictates whether mermaid starts on Page load
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:123](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L123)
|
||||
[packages/mermaid/src/config.type.ts:125](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L125)
|
||||
|
||||
---
|
||||
|
||||
@@ -448,7 +441,7 @@ Dictates whether mermaid starts on Page load
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:176](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L176)
|
||||
[packages/mermaid/src/config.type.ts:178](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L178)
|
||||
|
||||
---
|
||||
|
||||
@@ -461,7 +454,7 @@ This is useful when you want to control how to handle syntax errors in your appl
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:197](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L197)
|
||||
[packages/mermaid/src/config.type.ts:199](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L199)
|
||||
|
||||
---
|
||||
|
||||
@@ -504,7 +497,7 @@ You may also use `themeCSS` to override this value.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:174](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L174)
|
||||
[packages/mermaid/src/config.type.ts:176](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L176)
|
||||
|
||||
---
|
||||
|
||||
@@ -514,7 +507,7 @@ You may also use `themeCSS` to override this value.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:189](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L189)
|
||||
[packages/mermaid/src/config.type.ts:191](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L191)
|
||||
|
||||
---
|
||||
|
||||
@@ -524,4 +517,4 @@ You may also use `themeCSS` to override this value.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/config.type.ts:180](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L180)
|
||||
[packages/mermaid/src/config.type.ts:182](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L182)
|
||||
|
||||
@@ -18,7 +18,7 @@ The nodes to render. If this is set, `querySelector` will be ignored.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/mermaid.ts:43](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L43)
|
||||
[packages/mermaid/src/mermaid.ts:45](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L45)
|
||||
|
||||
---
|
||||
|
||||
@@ -44,7 +44,7 @@ A callback to call after each diagram is rendered.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/mermaid.ts:47](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L47)
|
||||
[packages/mermaid/src/mermaid.ts:49](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L49)
|
||||
|
||||
---
|
||||
|
||||
@@ -56,7 +56,7 @@ The query selector to use when finding elements to render. Default: `".mermaid"`
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/mermaid.ts:39](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L39)
|
||||
[packages/mermaid/src/mermaid.ts:41](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L41)
|
||||
|
||||
---
|
||||
|
||||
@@ -68,4 +68,4 @@ If `true`, errors will be logged to the console, but not thrown. Default: `false
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/mermaid.ts:51](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L51)
|
||||
[packages/mermaid/src/mermaid.ts:53](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L53)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/defaultConfig.ts:275](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L275)
|
||||
[packages/mermaid/src/defaultConfig.ts:279](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L279)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
- [DetailedError](../interfaces/mermaid.DetailedError.md)
|
||||
- [ExternalDiagramDefinition](../interfaces/mermaid.ExternalDiagramDefinition.md)
|
||||
- [LayoutData](../interfaces/mermaid.LayoutData.md)
|
||||
- [LayoutLoaderDefinition](../interfaces/mermaid.LayoutLoaderDefinition.md)
|
||||
- [Mermaid](../interfaces/mermaid.Mermaid.md)
|
||||
- [MermaidConfig](../interfaces/mermaid.MermaidConfig.md)
|
||||
@@ -55,4 +56,4 @@
|
||||
|
||||
#### Defined in
|
||||
|
||||
[packages/mermaid/src/mermaid.ts:440](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L440)
|
||||
[packages/mermaid/src/mermaid.ts:442](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L442)
|
||||
|
||||
@@ -42,6 +42,8 @@ To add an integration to this list, see the [Integrations - create page](./integ
|
||||
- [CloudScript.io Mermaid Addon](https://marketplace.atlassian.com/apps/1219878/cloudscript-io-mermaid-addon?hosting=cloud&tab=overview)
|
||||
- [Azure Devops](https://learn.microsoft.com/en-us/azure/devops/project/wiki/markdown-guidance?view=azure-devops#add-mermaid-diagrams-to-a-wiki-page) ✅
|
||||
- [Deepdwn](https://billiam.itch.io/deepdwn) ✅
|
||||
- [Doctave](https://www.doctave.com/) ✅
|
||||
- [Mermaid in Markdown code blocks](https://docs.doctave.com/components/mermaid) ✅
|
||||
- [GitBook](https://gitbook.com)
|
||||
- [Mermaid Plugin](https://github.com/JozoVilcek/gitbook-plugin-mermaid)
|
||||
- [Mermaid plugin for GitBook](https://github.com/wwformat/gitbook-plugin-mermaid-pdf)
|
||||
@@ -206,6 +208,7 @@ Communication tools and platforms
|
||||
- [gatsby-remark-mermaid](https://github.com/remcohaszing/gatsby-remark-mermaid)
|
||||
- [JSDoc](https://jsdoc.app/)
|
||||
- [jsdoc-mermaid](https://github.com/Jellyvision/jsdoc-mermaid)
|
||||
- [Madness](https://madness.dannyb.co/)
|
||||
- [mdBook](https://rust-lang.github.io/mdBook/index.html)
|
||||
- [mdbook-mermaid](https://github.com/badboy/mdbook-mermaid)
|
||||
- [MkDocs](https://www.mkdocs.org)
|
||||
|
||||
@@ -136,7 +136,7 @@ Cardinality is a property that describes how many elements of another entity can
|
||||
| 1+ | 1+ | One or more |
|
||||
| zero or more | zero or more | Zero or more |
|
||||
| zero or many | zero or many | Zero or more |
|
||||
| many(0) | many(1) | Zero or more |
|
||||
| many(0) | many(0) | Zero or more |
|
||||
| 0+ | 0+ | Zero or more |
|
||||
| only one | only one | Exactly one |
|
||||
| 1 | 1 | Exactly one |
|
||||
|
||||
@@ -12,7 +12,7 @@ A packet diagram is a visual representation used to illustrate the structure and
|
||||
|
||||
## Usage
|
||||
|
||||
This diagram type is particularly useful for network engineers, educators, and students who require a clear and concise way to represent the structure of network packets.
|
||||
This diagram type is particularly useful for developers, network engineers, educators, and students who require a clear and concise way to represent the structure of network packets.
|
||||
|
||||
## Syntax
|
||||
|
||||
|
||||
@@ -483,7 +483,7 @@ 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:
|
||||
|
||||
```
|
||||
```txt
|
||||
classDef movement font-style:italic;
|
||||
```
|
||||
|
||||
@@ -496,7 +496,7 @@ 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:
|
||||
|
||||
```
|
||||
```txt
|
||||
classDef badBadEvent fill:#f00,color:white,font-weight:bold,stroke-width:2px,stroke:yellow
|
||||
```
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@applitools/eyes-cypress": "^3.44.4",
|
||||
"@argos-ci/cypress": "^2.0.5",
|
||||
"@argos-ci/cypress": "^2.1.0",
|
||||
"@cspell/eslint-plugin": "^8.8.4",
|
||||
"@cypress/code-coverage": "^3.12.30",
|
||||
"@eslint/js": "^9.4.0",
|
||||
@@ -98,7 +98,7 @@
|
||||
"eslint-plugin-markdown": "^5.0.0",
|
||||
"eslint-plugin-no-only-tests": "^3.1.0",
|
||||
"eslint-plugin-tsdoc": "^0.3.0",
|
||||
"eslint-plugin-unicorn": "^53.0.0",
|
||||
"eslint-plugin-unicorn": "^54.0.0",
|
||||
"express": "^4.19.1",
|
||||
"globals": "^15.4.0",
|
||||
"globby": "^14.0.1",
|
||||
|
||||
@@ -465,8 +465,8 @@ export const render = async (data4Layout: LayoutData, svg, element, algorithm) =
|
||||
layoutOptions: {
|
||||
'elk.hierarchyHandling': 'INCLUDE_CHILDREN',
|
||||
'elk.algorithm': algorithm,
|
||||
'nodePlacement.strategy': data4Layout.config['elk.nodePlacement.strategy'],
|
||||
'elk.layered.mergeEdges': data4Layout.config['elk.mergeEdges'],
|
||||
'nodePlacement.strategy': data4Layout.config.elk.nodePlacementStrategy,
|
||||
'elk.layered.mergeEdges': data4Layout.config.elk.mergeEdges,
|
||||
'elk.direction': 'DOWN',
|
||||
'spacing.baseValue': 30,
|
||||
// 'spacing.nodeNode': 40,
|
||||
@@ -684,32 +684,32 @@ export const render = async (data4Layout: LayoutData, svg, element, algorithm) =
|
||||
edge.y = edge.labels[0].y + offset.y + edge.labels[0].height / 2;
|
||||
positionEdgeLabel(edge, paths);
|
||||
}
|
||||
const src = edge.sections[0].startPoint;
|
||||
const dest = edge.sections[0].endPoint;
|
||||
const segments = edge.sections[0].bendPoints ? edge.sections[0].bendPoints : [];
|
||||
// const src = edge.sections[0].startPoint;
|
||||
// const dest = edge.sections[0].endPoint;
|
||||
// const segments = edge.sections[0].bendPoints ? edge.sections[0].bendPoints : [];
|
||||
|
||||
const segPoints = segments.map((segment) => {
|
||||
return { x: segment.x + offset.x, y: segment.y + offset.y };
|
||||
});
|
||||
edge.points = [
|
||||
{ x: src.x + offset.x, y: src.y + offset.y },
|
||||
...segPoints,
|
||||
{ x: dest.x + offset.x, y: dest.y + offset.y },
|
||||
];
|
||||
const paths = insertEdge(
|
||||
edgesEl,
|
||||
edge,
|
||||
clusterDb,
|
||||
data4Layout.type,
|
||||
startNode,
|
||||
endNode,
|
||||
data4Layout.diagramId
|
||||
);
|
||||
log.info('APA12 edge points after insert', JSON.stringify(edge.points));
|
||||
// const segPoints = segments.map((segment) => {
|
||||
// return { x: segment.x + offset.x, y: segment.y + offset.y };
|
||||
// });
|
||||
// edge.points = [
|
||||
// { x: src.x + offset.x, y: src.y + offset.y },
|
||||
// ...segPoints,
|
||||
// { x: dest.x + offset.x, y: dest.y + offset.y },
|
||||
// ];
|
||||
// const paths = insertEdge(
|
||||
// edgesEl,
|
||||
// edge,
|
||||
// clusterDb,
|
||||
// data4Layout.type,
|
||||
// startNode,
|
||||
// endNode,
|
||||
// data4Layout.diagramId
|
||||
// );
|
||||
// log.info('APA12 edge points after insert', JSON.stringify(edge.points));
|
||||
|
||||
edge.x = edge.labels[0].x + offset.x + edge.labels[0].width / 2;
|
||||
edge.y = edge.labels[0].y + offset.y + edge.labels[0].height / 2;
|
||||
positionEdgeLabel(edge, paths);
|
||||
// edge.x = edge.labels[0].x + offset.x + edge.labels[0].width / 2;
|
||||
// edge.y = edge.labels[0].y + offset.y + edge.labels[0].height / 2;
|
||||
// positionEdgeLabel(edge, paths);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -766,7 +766,7 @@ function intersectLine(p1, p2, q1, q2) {
|
||||
// The denom/2 is to get rounding instead of truncating. It
|
||||
// is added or subtracted to the numerator, depending upon the
|
||||
// sign of the numerator.
|
||||
num = b1 * c2 - b2 * c1;
|
||||
let num = b1 * c2 - b2 * c1;
|
||||
const x = num < 0 ? (num - offset) / denom : (num + offset) / denom;
|
||||
|
||||
num = a2 * c1 - a1 * c2;
|
||||
@@ -925,7 +925,6 @@ export const intersection = (node, outsidePoint, insidePoint) => {
|
||||
}
|
||||
};
|
||||
const outsideNode = (node, point) => {
|
||||
log.debug('Checking bounds ', node, point);
|
||||
const x = node.x;
|
||||
const y = node.y;
|
||||
const dx = Math.abs(point.x - x);
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@zenuml/core": "^3.19.2"
|
||||
"@zenuml/core": "^3.23.27"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@mermaid-chart/mermaid": "workspace:^"
|
||||
|
||||
@@ -80,7 +80,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",
|
||||
"roughjs": "^4.6.6",
|
||||
"stylis": "^4.3.1",
|
||||
"ts-dedent": "^2.2.0",
|
||||
|
||||
@@ -88,16 +88,18 @@ export interface MermaidConfig {
|
||||
*
|
||||
*/
|
||||
maxEdges?: number;
|
||||
elk?: {
|
||||
/**
|
||||
* Elk specific option that allows egdes to share path where it convenient. It can make for pretty diagrams but can also make it harder to read the diagram.
|
||||
* Elk specific option that allows edges to share path where it convenient. It can make for pretty diagrams but can also make it harder to read the diagram.
|
||||
*
|
||||
*/
|
||||
'elk.mergeEdges'?: boolean;
|
||||
mergeEdges?: boolean;
|
||||
/**
|
||||
* Elk specific option affedcting how nodes are placed.
|
||||
* Elk specific option affecting how nodes are placed.
|
||||
*
|
||||
*/
|
||||
'elk.nodePlacement.strategy'?: 'SIMPLE' | 'NETWORK_SIMPLEX' | 'LINEAR_SEGMENTS' | 'BRANDES_KOEPF';
|
||||
nodePlacementStrategy?: 'SIMPLE' | 'NETWORK_SIMPLEX' | 'LINEAR_SEGMENTS' | 'BRANDES_KOEPF';
|
||||
};
|
||||
darkMode?: boolean;
|
||||
htmlLabels?: boolean;
|
||||
/**
|
||||
|
||||
@@ -20,6 +20,10 @@ const config: RequiredDeep<MermaidConfig> = {
|
||||
// Set, even though they're `undefined` so that `configKeys` finds these keys
|
||||
// TODO: Should we replace these with `null` so that they can go in the JSON Schema?
|
||||
deterministicIDSeed: undefined,
|
||||
elk: {
|
||||
mergeEdges: false,
|
||||
nodePlacementStrategy: 'SIMPLE',
|
||||
},
|
||||
themeCSS: undefined,
|
||||
|
||||
// add non-JSON default config values
|
||||
|
||||
@@ -113,6 +113,7 @@ export const clear = function () {
|
||||
functions.push(setupToolTips);
|
||||
namespaces = new Map();
|
||||
namespaceCounter = 0;
|
||||
direction = 'TB';
|
||||
commonClear();
|
||||
};
|
||||
|
||||
|
||||
@@ -444,6 +444,17 @@ class C13["With Città foreign language"]
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('should revert direction to default once direction is removed', () => {
|
||||
parser.parse(`classDiagram
|
||||
direction RL
|
||||
class A`);
|
||||
expect(classDb.getDirection()).toBe('RL');
|
||||
classDb.clear();
|
||||
parser.parse(`classDiagram
|
||||
class B`);
|
||||
expect(classDb.getDirection()).toBe('TB');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when parsing class defined in brackets', function () {
|
||||
|
||||
@@ -205,6 +205,13 @@ export const updateLink = function (positions: ('default' | number)[], style: st
|
||||
// style.push('fill:none');
|
||||
// }
|
||||
edges[pos].style = style;
|
||||
// if edges[pos].style does have fill not set, set it to none
|
||||
if (
|
||||
(edges[pos]?.style?.length ?? 0) > 0 &&
|
||||
!edges[pos]?.style?.some((s) => s?.startsWith('fill'))
|
||||
) {
|
||||
edges[pos]?.style?.push('fill:none');
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -51,7 +51,7 @@ export const draw = async function (text: string, id: string, _version: string,
|
||||
await render(data4Layout, svg, element);
|
||||
const padding = data4Layout.config.flowchart?.padding ?? 8;
|
||||
utils.insertTitle(
|
||||
element,
|
||||
svg,
|
||||
'flowchartTitleText',
|
||||
conf?.titleTopMargin || 0,
|
||||
diag.db.getDiagramTitle()
|
||||
|
||||
@@ -12,8 +12,7 @@ import {
|
||||
getDiagramTitle,
|
||||
} from '../common/commonDb.js';
|
||||
|
||||
let mainBranchName = getConfig().gitGraph.mainBranchName;
|
||||
let mainBranchOrder = getConfig().gitGraph.mainBranchOrder;
|
||||
let { mainBranchName, mainBranchOrder } = getConfig().gitGraph;
|
||||
let commits = new Map();
|
||||
let head = null;
|
||||
let branchesConfig = new Map();
|
||||
@@ -103,17 +102,18 @@ export const getOptions = function () {
|
||||
return options;
|
||||
};
|
||||
|
||||
export const commit = function (msg, id, type, tag) {
|
||||
log.debug('Entering commit:', msg, id, type, tag);
|
||||
id = common.sanitizeText(id, getConfig());
|
||||
msg = common.sanitizeText(msg, getConfig());
|
||||
tag = common.sanitizeText(tag, getConfig());
|
||||
export const commit = function (msg, id, type, tags) {
|
||||
log.debug('Entering commit:', msg, id, type, tags);
|
||||
const config = getConfig();
|
||||
id = common.sanitizeText(id, config);
|
||||
msg = common.sanitizeText(msg, config);
|
||||
tags = tags?.map((tag) => common.sanitizeText(tag, config));
|
||||
const commit = {
|
||||
id: id ? id : seq + '-' + getId(),
|
||||
message: msg,
|
||||
seq: seq++,
|
||||
type: type ? type : commitType.NORMAL,
|
||||
tag: tag ? tag : '',
|
||||
tags: tags ?? [],
|
||||
parents: head == null ? [] : [head.id],
|
||||
branch: curBranch,
|
||||
};
|
||||
@@ -147,9 +147,10 @@ export const branch = function (name, order) {
|
||||
}
|
||||
};
|
||||
|
||||
export const merge = function (otherBranch, custom_id, override_type, custom_tag) {
|
||||
otherBranch = common.sanitizeText(otherBranch, getConfig());
|
||||
custom_id = common.sanitizeText(custom_id, getConfig());
|
||||
export const merge = function (otherBranch, custom_id, override_type, custom_tags) {
|
||||
const config = getConfig();
|
||||
otherBranch = common.sanitizeText(otherBranch, config);
|
||||
custom_id = common.sanitizeText(custom_id, config);
|
||||
|
||||
const currentCommit = commits.get(branches.get(curBranch));
|
||||
const otherCommit = commits.get(branches.get(otherBranch));
|
||||
@@ -216,12 +217,12 @@ export const merge = function (otherBranch, custom_id, override_type, custom_tag
|
||||
' already exists, use different custom Id'
|
||||
);
|
||||
error.hash = {
|
||||
text: 'merge ' + otherBranch + custom_id + override_type + custom_tag,
|
||||
token: 'merge ' + otherBranch + custom_id + override_type + custom_tag,
|
||||
text: 'merge ' + otherBranch + custom_id + override_type + custom_tags?.join(','),
|
||||
token: 'merge ' + otherBranch + custom_id + override_type + custom_tags?.join(','),
|
||||
line: '1',
|
||||
loc: { first_line: 1, last_line: 1, first_column: 1, last_column: 1 },
|
||||
expected: [
|
||||
'merge ' + otherBranch + ' ' + custom_id + '_UNIQUE ' + override_type + ' ' + custom_tag,
|
||||
`merge ${otherBranch} ${custom_id}_UNIQUE ${override_type} ${custom_tags?.join(',')}`,
|
||||
],
|
||||
};
|
||||
|
||||
@@ -245,7 +246,7 @@ export const merge = function (otherBranch, custom_id, override_type, custom_tag
|
||||
type: commitType.MERGE,
|
||||
customType: override_type,
|
||||
customId: custom_id ? true : false,
|
||||
tag: custom_tag ? custom_tag : '',
|
||||
tags: custom_tags ? custom_tags : [],
|
||||
};
|
||||
head = commit;
|
||||
commits.set(commit.id, commit);
|
||||
@@ -255,12 +256,13 @@ export const merge = function (otherBranch, custom_id, override_type, custom_tag
|
||||
log.debug('in mergeBranch');
|
||||
};
|
||||
|
||||
export const cherryPick = function (sourceId, targetId, tag, parentCommitId) {
|
||||
log.debug('Entering cherryPick:', sourceId, targetId, tag);
|
||||
sourceId = common.sanitizeText(sourceId, getConfig());
|
||||
targetId = common.sanitizeText(targetId, getConfig());
|
||||
tag = common.sanitizeText(tag, getConfig());
|
||||
parentCommitId = common.sanitizeText(parentCommitId, getConfig());
|
||||
export const cherryPick = function (sourceId, targetId, tags, parentCommitId) {
|
||||
log.debug('Entering cherryPick:', sourceId, targetId, tags);
|
||||
const config = getConfig();
|
||||
sourceId = common.sanitizeText(sourceId, config);
|
||||
targetId = common.sanitizeText(targetId, config);
|
||||
tags = tags?.map((tag) => common.sanitizeText(tag, config));
|
||||
parentCommitId = common.sanitizeText(parentCommitId, config);
|
||||
|
||||
if (!sourceId || !commits.has(sourceId)) {
|
||||
let error = new Error(
|
||||
@@ -329,11 +331,13 @@ export const cherryPick = function (sourceId, targetId, tag, parentCommitId) {
|
||||
parents: [head == null ? null : head.id, sourceCommit.id],
|
||||
branch: curBranch,
|
||||
type: commitType.CHERRY_PICK,
|
||||
tag:
|
||||
tag ??
|
||||
tags: tags
|
||||
? tags.filter(Boolean)
|
||||
: [
|
||||
`cherry-pick:${sourceCommit.id}${
|
||||
sourceCommit.type === commitType.MERGE ? `|parent:${parentCommitId}` : ''
|
||||
}`,
|
||||
],
|
||||
};
|
||||
head = commit;
|
||||
commits.set(commit.id, commit);
|
||||
@@ -356,8 +360,6 @@ export const checkout = function (branch) {
|
||||
expected: ['"branch ' + branch + '"'],
|
||||
};
|
||||
throw error;
|
||||
//branches[branch] = head != null ? head.id : null;
|
||||
//log.debug('in createBranch');
|
||||
} else {
|
||||
curBranch = branch;
|
||||
const id = branches.get(curBranch);
|
||||
@@ -444,13 +446,12 @@ export const prettyPrint = function () {
|
||||
export const clear = function () {
|
||||
commits = new Map();
|
||||
head = null;
|
||||
let mainBranch = getConfig().gitGraph.mainBranchName;
|
||||
let mainBranchOrder = getConfig().gitGraph.mainBranchOrder;
|
||||
const { mainBranchName, mainBranchOrder } = getConfig().gitGraph;
|
||||
branches = new Map();
|
||||
branches.set(mainBranch, null);
|
||||
branches.set(mainBranchName, null);
|
||||
branchesConfig = new Map();
|
||||
branchesConfig.set(mainBranch, { name: mainBranch, order: mainBranchOrder });
|
||||
curBranch = mainBranch;
|
||||
branchesConfig.set(mainBranchName, { name: mainBranchName, order: mainBranchOrder });
|
||||
curBranch = mainBranchName;
|
||||
seq = 0;
|
||||
commonClear();
|
||||
};
|
||||
|
||||
@@ -20,7 +20,7 @@ describe('when parsing a gitGraph', function () {
|
||||
const key = commits.keys().next().value;
|
||||
expect(commits.get(key).message).toBe('');
|
||||
expect(commits.get(key).id).not.toBeNull();
|
||||
expect(commits.get(key).tag).toBe('');
|
||||
expect(commits.get(key).tags).toStrictEqual([]);
|
||||
expect(commits.get(key).type).toBe(0);
|
||||
});
|
||||
|
||||
@@ -37,7 +37,7 @@ describe('when parsing a gitGraph', function () {
|
||||
const key = commits.keys().next().value;
|
||||
expect(commits.get(key).message).toBe('');
|
||||
expect(commits.get(key).id).toBe('1111');
|
||||
expect(commits.get(key).tag).toBe('');
|
||||
expect(commits.get(key).tags).toStrictEqual([]);
|
||||
expect(commits.get(key).type).toBe(0);
|
||||
});
|
||||
|
||||
@@ -55,7 +55,7 @@ describe('when parsing a gitGraph', function () {
|
||||
const key = commits.keys().next().value;
|
||||
expect(commits.get(key).message).toBe('');
|
||||
expect(commits.get(key).id).not.toBeNull();
|
||||
expect(commits.get(key).tag).toBe('test');
|
||||
expect(commits.get(key).tags).toStrictEqual(['test']);
|
||||
expect(commits.get(key).type).toBe(0);
|
||||
});
|
||||
|
||||
@@ -73,7 +73,7 @@ describe('when parsing a gitGraph', function () {
|
||||
const key = commits.keys().next().value;
|
||||
expect(commits.get(key).message).toBe('');
|
||||
expect(commits.get(key).id).not.toBeNull();
|
||||
expect(commits.get(key).tag).toBe('');
|
||||
expect(commits.get(key).tags).toStrictEqual([]);
|
||||
expect(commits.get(key).type).toBe(2);
|
||||
});
|
||||
|
||||
@@ -91,7 +91,7 @@ describe('when parsing a gitGraph', function () {
|
||||
const key = commits.keys().next().value;
|
||||
expect(commits.get(key).message).toBe('');
|
||||
expect(commits.get(key).id).not.toBeNull();
|
||||
expect(commits.get(key).tag).toBe('');
|
||||
expect(commits.get(key).tags).toStrictEqual([]);
|
||||
expect(commits.get(key).type).toBe(1);
|
||||
});
|
||||
|
||||
@@ -109,7 +109,7 @@ describe('when parsing a gitGraph', function () {
|
||||
const key = commits.keys().next().value;
|
||||
expect(commits.get(key).message).toBe('');
|
||||
expect(commits.get(key).id).not.toBeNull();
|
||||
expect(commits.get(key).tag).toBe('');
|
||||
expect(commits.get(key).tags).toStrictEqual([]);
|
||||
expect(commits.get(key).type).toBe(0);
|
||||
});
|
||||
|
||||
@@ -127,7 +127,7 @@ describe('when parsing a gitGraph', function () {
|
||||
const key = commits.keys().next().value;
|
||||
expect(commits.get(key).message).toBe('test commit');
|
||||
expect(commits.get(key).id).not.toBeNull();
|
||||
expect(commits.get(key).tag).toBe('');
|
||||
expect(commits.get(key).tags).toStrictEqual([]);
|
||||
expect(commits.get(key).type).toBe(0);
|
||||
});
|
||||
|
||||
@@ -145,7 +145,7 @@ describe('when parsing a gitGraph', function () {
|
||||
const key = commits.keys().next().value;
|
||||
expect(commits.get(key).message).toBe('test commit');
|
||||
expect(commits.get(key).id).not.toBeNull();
|
||||
expect(commits.get(key).tag).toBe('');
|
||||
expect(commits.get(key).tags).toStrictEqual([]);
|
||||
expect(commits.get(key).type).toBe(0);
|
||||
});
|
||||
|
||||
@@ -163,7 +163,7 @@ describe('when parsing a gitGraph', function () {
|
||||
const key = commits.keys().next().value;
|
||||
expect(commits.get(key).message).toBe('');
|
||||
expect(commits.get(key).id).toBe('1111');
|
||||
expect(commits.get(key).tag).toBe('test tag');
|
||||
expect(commits.get(key).tags).toStrictEqual(['test tag']);
|
||||
expect(commits.get(key).type).toBe(0);
|
||||
});
|
||||
|
||||
@@ -181,7 +181,7 @@ describe('when parsing a gitGraph', function () {
|
||||
const key = commits.keys().next().value;
|
||||
expect(commits.get(key).message).toBe('');
|
||||
expect(commits.get(key).id).not.toBeNull();
|
||||
expect(commits.get(key).tag).toBe('test tag');
|
||||
expect(commits.get(key).tags).toStrictEqual(['test tag']);
|
||||
expect(commits.get(key).type).toBe(2);
|
||||
});
|
||||
|
||||
@@ -199,7 +199,7 @@ describe('when parsing a gitGraph', function () {
|
||||
const key = commits.keys().next().value;
|
||||
expect(commits.get(key).message).toBe('');
|
||||
expect(commits.get(key).id).not.toBeNull();
|
||||
expect(commits.get(key).tag).toBe('test tag');
|
||||
expect(commits.get(key).tags).toStrictEqual(['test tag']);
|
||||
expect(commits.get(key).type).toBe(2);
|
||||
});
|
||||
|
||||
@@ -217,7 +217,7 @@ describe('when parsing a gitGraph', function () {
|
||||
const key = commits.keys().next().value;
|
||||
expect(commits.get(key).message).toBe('');
|
||||
expect(commits.get(key).id).toBe('1111');
|
||||
expect(commits.get(key).tag).toBe('test tag');
|
||||
expect(commits.get(key).tags).toStrictEqual(['test tag']);
|
||||
expect(commits.get(key).type).toBe(1);
|
||||
});
|
||||
|
||||
@@ -235,7 +235,7 @@ describe('when parsing a gitGraph', function () {
|
||||
const key = commits.keys().next().value;
|
||||
expect(commits.get(key).message).toBe('test msg');
|
||||
expect(commits.get(key).id).toBe('1111');
|
||||
expect(commits.get(key).tag).toBe('test tag');
|
||||
expect(commits.get(key).tags).toStrictEqual(['test tag']);
|
||||
expect(commits.get(key).type).toBe(1);
|
||||
});
|
||||
|
||||
@@ -254,7 +254,7 @@ describe('when parsing a gitGraph', function () {
|
||||
const key = commits.keys().next().value;
|
||||
expect(commits.get(key).message).toBe('test msg');
|
||||
expect(commits.get(key).id).toBe('1111');
|
||||
expect(commits.get(key).tag).toBe('test tag');
|
||||
expect(commits.get(key).tags).toStrictEqual(['test tag']);
|
||||
expect(commits.get(key).type).toBe(1);
|
||||
});
|
||||
|
||||
@@ -272,7 +272,7 @@ describe('when parsing a gitGraph', function () {
|
||||
const key = commits.keys().next().value;
|
||||
expect(commits.get(key).message).toBe('test msg');
|
||||
expect(commits.get(key).id).toBe('1111');
|
||||
expect(commits.get(key).tag).toBe('test tag');
|
||||
expect(commits.get(key).tags).toStrictEqual(['test tag']);
|
||||
expect(commits.get(key).type).toBe(1);
|
||||
});
|
||||
|
||||
@@ -290,7 +290,7 @@ describe('when parsing a gitGraph', function () {
|
||||
const key = commits.keys().next().value;
|
||||
expect(commits.get(key).message).toBe('test msg');
|
||||
expect(commits.get(key).id).toBe('1111');
|
||||
expect(commits.get(key).tag).toBe('test tag');
|
||||
expect(commits.get(key).tags).toStrictEqual(['test tag']);
|
||||
expect(commits.get(key).type).toBe(1);
|
||||
});
|
||||
|
||||
@@ -616,7 +616,7 @@ describe('when parsing a gitGraph', function () {
|
||||
commits.get(commit1).id,
|
||||
commits.get(commit2).id,
|
||||
]);
|
||||
expect(commits.get(commit3).tag).toBe('merge-tag');
|
||||
expect(commits.get(commit3).tags).toStrictEqual(['merge-tag']);
|
||||
expect(parser.yy.getBranchesAsObjArray()).toStrictEqual([
|
||||
{ name: 'main' },
|
||||
{ name: 'testBranch' },
|
||||
@@ -671,12 +671,12 @@ describe('when parsing a gitGraph', function () {
|
||||
|
||||
expect(testBranchMerge.branch).toBe('main');
|
||||
expect(testBranchMerge.parents).toStrictEqual([mainCommit.id, testBranchCommit.id]);
|
||||
expect(testBranchMerge.tag).toBe('merge-tag');
|
||||
expect(testBranchMerge.tags).toStrictEqual(['merge-tag']);
|
||||
expect(testBranchMerge.id).toBe('2-222');
|
||||
|
||||
expect(testBranch2Merge.branch).toBe('main');
|
||||
expect(testBranch2Merge.parents).toStrictEqual([testBranchMerge.id, testBranch2Commit.id]);
|
||||
expect(testBranch2Merge.tag).toBe('merge-tag2');
|
||||
expect(testBranch2Merge.tags).toStrictEqual(['merge-tag2']);
|
||||
expect(testBranch2Merge.id).toBe('4-444');
|
||||
expect(testBranch2Merge.customType).toBe(2);
|
||||
expect(testBranch2Merge.customId).toBe(true);
|
||||
@@ -705,7 +705,7 @@ describe('when parsing a gitGraph', function () {
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
const cherryPickCommitID = [...commits.keys()][2];
|
||||
expect(commits.get(cherryPickCommitID).tag).toBe('cherry-pick:A');
|
||||
expect(commits.get(cherryPickCommitID).tags).toStrictEqual(['cherry-pick:A']);
|
||||
expect(commits.get(cherryPickCommitID).branch).toBe('main');
|
||||
});
|
||||
|
||||
@@ -721,7 +721,7 @@ describe('when parsing a gitGraph', function () {
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
const cherryPickCommitID = [...commits.keys()][2];
|
||||
expect(commits.get(cherryPickCommitID).tag).toBe('MyTag');
|
||||
expect(commits.get(cherryPickCommitID).tags).toStrictEqual(['MyTag']);
|
||||
expect(commits.get(cherryPickCommitID).branch).toBe('main');
|
||||
});
|
||||
|
||||
@@ -737,7 +737,7 @@ describe('when parsing a gitGraph', function () {
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
const cherryPickCommitID = [...commits.keys()][2];
|
||||
expect(commits.get(cherryPickCommitID).tag).toBe('');
|
||||
expect(commits.get(cherryPickCommitID).tags).toStrictEqual([]);
|
||||
expect(commits.get(cherryPickCommitID).branch).toBe('main');
|
||||
});
|
||||
|
||||
@@ -758,7 +758,7 @@ describe('when parsing a gitGraph', function () {
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
const cherryPickCommitID = [...commits.keys()][4];
|
||||
expect(commits.get(cherryPickCommitID).tag).toBe('cherry-pick:M|parent:B');
|
||||
expect(commits.get(cherryPickCommitID).tags).toStrictEqual(['cherry-pick:M|parent:B']);
|
||||
expect(commits.get(cherryPickCommitID).branch).toBe('release');
|
||||
});
|
||||
|
||||
@@ -779,7 +779,7 @@ describe('when parsing a gitGraph', function () {
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
const cherryPickCommitID = [...commits.keys()][4];
|
||||
expect(commits.get(cherryPickCommitID).tag).toBe('v1.0');
|
||||
expect(commits.get(cherryPickCommitID).tags).toStrictEqual(['v1.0']);
|
||||
expect(commits.get(cherryPickCommitID).branch).toBe('release');
|
||||
});
|
||||
|
||||
@@ -802,7 +802,7 @@ describe('when parsing a gitGraph', function () {
|
||||
parser.parse(str);
|
||||
const commits = parser.yy.getCommits();
|
||||
const cherryPickCommitID = [...commits.keys()][5];
|
||||
expect(commits.get(cherryPickCommitID).tag).toBe('v2.1:ZERO');
|
||||
expect(commits.get(cherryPickCommitID).tags).toStrictEqual(['v2.1:ZERO']);
|
||||
expect(commits.get(cherryPickCommitID).branch).toBe('release');
|
||||
});
|
||||
|
||||
@@ -827,8 +827,8 @@ describe('when parsing a gitGraph', function () {
|
||||
const commits = parser.yy.getCommits();
|
||||
const cherryPickCommitID = [...commits.keys()][5];
|
||||
const cherryPickCommitID2 = [...commits.keys()][7];
|
||||
expect(commits.get(cherryPickCommitID).tag).toBe('');
|
||||
expect(commits.get(cherryPickCommitID2).tag).toBe('');
|
||||
expect(commits.get(cherryPickCommitID).tags).toStrictEqual([]);
|
||||
expect(commits.get(cherryPickCommitID2).tags).toStrictEqual([]);
|
||||
expect(commits.get(cherryPickCommitID).branch).toBe('release');
|
||||
});
|
||||
|
||||
|
||||
@@ -414,62 +414,86 @@ const drawCommits = (svg, commits, modifyGraph) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (commit.tag) {
|
||||
if (commit.tags.length > 0) {
|
||||
let yOffset = 0;
|
||||
let maxTagBboxWidth = 0;
|
||||
let maxTagBboxHeight = 0;
|
||||
const tagElements = [];
|
||||
|
||||
for (const tagValue of commit.tags.reverse()) {
|
||||
const rect = gLabels.insert('polygon');
|
||||
const hole = gLabels.append('circle');
|
||||
const tag = gLabels
|
||||
.append('text')
|
||||
// Note that we are delaying setting the x position until we know the width of the text
|
||||
.attr('y', y - 16)
|
||||
.attr('y', y - 16 - yOffset)
|
||||
.attr('class', 'tag-label')
|
||||
.text(commit.tag);
|
||||
.text(tagValue);
|
||||
let tagBbox = tag.node().getBBox();
|
||||
maxTagBboxWidth = Math.max(maxTagBboxWidth, tagBbox.width);
|
||||
maxTagBboxHeight = Math.max(maxTagBboxHeight, tagBbox.height);
|
||||
|
||||
// We don't use the max over here to center the text within the tags
|
||||
tag.attr('x', posWithOffset - tagBbox.width / 2);
|
||||
|
||||
const h2 = tagBbox.height / 2;
|
||||
const ly = y - 19.2;
|
||||
tagElements.push({
|
||||
tag,
|
||||
hole,
|
||||
rect,
|
||||
yOffset,
|
||||
});
|
||||
|
||||
yOffset += 20;
|
||||
}
|
||||
|
||||
for (const { tag, hole, rect, yOffset } of tagElements) {
|
||||
const h2 = maxTagBboxHeight / 2;
|
||||
const ly = y - 19.2 - yOffset;
|
||||
rect.attr('class', 'tag-label-bkg').attr(
|
||||
'points',
|
||||
`
|
||||
${pos - tagBbox.width / 2 - px / 2},${ly + py}
|
||||
${pos - tagBbox.width / 2 - px / 2},${ly - py}
|
||||
${posWithOffset - tagBbox.width / 2 - px},${ly - h2 - py}
|
||||
${posWithOffset + tagBbox.width / 2 + px},${ly - h2 - py}
|
||||
${posWithOffset + tagBbox.width / 2 + px},${ly + h2 + py}
|
||||
${posWithOffset - tagBbox.width / 2 - px},${ly + h2 + py}`
|
||||
${pos - maxTagBboxWidth / 2 - px / 2},${ly + py}
|
||||
${pos - maxTagBboxWidth / 2 - px / 2},${ly - py}
|
||||
${posWithOffset - maxTagBboxWidth / 2 - px},${ly - h2 - py}
|
||||
${posWithOffset + maxTagBboxWidth / 2 + px},${ly - h2 - py}
|
||||
${posWithOffset + maxTagBboxWidth / 2 + px},${ly + h2 + py}
|
||||
${posWithOffset - maxTagBboxWidth / 2 - px},${ly + h2 + py}`
|
||||
);
|
||||
|
||||
hole
|
||||
.attr('cx', pos - tagBbox.width / 2 + px / 2)
|
||||
.attr('cy', ly)
|
||||
.attr('cx', pos - maxTagBboxWidth / 2 + px / 2)
|
||||
.attr('r', 1.5)
|
||||
.attr('class', 'tag-hole');
|
||||
|
||||
if (dir === 'TB' || dir === 'BT') {
|
||||
const yOrigin = pos + yOffset;
|
||||
|
||||
rect
|
||||
.attr('class', 'tag-label-bkg')
|
||||
.attr(
|
||||
'points',
|
||||
`
|
||||
${x},${pos + py}
|
||||
${x},${pos - py}
|
||||
${x + layoutOffset},${pos - h2 - py}
|
||||
${x + layoutOffset + tagBbox.width + px},${pos - h2 - py}
|
||||
${x + layoutOffset + tagBbox.width + px},${pos + h2 + py}
|
||||
${x + layoutOffset},${pos + h2 + py}`
|
||||
${x},${yOrigin + py}
|
||||
${x},${yOrigin - py}
|
||||
${x + layoutOffset},${yOrigin - h2 - py}
|
||||
${x + layoutOffset + maxTagBboxWidth + px},${yOrigin - h2 - py}
|
||||
${x + layoutOffset + maxTagBboxWidth + px},${yOrigin + h2 + py}
|
||||
${x + layoutOffset},${yOrigin + h2 + py}`
|
||||
)
|
||||
.attr('transform', 'translate(12,12) rotate(45, ' + x + ',' + pos + ')');
|
||||
hole
|
||||
.attr('cx', x + px / 2)
|
||||
.attr('cy', pos)
|
||||
.attr('cy', yOrigin)
|
||||
.attr('transform', 'translate(12,12) rotate(45, ' + x + ',' + pos + ')');
|
||||
tag
|
||||
.attr('x', x + 5)
|
||||
.attr('y', pos + 3)
|
||||
.attr('y', yOrigin + 3)
|
||||
.attr('transform', 'translate(14,14) rotate(45, ' + x + ',' + pos + ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pos = dir === 'BT' && isParallelCommits ? pos + commitStep : pos + commitStep + layoutOffset;
|
||||
if (pos > maxPos) {
|
||||
maxPos = pos;
|
||||
|
||||
@@ -112,122 +112,105 @@ branchStatement
|
||||
cherryPickStatement
|
||||
: CHERRY_PICK COMMIT_ID STR {yy.cherryPick($3, '', undefined)}
|
||||
| CHERRY_PICK COMMIT_ID STR PARENT_COMMIT STR {yy.cherryPick($3, '', undefined,$5)}
|
||||
| CHERRY_PICK COMMIT_ID STR COMMIT_TAG STR {yy.cherryPick($3, '', $5)}
|
||||
| CHERRY_PICK COMMIT_ID STR PARENT_COMMIT STR COMMIT_TAG STR {yy.cherryPick($3, '', $7,$5)}
|
||||
| CHERRY_PICK COMMIT_ID STR COMMIT_TAG STR PARENT_COMMIT STR {yy.cherryPick($3, '', $5,$7)}
|
||||
| CHERRY_PICK COMMIT_TAG STR COMMIT_ID STR {yy.cherryPick($5, '', $3)}
|
||||
| CHERRY_PICK COMMIT_TAG EMPTYSTR COMMIT_ID STR {yy.cherryPick($5, '', '')}
|
||||
| CHERRY_PICK COMMIT_ID STR COMMIT_TAG EMPTYSTR {yy.cherryPick($3, '', '')}
|
||||
| CHERRY_PICK COMMIT_ID STR PARENT_COMMIT STR COMMIT_TAG EMPTYSTR {yy.cherryPick($3, '', '',$5)}
|
||||
| CHERRY_PICK COMMIT_ID STR COMMIT_TAG EMPTYSTR PARENT_COMMIT STR {yy.cherryPick($3, '', '',$7)}
|
||||
| CHERRY_PICK COMMIT_TAG STR COMMIT_ID STR PARENT_COMMIT STR {yy.cherryPick($5, '', $3,$7)}
|
||||
| CHERRY_PICK COMMIT_TAG EMPTYSTR COMMIT_ID STR PARENT_COMMIT STR{yy.cherryPick($5, '', '',$7)}
|
||||
| CHERRY_PICK COMMIT_ID STR commitTags {yy.cherryPick($3, '', $4)}
|
||||
| CHERRY_PICK COMMIT_ID STR PARENT_COMMIT STR commitTags {yy.cherryPick($3, '', $6,$5)}
|
||||
| CHERRY_PICK COMMIT_ID STR commitTags PARENT_COMMIT STR {yy.cherryPick($3, '', $4,$6)}
|
||||
| CHERRY_PICK commitTags COMMIT_ID STR {yy.cherryPick($4, '', $2)}
|
||||
| CHERRY_PICK commitTags COMMIT_ID STR PARENT_COMMIT STR {yy.cherryPick($4, '', $2,$6)}
|
||||
;
|
||||
|
||||
mergeStatement
|
||||
: MERGE ref {yy.merge($2,'','','')}
|
||||
| MERGE ref COMMIT_ID STR {yy.merge($2, $4,'','')}
|
||||
| MERGE ref COMMIT_TYPE commitType {yy.merge($2,'', $4,'')}
|
||||
| MERGE ref COMMIT_TAG STR {yy.merge($2, '','',$4)}
|
||||
| MERGE ref COMMIT_TAG STR COMMIT_ID STR {yy.merge($2, $6,'', $4)}
|
||||
| MERGE ref COMMIT_TAG STR COMMIT_TYPE commitType {yy.merge($2, '',$6, $4)}
|
||||
| MERGE ref COMMIT_TYPE commitType COMMIT_TAG STR {yy.merge($2, '',$4, $6)}
|
||||
| MERGE ref COMMIT_ID STR COMMIT_TYPE commitType {yy.merge($2, $4, $6, '')}
|
||||
| MERGE ref COMMIT_ID STR COMMIT_TAG STR {yy.merge($2, $4, '', $6)}
|
||||
| MERGE ref COMMIT_TYPE commitType COMMIT_ID STR {yy.merge($2, $6,$4, '')}
|
||||
| MERGE ref COMMIT_ID STR COMMIT_TYPE commitType COMMIT_TAG STR {yy.merge($2, $4, $6, $8)}
|
||||
| MERGE ref COMMIT_TYPE commitType COMMIT_TAG STR COMMIT_ID STR {yy.merge($2, $8, $4, $6)}
|
||||
| MERGE ref COMMIT_ID STR COMMIT_TAG STR COMMIT_TYPE commitType {yy.merge($2, $4, $8, $6)}
|
||||
| MERGE ref COMMIT_TYPE commitType COMMIT_ID STR COMMIT_TAG STR {yy.merge($2, $6, $4, $8)}
|
||||
| MERGE ref COMMIT_TAG STR COMMIT_TYPE commitType COMMIT_ID STR {yy.merge($2, $8, $6, $4)}
|
||||
| MERGE ref COMMIT_TAG STR COMMIT_ID STR COMMIT_TYPE commitType {yy.merge($2, $6, $8, $4)}
|
||||
: MERGE ref {yy.merge($2,'','', undefined)}
|
||||
| MERGE ref COMMIT_ID STR {yy.merge($2, $4,'', undefined)}
|
||||
| MERGE ref COMMIT_TYPE commitType {yy.merge($2,'', $4, undefined)}
|
||||
| MERGE ref commitTags {yy.merge($2, '','',$3)}
|
||||
| MERGE ref commitTags COMMIT_ID STR {yy.merge($2, $5,'', $3)}
|
||||
| MERGE ref commitTags COMMIT_TYPE commitType {yy.merge($2, '',$5, $3)}
|
||||
| MERGE ref COMMIT_TYPE commitType commitTags {yy.merge($2, '',$4, $5)}
|
||||
| MERGE ref COMMIT_ID STR COMMIT_TYPE commitType {yy.merge($2, $4, $6, undefined)}
|
||||
| MERGE ref COMMIT_ID STR commitTags {yy.merge($2, $4, '', $5)}
|
||||
| MERGE ref COMMIT_TYPE commitType COMMIT_ID STR {yy.merge($2, $6,$4, undefined)}
|
||||
| MERGE ref COMMIT_ID STR COMMIT_TYPE commitType commitTags {yy.merge($2, $4, $6, $7)}
|
||||
| MERGE ref COMMIT_TYPE commitType commitTags COMMIT_ID STR {yy.merge($2, $7, $4, $5)}
|
||||
| MERGE ref COMMIT_ID STR commitTags COMMIT_TYPE commitType {yy.merge($2, $4, $7, $5)}
|
||||
| MERGE ref COMMIT_TYPE commitType COMMIT_ID STR commitTags {yy.merge($2, $6, $4, $7)}
|
||||
| MERGE ref commitTags COMMIT_TYPE commitType COMMIT_ID STR {yy.merge($2, $7, $5, $3)}
|
||||
| MERGE ref commitTags COMMIT_ID STR COMMIT_TYPE commitType {yy.merge($2, $5, $7, $3)}
|
||||
;
|
||||
|
||||
commitStatement
|
||||
: COMMIT commit_arg {yy.commit($2)}
|
||||
| COMMIT COMMIT_TAG STR {yy.commit('','',yy.commitType.NORMAL,$3)}
|
||||
| COMMIT COMMIT_TYPE commitType {yy.commit('','',$3,'')}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_TYPE commitType {yy.commit('','',$5,$3)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_TAG STR {yy.commit('','',$3,$5)}
|
||||
| COMMIT COMMIT_ID STR {yy.commit('',$3,yy.commitType.NORMAL,'')}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TAG STR {yy.commit('',$3,yy.commitType.NORMAL,$5)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_ID STR {yy.commit('',$5,yy.commitType.NORMAL,$3)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TYPE commitType {yy.commit('',$3,$5,'')}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_ID STR {yy.commit('',$5,$3,'')}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TYPE commitType COMMIT_TAG STR {yy.commit('',$3,$5,$7)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TAG STR COMMIT_TYPE commitType {yy.commit('',$3,$7,$5)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_ID STR COMMIT_TAG STR {yy.commit('',$5,$3,$7)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_TAG STR COMMIT_ID STR {yy.commit('',$7,$3,$5)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_TYPE commitType COMMIT_ID STR {yy.commit('',$7,$5,$3)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_ID STR COMMIT_TYPE commitType {yy.commit('',$5,$7,$3)}
|
||||
| COMMIT COMMIT_MSG STR {yy.commit($3,'',yy.commitType.NORMAL,'')}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_MSG STR {yy.commit($5,'',yy.commitType.NORMAL,$3)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TAG STR {yy.commit($3,'',yy.commitType.NORMAL,$5)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TYPE commitType {yy.commit($3,'',$5,'')}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_MSG STR {yy.commit($5,'',$3,'')}
|
||||
| COMMIT COMMIT_ID STR COMMIT_MSG STR {yy.commit($5,$3,yy.commitType.NORMAL,'')}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_ID STR {yy.commit($3,$5,yy.commitType.NORMAL,'')}
|
||||
| COMMIT commitTags {yy.commit('','',yy.commitType.NORMAL,$2)}
|
||||
| COMMIT COMMIT_TYPE commitType {yy.commit('','',$3, undefined)}
|
||||
| COMMIT commitTags COMMIT_TYPE commitType {yy.commit('','',$4,$2)}
|
||||
| COMMIT COMMIT_TYPE commitType commitTags {yy.commit('','',$3,$4)}
|
||||
| COMMIT COMMIT_ID STR {yy.commit('',$3,yy.commitType.NORMAL, undefined)}
|
||||
| COMMIT COMMIT_ID STR commitTags {yy.commit('',$3,yy.commitType.NORMAL,$4)}
|
||||
| COMMIT commitTags COMMIT_ID STR {yy.commit('',$4,yy.commitType.NORMAL,$2)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TYPE commitType {yy.commit('',$3,$5, undefined)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_ID STR {yy.commit('',$5,$3, undefined)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TYPE commitType commitTags {yy.commit('',$3,$5,$6)}
|
||||
| COMMIT COMMIT_ID STR commitTags COMMIT_TYPE commitType {yy.commit('',$3,$6,$4)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_ID STR commitTags {yy.commit('',$5,$3,$6)}
|
||||
| COMMIT COMMIT_TYPE commitType commitTags COMMIT_ID STR {yy.commit('',$6,$3,$4)}
|
||||
| COMMIT commitTags COMMIT_TYPE commitType COMMIT_ID STR {yy.commit('',$6,$4,$2)}
|
||||
| COMMIT commitTags COMMIT_ID STR COMMIT_TYPE commitType {yy.commit('',$4,$6,$2)}
|
||||
| COMMIT COMMIT_MSG STR {yy.commit($3,'',yy.commitType.NORMAL, undefined)}
|
||||
| COMMIT commitTags COMMIT_MSG STR {yy.commit($4,'',yy.commitType.NORMAL,$2)}
|
||||
| COMMIT COMMIT_MSG STR commitTags {yy.commit($3,'',yy.commitType.NORMAL,$4)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TYPE commitType {yy.commit($3,'',$5, undefined)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_MSG STR {yy.commit($5,'',$3, undefined)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_MSG STR {yy.commit($5,$3,yy.commitType.NORMAL, undefined)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_ID STR {yy.commit($3,$5,yy.commitType.NORMAL, undefined)}
|
||||
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TYPE commitType COMMIT_TAG STR {yy.commit($3,'',$5,$7)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TAG STR COMMIT_TYPE commitType {yy.commit($3,'',$7,$5)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_MSG STR COMMIT_TAG STR {yy.commit($5,'',$3,$7)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_TAG STR COMMIT_MSG STR {yy.commit($7,'',$3,$5)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_TYPE commitType COMMIT_MSG STR {yy.commit($7,'',$5,$3)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_MSG STR COMMIT_TYPE commitType {yy.commit($5,'',$7,$3)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TYPE commitType commitTags {yy.commit($3,'',$5,$6)}
|
||||
| COMMIT COMMIT_MSG STR commitTags COMMIT_TYPE commitType {yy.commit($3,'',$6,$4)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_MSG STR commitTags {yy.commit($5,'',$3,$6)}
|
||||
| COMMIT COMMIT_TYPE commitType commitTags COMMIT_MSG STR {yy.commit($6,'',$3,$4)}
|
||||
| COMMIT commitTags COMMIT_TYPE commitType COMMIT_MSG STR {yy.commit($6,'',$4,$2)}
|
||||
| COMMIT commitTags COMMIT_MSG STR COMMIT_TYPE commitType {yy.commit($4,'',$6,$2)}
|
||||
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TYPE commitType COMMIT_ID STR {yy.commit($3,$7,$5,'')}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_ID STR COMMIT_TYPE commitType {yy.commit($3,$5,$7,'')}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_MSG STR COMMIT_ID STR {yy.commit($5,$7,$3,'')}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_ID STR COMMIT_MSG STR {yy.commit($7,$5,$3,'')}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TYPE commitType COMMIT_MSG STR {yy.commit($7,$3,$5,'')}
|
||||
| COMMIT COMMIT_ID STR COMMIT_MSG STR COMMIT_TYPE commitType {yy.commit($5,$3,$7,'')}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TYPE commitType COMMIT_ID STR {yy.commit($3,$7,$5, undefined)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_ID STR COMMIT_TYPE commitType {yy.commit($3,$5,$7, undefined)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_MSG STR COMMIT_ID STR {yy.commit($5,$7,$3, undefined)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_ID STR COMMIT_MSG STR {yy.commit($7,$5,$3, undefined)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TYPE commitType COMMIT_MSG STR {yy.commit($7,$3,$5, undefined)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_MSG STR COMMIT_TYPE commitType {yy.commit($5,$3,$7, undefined)}
|
||||
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TAG STR COMMIT_ID STR {yy.commit($3,$7,yy.commitType.NORMAL,$5)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_ID STR COMMIT_TAG STR {yy.commit($3,$5,yy.commitType.NORMAL,$7)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_MSG STR COMMIT_ID STR {yy.commit($5,$7,yy.commitType.NORMAL,$3)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_ID STR COMMIT_MSG STR {yy.commit($7,$5,yy.commitType.NORMAL,$3)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TAG STR COMMIT_MSG STR {yy.commit($7,$3,yy.commitType.NORMAL,$5)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_MSG STR COMMIT_TAG STR {yy.commit($5,$3,yy.commitType.NORMAL,$7)}
|
||||
| COMMIT COMMIT_MSG STR commitTags COMMIT_ID STR {yy.commit($3,$6,yy.commitType.NORMAL,$4)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_ID STR commitTags {yy.commit($3,$5,yy.commitType.NORMAL,$6)}
|
||||
| COMMIT commitTags COMMIT_MSG STR COMMIT_ID STR {yy.commit($4,$6,yy.commitType.NORMAL,$2)}
|
||||
| COMMIT commitTags COMMIT_ID STR COMMIT_MSG STR {yy.commit($6,$4,yy.commitType.NORMAL,$2)}
|
||||
| COMMIT COMMIT_ID STR commitTags COMMIT_MSG STR {yy.commit($6,$3,yy.commitType.NORMAL,$4)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_MSG STR commitTags {yy.commit($5,$3,yy.commitType.NORMAL,$6)}
|
||||
|
||||
| COMMIT COMMIT_MSG STR COMMIT_ID STR COMMIT_TYPE commitType COMMIT_TAG STR {yy.commit($3,$5,$7,$9)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_ID STR COMMIT_TAG STR COMMIT_TYPE commitType {yy.commit($3,$5,$9,$7)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TYPE commitType COMMIT_ID STR COMMIT_TAG STR {yy.commit($3,$7,$5,$9)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TYPE commitType COMMIT_TAG STR COMMIT_ID STR {yy.commit($3,$9,$5,$7)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TAG STR COMMIT_ID STR COMMIT_TYPE commitType {yy.commit($3,$7,$9,$5)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TAG STR COMMIT_TYPE commitType COMMIT_ID STR {yy.commit($3,$9,$7,$5)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_ID STR COMMIT_TYPE commitType commitTags {yy.commit($3,$5,$7,$8)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_ID STR commitTags COMMIT_TYPE commitType {yy.commit($3,$5,$8,$6)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TYPE commitType COMMIT_ID STR commitTags {yy.commit($3,$7,$5,$8)}
|
||||
| COMMIT COMMIT_MSG STR COMMIT_TYPE commitType commitTags COMMIT_ID STR {yy.commit($3,$8,$5,$6)}
|
||||
| COMMIT COMMIT_MSG STR commitTags COMMIT_ID STR COMMIT_TYPE commitType {yy.commit($3,$6,$8,$4)}
|
||||
| COMMIT COMMIT_MSG STR commitTags COMMIT_TYPE commitType COMMIT_ID STR {yy.commit($3,$8,$6,$4)}
|
||||
|
||||
| COMMIT COMMIT_ID STR COMMIT_MSG STR COMMIT_TYPE commitType COMMIT_TAG STR {yy.commit($5,$3,$7,$9)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_MSG STR COMMIT_TAG STR COMMIT_TYPE commitType {yy.commit($5,$3,$9,$7)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TYPE commitType COMMIT_MSG STR COMMIT_TAG STR {yy.commit($7,$3,$5,$9)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TYPE commitType COMMIT_TAG STR COMMIT_MSG STR {yy.commit($9,$3,$5,$7)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TAG STR COMMIT_MSG STR COMMIT_TYPE commitType {yy.commit($7,$3,$9,$5)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TAG STR COMMIT_TYPE commitType COMMIT_MSG STR {yy.commit($9,$3,$7,$5)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_MSG STR COMMIT_TYPE commitType commitTags {yy.commit($5,$3,$7,$8)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_MSG STR commitTags COMMIT_TYPE commitType {yy.commit($5,$3,$8,$6)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TYPE commitType COMMIT_MSG STR commitTags {yy.commit($7,$3,$5,$8)}
|
||||
| COMMIT COMMIT_ID STR COMMIT_TYPE commitType commitTags COMMIT_MSG STR {yy.commit($8,$3,$5,$6)}
|
||||
| COMMIT COMMIT_ID STR commitTags COMMIT_MSG STR COMMIT_TYPE commitType {yy.commit($6,$3,$8,$4)}
|
||||
| COMMIT COMMIT_ID STR commitTags COMMIT_TYPE commitType COMMIT_MSG STR {yy.commit($8,$3,$6,$4)}
|
||||
|
||||
| COMMIT COMMIT_TAG STR COMMIT_ID STR COMMIT_TYPE commitType COMMIT_MSG STR {yy.commit($9,$5,$7,$3)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_ID STR COMMIT_MSG STR COMMIT_TYPE commitType {yy.commit($7,$5,$9,$3)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_TYPE commitType COMMIT_ID STR COMMIT_MSG STR {yy.commit($9,$7,$5,$3)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_TYPE commitType COMMIT_MSG STR COMMIT_ID STR {yy.commit($7,$9,$5,$3)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_MSG STR COMMIT_ID STR COMMIT_TYPE commitType {yy.commit($5,$7,$9,$3)}
|
||||
| COMMIT COMMIT_TAG STR COMMIT_MSG STR COMMIT_TYPE commitType COMMIT_ID STR {yy.commit($5,$9,$7,$3)}
|
||||
| COMMIT commitTags COMMIT_ID STR COMMIT_TYPE commitType COMMIT_MSG STR {yy.commit($8,$4,$6,$2)}
|
||||
| COMMIT commitTags COMMIT_ID STR COMMIT_MSG STR COMMIT_TYPE commitType {yy.commit($6,$4,$8,$2)}
|
||||
| COMMIT commitTags COMMIT_TYPE commitType COMMIT_ID STR COMMIT_MSG STR {yy.commit($8,$6,$4,$2)}
|
||||
| COMMIT commitTags COMMIT_TYPE commitType COMMIT_MSG STR COMMIT_ID STR {yy.commit($6,$8,$4,$2)}
|
||||
| COMMIT commitTags COMMIT_MSG STR COMMIT_ID STR COMMIT_TYPE commitType {yy.commit($4,$6,$8,$2)}
|
||||
| COMMIT commitTags COMMIT_MSG STR COMMIT_TYPE commitType COMMIT_ID STR {yy.commit($4,$8,$6,$2)}
|
||||
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_ID STR COMMIT_MSG STR COMMIT_TAG STR {yy.commit($7,$5,$3,$9)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_ID STR COMMIT_TAG STR COMMIT_MSG STR {yy.commit($9,$5,$3,$7)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_TAG STR COMMIT_MSG STR COMMIT_ID STR {yy.commit($7,$9,$3,$5)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_TAG STR COMMIT_ID STR COMMIT_MSG STR {yy.commit($9,$7,$3,$5)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_MSG STR COMMIT_ID STR COMMIT_TAG STR {yy.commit($5,$7,$3,$9)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_MSG STR COMMIT_TAG STR COMMIT_ID STR {yy.commit($5,$9,$3,$7)}
|
||||
|
||||
|
||||
// | COMMIT COMMIT_ID STR {yy.commit('',$3,yy.commitType.NORMAL,'')}
|
||||
// | COMMIT COMMIT_TYPE commitType {yy.commit('','',$3,'')}
|
||||
// | COMMIT COMMIT_TAG STR {yy.commit('','',yy.commitType.NORMAL,$3)}
|
||||
// | COMMIT COMMIT_MSG STR {yy.commit($3,'',yy.commitType.NORMAL,'')}
|
||||
// | COMMIT COMMIT_TAG STR COMMIT_TYPE commitType {yy.commit('','',$5,$3)}
|
||||
// | COMMIT COMMIT_TYPE commitType COMMIT_TAG STR {yy.commit('','',$3,$5)}
|
||||
// | COMMIT COMMIT_ID STR COMMIT_TYPE commitType {yy.commit('',$3,$5,'')}
|
||||
// | COMMIT COMMIT_ID STR COMMIT_TAG STR {yy.commit('',$3,yy.commitType.NORMAL,$5)}
|
||||
// | COMMIT COMMIT_ID STR COMMIT_TYPE commitType COMMIT_TAG STR {yy.commit('',$3,$5,$7)}
|
||||
// | COMMIT COMMIT_ID STR COMMIT_TAG STR COMMIT_TYPE commitType {yy.commit('',$3,$7,$5)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_ID STR COMMIT_MSG STR commitTags {yy.commit($7,$5,$3,$8)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_ID STR commitTags COMMIT_MSG STR {yy.commit($8,$5,$3,$6)}
|
||||
| COMMIT COMMIT_TYPE commitType commitTags COMMIT_MSG STR COMMIT_ID STR {yy.commit($6,$8,$3,$4)}
|
||||
| COMMIT COMMIT_TYPE commitType commitTags COMMIT_ID STR COMMIT_MSG STR {yy.commit($8,$6,$3,$4)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_MSG STR COMMIT_ID STR commitTags {yy.commit($5,$7,$3,$8)}
|
||||
| COMMIT COMMIT_TYPE commitType COMMIT_MSG STR commitTags COMMIT_ID STR {yy.commit($5,$8,$3,$6)}
|
||||
;
|
||||
commit_arg
|
||||
: /* empty */ {$$ = ""}
|
||||
@@ -238,6 +221,12 @@ commitType
|
||||
| REVERSE { $$=yy.commitType.REVERSE;}
|
||||
| HIGHLIGHT { $$=yy.commitType.HIGHLIGHT;}
|
||||
;
|
||||
commitTags
|
||||
: COMMIT_TAG STR {$$=[$2]}
|
||||
| COMMIT_TAG EMPTYSTR {$$=['']}
|
||||
| commitTags COMMIT_TAG STR {$commitTags.push($3); $$=$commitTags;}
|
||||
| commitTags COMMIT_TAG EMPTYSTR {$commitTags.push(''); $$=$commitTags;}
|
||||
;
|
||||
|
||||
ref
|
||||
: ID
|
||||
|
||||
@@ -198,9 +198,6 @@ function getClassesFromDbInfo(dbInfoItem) {
|
||||
* Get classes from the db for the info item.
|
||||
* If there aren't any or if dbInfoItem isn't defined, return an empty string.
|
||||
* Else create 1 string from the list of classes found
|
||||
*
|
||||
* @param {undefined | null | object} dbInfoItem
|
||||
* @returns {string}
|
||||
*/
|
||||
function getStylesFromDbInfo(dbInfoItem) {
|
||||
if (dbInfoItem === undefined || dbInfoItem === null) {
|
||||
|
||||
@@ -37,6 +37,8 @@ To add an integration to this list, see the [Integrations - create page](./integ
|
||||
- [CloudScript.io Mermaid Addon](https://marketplace.atlassian.com/apps/1219878/cloudscript-io-mermaid-addon?hosting=cloud&tab=overview)
|
||||
- [Azure Devops](https://learn.microsoft.com/en-us/azure/devops/project/wiki/markdown-guidance?view=azure-devops#add-mermaid-diagrams-to-a-wiki-page) ✅
|
||||
- [Deepdwn](https://billiam.itch.io/deepdwn) ✅
|
||||
- [Doctave](https://www.doctave.com/) ✅
|
||||
- [Mermaid in Markdown code blocks](https://docs.doctave.com/components/mermaid) ✅
|
||||
- [GitBook](https://gitbook.com)
|
||||
- [Mermaid Plugin](https://github.com/JozoVilcek/gitbook-plugin-mermaid)
|
||||
- [Mermaid plugin for GitBook](https://github.com/wwformat/gitbook-plugin-mermaid-pdf)
|
||||
@@ -201,6 +203,7 @@ Communication tools and platforms
|
||||
- [gatsby-remark-mermaid](https://github.com/remcohaszing/gatsby-remark-mermaid)
|
||||
- [JSDoc](https://jsdoc.app/)
|
||||
- [jsdoc-mermaid](https://github.com/Jellyvision/jsdoc-mermaid)
|
||||
- [Madness](https://madness.dannyb.co/)
|
||||
- [mdBook](https://rust-lang.github.io/mdBook/index.html)
|
||||
- [mdbook-mermaid](https://github.com/badboy/mdbook-mermaid)
|
||||
- [MkDocs](https://www.mkdocs.org)
|
||||
|
||||
@@ -100,7 +100,7 @@ Cardinality is a property that describes how many elements of another entity can
|
||||
| 1+ | 1+ | One or more |
|
||||
| zero or more | zero or more | Zero or more |
|
||||
| zero or many | zero or many | Zero or more |
|
||||
| many(0) | many(1) | Zero or more |
|
||||
| many(0) | many(0) | Zero or more |
|
||||
| 0+ | 0+ | Zero or more |
|
||||
| only one | only one | Exactly one |
|
||||
| 1 | 1 | Exactly one |
|
||||
|
||||
@@ -6,7 +6,7 @@ A packet diagram is a visual representation used to illustrate the structure and
|
||||
|
||||
## Usage
|
||||
|
||||
This diagram type is particularly useful for network engineers, educators, and students who require a clear and concise way to represent the structure of network packets.
|
||||
This diagram type is particularly useful for developers, network engineers, educators, and students who require a clear and concise way to represent the structure of network packets.
|
||||
|
||||
## Syntax
|
||||
|
||||
|
||||
@@ -288,7 +288,7 @@ 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:
|
||||
|
||||
```
|
||||
```txt
|
||||
classDef movement font-style:italic;
|
||||
```
|
||||
|
||||
@@ -301,7 +301,7 @@ 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:
|
||||
|
||||
```
|
||||
```txt
|
||||
classDef badBadEvent fill:#f00,color:white,font-weight:bold,stroke-width:2px,stroke:yellow
|
||||
```
|
||||
|
||||
|
||||
@@ -49,8 +49,8 @@ async function addHtmlSpan(element, node, width, classes, addBackground = false)
|
||||
bbox = div.node().getBoundingClientRect();
|
||||
}
|
||||
|
||||
fo.style('width', bbox.width);
|
||||
fo.style('height', bbox.height);
|
||||
// fo.style('width', bbox.width);
|
||||
// fo.style('height', bbox.height);
|
||||
|
||||
return fo.node();
|
||||
}
|
||||
@@ -159,7 +159,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) {
|
||||
@@ -216,28 +216,61 @@ export const createText = async (
|
||||
|
||||
const htmlText = markdownToHTML(text, config);
|
||||
const decodedReplacedText = replaceIconSubstring(decodeEntities(htmlText));
|
||||
|
||||
//for Katex the text could contain escaped characters, \\relax that should be transformed to \relax
|
||||
const inputForKatex = text.replace(/\\\\/g, '\\');
|
||||
|
||||
const node = {
|
||||
isNode,
|
||||
label: decodedReplacedText,
|
||||
label: hasKatex(text) ? inputForKatex : decodedReplacedText,
|
||||
labelStyle: style.replace('fill:', 'color:'),
|
||||
};
|
||||
const vertexNode = await addHtmlSpan(el, node, width, classes, addSvgBackground);
|
||||
return vertexNode;
|
||||
} else {
|
||||
const structuredText = markdownToLines(text.replace('<br>', '<br/>'), config);
|
||||
//sometimes the user might add br tags with 1 or more spaces in between, so we need to replace them with <br/>
|
||||
const sanitizeBR = text.replace(/<br\s*\/?>/g, '<br/>');
|
||||
const structuredText = markdownToLines(sanitizeBR.replace('<br>', '<br/>'), config);
|
||||
const svgLabel = createFormattedText(
|
||||
width,
|
||||
el,
|
||||
structuredText,
|
||||
text ? addSvgBackground : false
|
||||
);
|
||||
if (isNode) {
|
||||
if (/stroke:/.exec(style)) {
|
||||
style = style.replace('stroke:', 'lineColor:');
|
||||
}
|
||||
select(svgLabel)
|
||||
.select('text')
|
||||
.attr('style', style.replace(/color:/g, 'fill:'));
|
||||
|
||||
const nodeLabelTextStyle = style
|
||||
.replace(/stroke:[^;]+;?/g, '')
|
||||
.replace(/stroke-width:[^;]+;?/g, '')
|
||||
.replace(/fill:[^;]+;?/g, '')
|
||||
.replace(/color:/g, 'fill:');
|
||||
select(svgLabel).attr('style', nodeLabelTextStyle);
|
||||
// svgLabel.setAttribute('style', style);
|
||||
} else {
|
||||
//On style, assume `stroke`, `stroke-width` are used for edge path, so remove them
|
||||
// remove `fill`
|
||||
// use `background` as `fill` for label rect,
|
||||
|
||||
const edgeLabelRectStyle = style
|
||||
.replace(/stroke:[^;]+;?/g, '')
|
||||
.replace(/stroke-width:[^;]+;?/g, '')
|
||||
.replace(/fill:[^;]+;?/g, '')
|
||||
.replace(/background:/g, 'fill:');
|
||||
select(svgLabel)
|
||||
.select('rect')
|
||||
.attr('style', edgeLabelRectStyle.replace(/background:/g, 'fill:'));
|
||||
|
||||
// for text, update fill color with `color`
|
||||
const edgeLabelTextStyle = style
|
||||
.replace(/stroke:[^;]+;?/g, '')
|
||||
.replace(/stroke-width:[^;]+;?/g, '')
|
||||
.replace(/fill:[^;]+;?/g, '')
|
||||
.replace(/color:/g, 'fill:');
|
||||
select(svgLabel).select('text').attr('style', edgeLabelTextStyle);
|
||||
}
|
||||
return svgLabel;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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';
|
||||
@@ -9,8 +9,10 @@ import type { MermaidConfig } from '../config.type.js';
|
||||
* @returns processed markdown
|
||||
*/
|
||||
function preprocessMarkdown(markdown: string, { markdownAutoWrap }: MermaidConfig): string {
|
||||
//Replace <br/>with \n
|
||||
const withoutBR = markdown.replace(/<br\/>/g, '\n');
|
||||
// Replace multiple newlines with a single newline
|
||||
const withoutMultipleNewlines = markdown.replace(/\n{2,}/g, '\n');
|
||||
const withoutMultipleNewlines = withoutBR.replace(/\n{2,}/g, '\n');
|
||||
// Remove extra spaces at the beginning of each line
|
||||
const withoutExtraSpaces = dedent(withoutMultipleNewlines);
|
||||
if (markdownAutoWrap === false) {
|
||||
@@ -24,13 +26,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,18 +44,22 @@ 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);
|
||||
});
|
||||
} else if (node.type === 'html') {
|
||||
lines[currentLine].push({ content: node.text, type: 'normal' });
|
||||
}
|
||||
}
|
||||
|
||||
children.forEach((treeNode) => {
|
||||
nodes.forEach((treeNode) => {
|
||||
if (treeNode.type === 'paragraph') {
|
||||
treeNode.children.forEach((contentNode) => {
|
||||
processNode(contentNode);
|
||||
treeNode.tokens?.forEach((contentNode) => {
|
||||
processNode(contentNode as MarkedToken);
|
||||
});
|
||||
} else if (treeNode.type === 'html') {
|
||||
lines[currentLine].push({ content: treeNode.text, type: 'normal' });
|
||||
}
|
||||
});
|
||||
|
||||
@@ -61,25 +67,27 @@ 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>`;
|
||||
} else if (node.type === 'space') {
|
||||
return '';
|
||||
} else if (node.type === 'html') {
|
||||
return `${node.value}`;
|
||||
return `${node.text}`;
|
||||
}
|
||||
return `Unsupported markdown: ${node.type}`;
|
||||
}
|
||||
|
||||
return children.map(output).join('');
|
||||
return nodes.map(output).join('');
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit
|
||||
graph
|
||||
);
|
||||
log.info(findNonClusterChild(node.id, graph));
|
||||
clusterDb[node.id] = { id: findNonClusterChild(node.id, graph), node };
|
||||
clusterDb.set(node.id, { id: findNonClusterChild(node.id, graph), node });
|
||||
// insertCluster(clusters, graph.node(v));
|
||||
} else {
|
||||
log.trace('Node - the non recursive path XAX', v, node.id, node);
|
||||
@@ -138,7 +138,16 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit
|
||||
log.info('Edge ' + e.v + ' -> ' + e.w + ': ', e, ' ', JSON.stringify(graph.edge(e)));
|
||||
|
||||
// Check if link is either from or to a cluster
|
||||
log.info('Fix', clusterDb, 'ids:', e.v, e.w, 'Translating: ', clusterDb[e.v], clusterDb[e.w]);
|
||||
log.info(
|
||||
'Fix',
|
||||
clusterDb,
|
||||
'ids:',
|
||||
e.v,
|
||||
e.w,
|
||||
'Translating: ',
|
||||
clusterDb.get(e.v),
|
||||
clusterDb.get(e.w)
|
||||
);
|
||||
await insertEdgeLabel(edgeLabels, edge);
|
||||
});
|
||||
|
||||
@@ -147,20 +156,6 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit
|
||||
|
||||
await processEdges();
|
||||
|
||||
// // Insert labels, this will insert them into the dom so that the width can be calculated
|
||||
// // Also figure out which edges point to/from clusters and adjust them accordingly
|
||||
// // Edges from/to clusters really points to the first child in the cluster.
|
||||
// // TODO: pick optimal child in the cluster to us as link anchor
|
||||
// await graph.edges().forEach(async function (e) {
|
||||
// const edge = graph.edge(e.v, e.w, e.name);
|
||||
// log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(e));
|
||||
// log.info('Edge ' + e.v + ' -> ' + e.w + ': ', e, ' ', JSON.stringify(graph.edge(e)));
|
||||
|
||||
// // Check if link is either from or to a cluster
|
||||
// log.info('Fix', clusterDb, 'ids:', e.v, e.w, 'Translating: ', clusterDb[e.v], clusterDb[e.w]);
|
||||
// await insertEdgeLabel(edgeLabels, edge);
|
||||
// });
|
||||
|
||||
log.info('Graph before layout:', JSON.stringify(graphlibJson.write(graph)));
|
||||
|
||||
log.info('############################################# XXX');
|
||||
@@ -198,7 +193,7 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit
|
||||
node.y,
|
||||
graph.parent(v)
|
||||
);
|
||||
clusterDb[node.id].node = node;
|
||||
clusterDb.get(node.id).node = node;
|
||||
positionNode(node);
|
||||
} else {
|
||||
// A tainted cluster node
|
||||
@@ -222,7 +217,7 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit
|
||||
await insertCluster(clusters, node);
|
||||
|
||||
// A cluster in the non-recursive way
|
||||
clusterDb[node.id].node = node;
|
||||
clusterDb.get(node.id).node = node;
|
||||
} else {
|
||||
// Regular node
|
||||
const parent = graph.node(node.parentId);
|
||||
@@ -255,7 +250,6 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit
|
||||
const edge = graph.edge(e);
|
||||
log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(edge), edge);
|
||||
|
||||
// OBS HERE
|
||||
edge.points.forEach((point) => (point.y += subGraphTitleTotalMargin / 2));
|
||||
const startNode = graph.node(e.v);
|
||||
var endNode = graph.node(e.w);
|
||||
@@ -273,17 +267,8 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit
|
||||
log.warn('Returning from recursive render XAX', elem, diff);
|
||||
return { elem, diff };
|
||||
};
|
||||
/**
|
||||
* ###############################################################
|
||||
* Render the graph
|
||||
* ###############################################################
|
||||
* @param data4Layout
|
||||
* @param svg
|
||||
* @param element
|
||||
*/
|
||||
|
||||
export const render = async (data4Layout, svg, element) => {
|
||||
// Create the input mermaid.graph
|
||||
// console.log('XYZ data4Layout', data4Layout);
|
||||
const graph = new graphlib.Graph({
|
||||
multigraph: true,
|
||||
compound: true,
|
||||
@@ -305,15 +290,12 @@ export const render = async (data4Layout, svg, element) => {
|
||||
return {};
|
||||
});
|
||||
|
||||
// Org
|
||||
|
||||
insertMarkers(element, data4Layout.markers, data4Layout.type, data4Layout.diagramId);
|
||||
clearNodes();
|
||||
clearEdges();
|
||||
clearClusters();
|
||||
clearGraphlib();
|
||||
|
||||
// Add the nodes and edges to the graph
|
||||
data4Layout.nodes.forEach((node) => {
|
||||
graph.setNode(node.id, { ...node });
|
||||
if (node.parentId) {
|
||||
|
||||
@@ -3,39 +3,40 @@ import { log } from '$root/logger.js';
|
||||
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
|
||||
import * as graphlibJson from 'dagre-d3-es/src/graphlib/json.js';
|
||||
|
||||
export let clusterDb = {};
|
||||
let descendants = {};
|
||||
let parents = {};
|
||||
export let clusterDb = new Map();
|
||||
let descendants = new Map();
|
||||
let parents = new Map();
|
||||
|
||||
export const clear = () => {
|
||||
descendants = {};
|
||||
parents = {};
|
||||
clusterDb = {};
|
||||
descendants.clear();
|
||||
parents.clear();
|
||||
clusterDb.clear();
|
||||
};
|
||||
|
||||
const isDescendant = (id, ancestorId) => {
|
||||
log.trace('In isDescendant', ancestorId, ' ', id, ' = ', descendants[ancestorId].includes(id));
|
||||
return descendants[ancestorId].includes(id);
|
||||
const ancestorDescendants = descendants.get(ancestorId) || [];
|
||||
log.trace('In isDescendant', ancestorId, ' ', id, ' = ', ancestorDescendants.includes(id));
|
||||
return ancestorDescendants.includes(id);
|
||||
};
|
||||
|
||||
const edgeInCluster = (edge, clusterId) => {
|
||||
log.info('Descendants of ', clusterId, ' is ', descendants[clusterId]);
|
||||
const clusterDescendants = descendants.get(clusterId) || [];
|
||||
log.info('Descendants of ', clusterId, ' is ', clusterDescendants);
|
||||
log.info('Edge is ', edge);
|
||||
// Edges to/from the cluster is not in the cluster, they are in the parent
|
||||
if (edge.v === clusterId || edge.w === clusterId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!descendants[clusterId]) {
|
||||
if (!clusterDescendants) {
|
||||
log.debug('Tilt, ', clusterId, ',not in descendants');
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
descendants[clusterId].includes(edge.v) ||
|
||||
clusterDescendants.includes(edge.v) ||
|
||||
isDescendant(edge.v, clusterId) ||
|
||||
isDescendant(edge.w, clusterId) ||
|
||||
descendants[clusterId].includes(edge.w)
|
||||
clusterDescendants.includes(edge.w)
|
||||
);
|
||||
};
|
||||
|
||||
@@ -51,7 +52,6 @@ const copy = (clusterId, graph, newGraph, rootId) => {
|
||||
);
|
||||
const nodes = graph.children(clusterId) || [];
|
||||
|
||||
// Include cluster node if it is not the root
|
||||
if (clusterId !== rootId) {
|
||||
nodes.push(clusterId);
|
||||
}
|
||||
@@ -63,7 +63,7 @@ const copy = (clusterId, graph, newGraph, rootId) => {
|
||||
copy(node, graph, newGraph, rootId);
|
||||
} else {
|
||||
const data = graph.node(node);
|
||||
log.info('cp ', node, ' to ', rootId, ' with parent ', clusterId); //,node, data, ' parent is ', clusterId);
|
||||
log.info('cp ', node, ' to ', rootId, ' with parent ', clusterId);
|
||||
newGraph.setNode(node, data);
|
||||
if (rootId !== graph.parent(node)) {
|
||||
log.warn('Setting parent', node, graph.parent(node));
|
||||
@@ -91,7 +91,6 @@ const copy = (clusterId, graph, newGraph, rootId) => {
|
||||
const data = graph.edge(edge.v, edge.w, edge.name);
|
||||
log.info('Edge data', data, rootId);
|
||||
try {
|
||||
// Do not copy edges in and out of the root cluster, they belong to the parent graph
|
||||
if (edgeInCluster(edge, rootId)) {
|
||||
log.info('Copying as ', edge.v, edge.w, data, edge.name);
|
||||
newGraph.setEdge(edge.v, edge.w, data, edge.name);
|
||||
@@ -117,25 +116,19 @@ const copy = (clusterId, graph, newGraph, rootId) => {
|
||||
graph.removeNode(node);
|
||||
});
|
||||
};
|
||||
|
||||
export const extractDescendants = (id, graph) => {
|
||||
// log.debug('Extracting ', id);
|
||||
const children = graph.children(id);
|
||||
let res = [...children];
|
||||
|
||||
for (const child of children) {
|
||||
parents[child] = id;
|
||||
parents.set(child, id);
|
||||
res = [...res, ...extractDescendants(child, graph)];
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
/**
|
||||
* Validates the graph, checking that all parent child relation points to existing nodes and that
|
||||
* edges between nodes also ia correct. When not correct the function logs the discrepancies.
|
||||
*
|
||||
* @param graph
|
||||
*/
|
||||
export const validate = (graph) => {
|
||||
const edges = graph.edges();
|
||||
log.trace('Edges: ', edges);
|
||||
@@ -168,13 +161,6 @@ const findCommonEdges = (graph, id1, id2) => {
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Finds a child that is not a cluster. When faking an edge between a node and a cluster.
|
||||
*
|
||||
* @param id
|
||||
* @param {any} graph
|
||||
* @param {string} clusterId
|
||||
*/
|
||||
export const findNonClusterChild = (id, graph, clusterId) => {
|
||||
const children = graph.children(id);
|
||||
log.trace('Searching children of id ', id, children);
|
||||
@@ -185,19 +171,10 @@ export const findNonClusterChild = (id, graph, clusterId) => {
|
||||
for (const child of children) {
|
||||
const _id = findNonClusterChild(child, graph, clusterId);
|
||||
|
||||
// Edge chase where the cluster has an edge to a node and the selected
|
||||
// child has a link to the same node
|
||||
const commonEdges = findCommonEdges(graph, clusterId, _id);
|
||||
|
||||
if (_id) {
|
||||
if (commonEdges.length > 0) {
|
||||
// console.log(
|
||||
// '\x1B[44;93;4m abc24 The replacement also has an edge',
|
||||
// clusterId,
|
||||
// ' => ',
|
||||
// _id,
|
||||
// graph.edges()
|
||||
// );
|
||||
reserve = _id;
|
||||
} else {
|
||||
return _id;
|
||||
@@ -208,17 +185,15 @@ export const findNonClusterChild = (id, graph, clusterId) => {
|
||||
};
|
||||
|
||||
const getAnchorId = (id) => {
|
||||
if (!clusterDb[id]) {
|
||||
if (!clusterDb.has(id)) {
|
||||
return id;
|
||||
}
|
||||
// If the cluster has no external connections
|
||||
if (!clusterDb[id].externalConnections) {
|
||||
if (!clusterDb.get(id).externalConnections) {
|
||||
return id;
|
||||
}
|
||||
|
||||
// Return the replacement node
|
||||
if (clusterDb[id]) {
|
||||
return clusterDb[id].id;
|
||||
if (clusterDb.has(id)) {
|
||||
return clusterDb.get(id).id;
|
||||
}
|
||||
return id;
|
||||
};
|
||||
@@ -230,8 +205,7 @@ export const adjustClustersAndEdges = (graph, depth) => {
|
||||
} else {
|
||||
log.debug('Opting in, graph ');
|
||||
}
|
||||
// Go through the nodes and for each cluster found, save a replacement node, this can be used when
|
||||
// faking a link to a cluster
|
||||
|
||||
graph.nodes().forEach(function (id) {
|
||||
const children = graph.children(id);
|
||||
if (children.length > 0) {
|
||||
@@ -241,34 +215,24 @@ export const adjustClustersAndEdges = (graph, depth) => {
|
||||
' Replacement id in edges: ',
|
||||
findNonClusterChild(id, graph, id)
|
||||
);
|
||||
descendants[id] = extractDescendants(id, graph);
|
||||
clusterDb[id] = { id: findNonClusterChild(id, graph, id), clusterData: graph.node(id) };
|
||||
descendants.set(id, extractDescendants(id, graph));
|
||||
clusterDb.set(id, { id: findNonClusterChild(id, graph, id), clusterData: graph.node(id) });
|
||||
}
|
||||
});
|
||||
|
||||
// Check incoming and outgoing edges for each cluster
|
||||
graph.nodes().forEach(function (id) {
|
||||
const children = graph.children(id);
|
||||
const edges = graph.edges();
|
||||
if (children.length > 0) {
|
||||
log.debug('Cluster identified', id, descendants);
|
||||
edges.forEach((edge) => {
|
||||
// log.debug('Edge, descendants: ', edge, descendants[id]);
|
||||
|
||||
// Check if any edge leaves the cluster (not the actual cluster, that's a link from the box)
|
||||
if (edge.v !== id && edge.w !== id) {
|
||||
// Any edge where either the one of the nodes is descending to the cluster but not the other
|
||||
// if (descendants[id].indexOf(edge.v) < 0 && descendants[id].indexOf(edge.w) < 0) {
|
||||
|
||||
const d1 = isDescendant(edge.v, id);
|
||||
const d2 = isDescendant(edge.w, id);
|
||||
|
||||
// d1 xor d2 - if either d1 is true and d2 is false or the other way around
|
||||
if (d1 ^ d2) {
|
||||
log.warn('Edge: ', edge, ' leaves cluster ', id);
|
||||
log.warn('Descendants of XXX ', id, ': ', descendants[id]);
|
||||
clusterDb[id].externalConnections = true;
|
||||
}
|
||||
log.warn('Descendants of XXX ', id, ': ', descendants.get(id));
|
||||
clusterDb.get(id).externalConnections = true;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -276,18 +240,15 @@ export const adjustClustersAndEdges = (graph, depth) => {
|
||||
}
|
||||
});
|
||||
|
||||
for (let id of Object.keys(clusterDb)) {
|
||||
const nonClusterChild = clusterDb[id].id;
|
||||
for (let id of clusterDb.keys()) {
|
||||
const nonClusterChild = clusterDb.get(id).id;
|
||||
const parent = graph.parent(nonClusterChild);
|
||||
|
||||
// Change replacement node of id to parent of current replacement node if valid
|
||||
if (parent !== id && clusterDb[parent] && !clusterDb[parent].externalConnections) {
|
||||
clusterDb[id].id = parent;
|
||||
if (parent !== id && clusterDb.has(parent) && !clusterDb.get(parent).externalConnections) {
|
||||
clusterDb.get(id).id = parent;
|
||||
}
|
||||
}
|
||||
|
||||
// For clusters with incoming and/or outgoing edges translate those edges to a real node
|
||||
// in the cluster in order to fake the edge
|
||||
graph.edges().forEach(function (e) {
|
||||
const edge = graph.edge(e);
|
||||
log.warn('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(e));
|
||||
@@ -295,7 +256,6 @@ export const adjustClustersAndEdges = (graph, depth) => {
|
||||
|
||||
let v = e.v;
|
||||
let w = e.w;
|
||||
// Check if link is either from or to a cluster
|
||||
log.warn(
|
||||
'Fix XXX',
|
||||
clusterDb,
|
||||
@@ -303,14 +263,13 @@ export const adjustClustersAndEdges = (graph, depth) => {
|
||||
e.v,
|
||||
e.w,
|
||||
'Translating: ',
|
||||
clusterDb[e.v],
|
||||
clusterDb.get(e.v),
|
||||
' --- ',
|
||||
clusterDb[e.w]
|
||||
clusterDb.get(e.w)
|
||||
);
|
||||
if (clusterDb[e.v] && clusterDb[e.w] && clusterDb[e.v] === clusterDb[e.w]) {
|
||||
// cspell:ignore trixing
|
||||
log.warn('Fixing and trixing link to self - removing XXX', e.v, e.w, e.name);
|
||||
log.warn('Fixing and trixing - removing XXX', e.v, e.w, e.name);
|
||||
if (clusterDb.get(e.v) && clusterDb.get(e.w) && clusterDb.get(e.v) === clusterDb.get(e.w)) {
|
||||
log.warn('Fixing and trying link to self - removing XXX', e.v, e.w, e.name);
|
||||
log.warn('Fixing and trying - removing XXX', e.v, e.w, e.name);
|
||||
v = getAnchorId(e.v);
|
||||
w = getAnchorId(e.w);
|
||||
graph.removeEdge(e.v, e.w, e.name);
|
||||
@@ -320,7 +279,7 @@ export const adjustClustersAndEdges = (graph, depth) => {
|
||||
domId: specialId1,
|
||||
id: specialId1,
|
||||
labelStyle: '',
|
||||
label: edge.label,
|
||||
label: '',
|
||||
padding: 0,
|
||||
shape: 'labelRect',
|
||||
style: '',
|
||||
@@ -342,27 +301,29 @@ export const adjustClustersAndEdges = (graph, depth) => {
|
||||
const edge2 = structuredClone(edge);
|
||||
edge1.label = '';
|
||||
edge1.arrowTypeEnd = 'none';
|
||||
edge1.id = e.name + '-cyclic-special-1';
|
||||
edgeMid.arrowTypeEnd = 'none';
|
||||
edgeMid.id = e.name + '-cyclic-special-mid';
|
||||
edge2.label = '';
|
||||
edge1.fromCluster = e.v;
|
||||
edge2.toCluster = e.v;
|
||||
|
||||
graph.setEdge(v, specialId1, edge1, e.name + '-cyclic-special');
|
||||
graph.setEdge(specialId1, specialId2, edgeMid, e.name + '-cyclic-special');
|
||||
graph.setEdge(specialId2, w, edge2, e.name + '-cyclic-special');
|
||||
} else if (clusterDb[e.v] || clusterDb[e.w]) {
|
||||
log.warn('Fixing and trixing - removing XXX', e.v, e.w, e.name);
|
||||
edge2.id = e.name + '-cyclic-special-2';
|
||||
graph.setEdge(v, specialId1, edge1, e.name + '-cyclic-special-0');
|
||||
graph.setEdge(specialId1, specialId2, edgeMid, e.name + '-cyclic-special-1');
|
||||
graph.setEdge(specialId2, w, edge2, e.name + '-cyclic-special-2');
|
||||
} else if (clusterDb.get(e.v) || clusterDb.get(e.w)) {
|
||||
log.warn('Fixing and trying - removing XXX', e.v, e.w, e.name);
|
||||
v = getAnchorId(e.v);
|
||||
w = getAnchorId(e.w);
|
||||
graph.removeEdge(e.v, e.w, e.name);
|
||||
if (v !== e.v) {
|
||||
const parent = graph.parent(v);
|
||||
clusterDb[parent].externalConnections = true;
|
||||
clusterDb.get(parent).externalConnections = true;
|
||||
edge.fromCluster = e.v;
|
||||
}
|
||||
if (w !== e.w) {
|
||||
const parent = graph.parent(w);
|
||||
clusterDb[parent].externalConnections = true;
|
||||
clusterDb.get(parent).externalConnections = true;
|
||||
edge.toCluster = e.w;
|
||||
}
|
||||
log.warn('Fix Replacing with XXX', v, w, e.name);
|
||||
@@ -375,7 +336,7 @@ export const adjustClustersAndEdges = (graph, depth) => {
|
||||
log.trace(clusterDb);
|
||||
|
||||
// Remove references to extracted cluster
|
||||
// graph.edges().forEach(edge => {
|
||||
// graph.edges().forEach((edge) => {
|
||||
// if (isDescendant(edge.v, clusterId) || isDescendant(edge.w, clusterId)) {
|
||||
// graph.removeEdge(edge);
|
||||
// }
|
||||
@@ -388,9 +349,6 @@ export const extractor = (graph, depth) => {
|
||||
log.error('Bailing out');
|
||||
return;
|
||||
}
|
||||
// For clusters without incoming and/or outgoing edges, create a new cluster-node
|
||||
// containing the nodes and edges in the custer in a new graph
|
||||
// for (let i = 0;)
|
||||
let nodes = graph.nodes();
|
||||
let hasChildren = false;
|
||||
for (const node of nodes) {
|
||||
@@ -402,30 +360,23 @@ export const extractor = (graph, depth) => {
|
||||
log.debug('Done, no node has children', graph.nodes());
|
||||
return;
|
||||
}
|
||||
// const clusters = Object.keys(clusterDb);
|
||||
// clusters.forEach(clusterId => {
|
||||
log.debug('Nodes = ', nodes, depth);
|
||||
for (const node of nodes) {
|
||||
log.debug(
|
||||
'Extracting node',
|
||||
node,
|
||||
clusterDb,
|
||||
clusterDb[node] && !clusterDb[node].externalConnections,
|
||||
clusterDb.has(node) && !clusterDb.get(node).externalConnections,
|
||||
!graph.parent(node),
|
||||
graph.node(node),
|
||||
graph.children('D'),
|
||||
' Depth ',
|
||||
depth
|
||||
);
|
||||
// Note that the node might have been removed after the Object.keys call so better check
|
||||
// that it still is in the game
|
||||
if (!clusterDb[node]) {
|
||||
// Skip if the node is not a cluster
|
||||
if (!clusterDb.has(node)) {
|
||||
log.debug('Not a cluster', node, depth);
|
||||
// break;
|
||||
} else if (
|
||||
!clusterDb[node].externalConnections &&
|
||||
// !graph.parent(node) &&
|
||||
!clusterDb.get(node).externalConnections &&
|
||||
graph.children(node) &&
|
||||
graph.children(node).length > 0
|
||||
) {
|
||||
@@ -437,9 +388,9 @@ export const extractor = (graph, depth) => {
|
||||
|
||||
const graphSettings = graph.graph();
|
||||
let dir = graphSettings.rankdir === 'TB' ? 'LR' : 'TB';
|
||||
if (clusterDb[node]?.clusterData?.dir) {
|
||||
dir = clusterDb[node].clusterData.dir;
|
||||
log.warn('Fixing dir', clusterDb[node].clusterData.dir, dir);
|
||||
if (clusterDb.get(node)?.clusterData?.dir) {
|
||||
dir = clusterDb.get(node).clusterData.dir;
|
||||
log.warn('Fixing dir', clusterDb.get(node).clusterData.dir, dir);
|
||||
}
|
||||
|
||||
const clusterGraph = new graphlib.Graph({
|
||||
@@ -447,7 +398,7 @@ export const extractor = (graph, depth) => {
|
||||
compound: true,
|
||||
})
|
||||
.setGraph({
|
||||
rankdir: dir, // Todo: set proper spacing
|
||||
rankdir: dir,
|
||||
nodesep: 50,
|
||||
ranksep: 50,
|
||||
marginx: 8,
|
||||
@@ -462,8 +413,8 @@ export const extractor = (graph, depth) => {
|
||||
graph.setNode(node, {
|
||||
clusterNode: true,
|
||||
id: node,
|
||||
clusterData: clusterDb[node].clusterData,
|
||||
label: clusterDb[node].label,
|
||||
clusterData: clusterDb.get(node).clusterData,
|
||||
label: clusterDb.get(node).label,
|
||||
graph: clusterGraph,
|
||||
});
|
||||
log.warn('New graph after copy node: (', node, ')', graphlibJson.write(clusterGraph));
|
||||
@@ -473,7 +424,7 @@ export const extractor = (graph, depth) => {
|
||||
'Cluster ** ',
|
||||
node,
|
||||
' **not meeting the criteria !externalConnections:',
|
||||
!clusterDb[node].externalConnections,
|
||||
!clusterDb.get(node).externalConnections,
|
||||
' no parent: ',
|
||||
!graph.parent(node),
|
||||
' children ',
|
||||
@@ -500,7 +451,7 @@ const sorter = (graph, nodes) => {
|
||||
if (nodes.length === 0) {
|
||||
return [];
|
||||
}
|
||||
let result = Object.assign(nodes);
|
||||
let result = Object.assign([], nodes);
|
||||
nodes.forEach((node) => {
|
||||
const children = graph.children(node);
|
||||
const sorted = sorter(graph, children);
|
||||
|
||||
@@ -154,7 +154,6 @@ export const positionEdgeLabel = (edge, paths) => {
|
||||
let x = edge.x;
|
||||
let y = edge.y;
|
||||
if (path) {
|
||||
// // debugger;
|
||||
const pos = utils.calcLabelPosition(path);
|
||||
log.debug(
|
||||
'Moving label ' + edge.label + ' from (',
|
||||
@@ -175,13 +174,11 @@ export const positionEdgeLabel = (edge, paths) => {
|
||||
el.attr('transform', `translate(${x}, ${y + subGraphTitleTotalMargin / 2})`);
|
||||
}
|
||||
|
||||
//let path = paths.updatedPath ? paths.updatedPath : paths.originalPath;
|
||||
if (edge.startLabelLeft) {
|
||||
const el = terminalLabels.get(edge.id).startLeft;
|
||||
let x = edge.x;
|
||||
let y = edge.y;
|
||||
if (path) {
|
||||
// debugger;
|
||||
const pos = utils.calcTerminalLabelPosition(edge.arrowTypeStart ? 10 : 0, 'start_left', path);
|
||||
x = pos.x;
|
||||
y = pos.y;
|
||||
@@ -193,7 +190,6 @@ export const positionEdgeLabel = (edge, paths) => {
|
||||
let x = edge.x;
|
||||
let y = edge.y;
|
||||
if (path) {
|
||||
// debugger;
|
||||
const pos = utils.calcTerminalLabelPosition(
|
||||
edge.arrowTypeStart ? 10 : 0,
|
||||
'start_right',
|
||||
@@ -209,7 +205,6 @@ export const positionEdgeLabel = (edge, paths) => {
|
||||
let x = edge.x;
|
||||
let y = edge.y;
|
||||
if (path) {
|
||||
// debugger;
|
||||
const pos = utils.calcTerminalLabelPosition(edge.arrowTypeEnd ? 10 : 0, 'end_left', path);
|
||||
x = pos.x;
|
||||
y = pos.y;
|
||||
@@ -275,21 +270,18 @@ export const intersection = (node, outsidePoint, insidePoint) => {
|
||||
res.y = outsidePoint.y;
|
||||
}
|
||||
|
||||
log.debug(`abc89 topp/bott calc, Q ${Q}, q ${q}, R ${R}, r ${r}`, res); // cspell: disable-line
|
||||
log.debug(`abc89 top/bottom calc, Q ${Q}, q ${q}, R ${R}, r ${r}`, res);
|
||||
|
||||
return res;
|
||||
} else {
|
||||
// Intersection onn sides of rect
|
||||
// Intersection on sides of rect
|
||||
if (insidePoint.x < outsidePoint.x) {
|
||||
r = outsidePoint.x - w - x;
|
||||
} else {
|
||||
r = x - w - outsidePoint.x;
|
||||
}
|
||||
let q = (Q * r) / R;
|
||||
// OK let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : insidePoint.x + dx - w;
|
||||
// OK let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : outsidePoint.x + r;
|
||||
let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : insidePoint.x - R + r;
|
||||
// let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : outsidePoint.x + r;
|
||||
let _y = insidePoint.y < outsidePoint.y ? insidePoint.y + q : insidePoint.y - q;
|
||||
log.debug(`sides calc abc89, Q ${Q}, q ${q}, R ${R}, r ${r}`, { _x, _y });
|
||||
if (r === 0) {
|
||||
@@ -306,49 +298,34 @@ export const intersection = (node, outsidePoint, insidePoint) => {
|
||||
return { x: _x, y: _y };
|
||||
}
|
||||
};
|
||||
/**
|
||||
* This function will page a path and node where the last point(s) in the path is inside the node
|
||||
* and return an update path ending by the border of the node.
|
||||
*
|
||||
* @param {Array} _points
|
||||
* @param {any} boundaryNode
|
||||
* @returns {Array} Points
|
||||
*/
|
||||
|
||||
const cutPathAtIntersect = (_points, boundaryNode) => {
|
||||
log.warn('abc88 cutPathAtIntersect', _points, boundaryNode);
|
||||
let points = [];
|
||||
let lastPointOutside = _points[0];
|
||||
let isInside = false;
|
||||
_points.forEach((point) => {
|
||||
// const node = clusterDb[edge.toCluster].node;
|
||||
log.info('abc88 checking point', point, boundaryNode);
|
||||
|
||||
// check if point is inside the boundary rect
|
||||
if (!outsideNode(boundaryNode, point) && !isInside) {
|
||||
// First point inside the rect found
|
||||
// Calc the intersection coord between the point anf the last point outside the rect
|
||||
const inter = intersection(boundaryNode, lastPointOutside, point);
|
||||
log.debug('abc88 inside', point, lastPointOutside, inter);
|
||||
log.debug('abc88 intersection', inter, boundaryNode);
|
||||
|
||||
// // Check case where the intersection is the same as the last point
|
||||
let pointPresent = false;
|
||||
points.forEach((p) => {
|
||||
pointPresent = pointPresent || (p.x === inter.x && p.y === inter.y);
|
||||
});
|
||||
// // if (!pointPresent) {
|
||||
|
||||
if (!points.some((e) => e.x === inter.x && e.y === inter.y)) {
|
||||
points.push(inter);
|
||||
} else {
|
||||
log.warn('abc88 no intersect', inter, points);
|
||||
}
|
||||
// points.push(inter);
|
||||
isInside = true;
|
||||
} else {
|
||||
// Outside
|
||||
log.warn('abc88 outside', point, lastPointOutside);
|
||||
lastPointOutside = point;
|
||||
// points.push(point);
|
||||
if (!isInside) {
|
||||
points.push(point);
|
||||
}
|
||||
@@ -358,13 +335,6 @@ const cutPathAtIntersect = (_points, boundaryNode) => {
|
||||
return points;
|
||||
};
|
||||
|
||||
/**
|
||||
* Given an edge, this function will return the corner points of the edge. This is defined as:
|
||||
* one point that has a previous point and a next point such as the angle between the previous
|
||||
* point and the next point is 90 degrees. Meaning that the previous point has the same x coordinate
|
||||
* as the center point and at the same time the next point has the same y coordinate or vice versa.
|
||||
* @param points
|
||||
*/
|
||||
function extractCornerPoints(points) {
|
||||
const cornerPoints = [];
|
||||
const cornerPointPositions = [];
|
||||
@@ -401,11 +371,6 @@ const findAdjacentPoint = function (pointA, pointB, distance) {
|
||||
return { x: pointB.x - ratio * xDiff, y: pointB.y - ratio * yDiff };
|
||||
};
|
||||
|
||||
/**
|
||||
* Given an array of points, this function will return a new array of points where the corners have been removed and replaced with
|
||||
* adjacent points in each direction. SO a corder will be replaced with a point before and the point after the corner.
|
||||
*/
|
||||
|
||||
const fixCorners = function (lineData) {
|
||||
const { cornerPointPositions } = extractCornerPoints(lineData);
|
||||
const newLineData = [];
|
||||
@@ -415,7 +380,6 @@ const fixCorners = function (lineData) {
|
||||
const nextPoint = lineData[i + 1];
|
||||
const cornerPoint = lineData[i];
|
||||
|
||||
// Find a new point on the line point 5 points back and push it to the new array
|
||||
const newPrevPoint = findAdjacentPoint(prevPoint, cornerPoint, 5);
|
||||
const newNextPoint = findAdjacentPoint(nextPoint, cornerPoint, 5);
|
||||
|
||||
@@ -466,9 +430,7 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
||||
var head = endNode;
|
||||
|
||||
if (head.intersect && tail.intersect) {
|
||||
// log.info('abc88 InsertEdge: 0.5', edge.start, '-->', edge.end, JSON.stringify(points));
|
||||
points = points.slice(1, edge.points.length - 1);
|
||||
// log.info('abc88 InsertEdge APA12: 0.7', edge.start, '-->', edge.end, JSON.stringify(points));
|
||||
points.unshift(tail.intersect(points[0]));
|
||||
log.debug(
|
||||
'Last point APA12',
|
||||
@@ -481,59 +443,43 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
||||
);
|
||||
points.push(head.intersect(points[points.length - 1]));
|
||||
}
|
||||
// log.info('abc88 InsertEdge 2 SPLIT: ', points);
|
||||
if (edge.toCluster) {
|
||||
log.info('to cluster abc88', clusterDb[edge.toCluster]);
|
||||
points = cutPathAtIntersect(edge.points, clusterDb[edge.toCluster].node);
|
||||
log.info('to cluster abc88', clusterDb.get(edge.toCluster));
|
||||
points = cutPathAtIntersect(edge.points, clusterDb.get(edge.toCluster).node);
|
||||
|
||||
pointsHasChanged = true;
|
||||
}
|
||||
|
||||
if (edge.fromCluster) {
|
||||
log.debug('from cluster abc88', clusterDb[edge.fromCluster], JSON.stringify(points, null, 2));
|
||||
points = cutPathAtIntersect(points.reverse(), clusterDb[edge.fromCluster].node).reverse();
|
||||
// log.info('from cluster abc88 fixed', JSON.stringify(points, null, 2));
|
||||
log.debug(
|
||||
'from cluster abc88',
|
||||
clusterDb.get(edge.fromCluster),
|
||||
JSON.stringify(points, null, 2)
|
||||
);
|
||||
points = cutPathAtIntersect(points.reverse(), clusterDb.get(edge.fromCluster).node).reverse();
|
||||
|
||||
pointsHasChanged = true;
|
||||
}
|
||||
|
||||
// The data for our line
|
||||
let lineData = points.filter((p) => !Number.isNaN(p.y));
|
||||
// const { cornerPoints, cornerPointPositions } = extractCornerPoints(lineData);
|
||||
lineData = fixCorners(lineData);
|
||||
let lastPoint = lineData[lineData.length - 1];
|
||||
if (lineData.length > 1) {
|
||||
lastPoint = lineData[lineData.length - 1];
|
||||
const secondLastPoint = lineData[lineData.length - 2];
|
||||
// Calculate the mid point of the last two points
|
||||
const diffX = (lastPoint.x - secondLastPoint.x) / 2;
|
||||
const diffY = (lastPoint.y - secondLastPoint.y) / 2;
|
||||
const midPoint = { x: secondLastPoint.x + diffX, y: secondLastPoint.y + diffY };
|
||||
lineData.splice(-1, 0, midPoint);
|
||||
}
|
||||
// This is the accessor function we talked about above
|
||||
let curve = curveBasis;
|
||||
// curve = curveCardinal;
|
||||
// curve = curveLinear;
|
||||
// curve = curveNatural;
|
||||
// curve = curveCatmullRom.alpha(0.5);
|
||||
// curve = curveCatmullRom;
|
||||
// curve = curveCardinal.tension(0.7);
|
||||
// curve = curveMonotoneY;
|
||||
// let curve = interpolateToCurve([5], curveNatural, 0.01, 10);
|
||||
|
||||
// Currently only flowcharts get the curve from the settings, perhaps this should
|
||||
// be expanded to a common setting? Restricting it for now in order not to cause side-effects that
|
||||
// have not been thought through
|
||||
if (edge.curve) {
|
||||
curve = edge.curve;
|
||||
}
|
||||
|
||||
const { x, y } = getLineFunctionsWithOffset(edge);
|
||||
// const lineFunction = edge.curve ? line().x(x).y(y).curve(curve) : roundedCornersLine;
|
||||
const lineFunction = line().x(x).y(y).curve(curve);
|
||||
|
||||
// Construct stroke classes based on properties
|
||||
let strokeClasses;
|
||||
switch (edge.thickness) {
|
||||
case 'normal':
|
||||
@@ -563,14 +509,11 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
||||
}
|
||||
let svgPath;
|
||||
let linePath = lineFunction(lineData);
|
||||
const edgeStyles = Array.isArray(edge.style) ? edge.style : [edge.style];
|
||||
if (edge.look === 'handdrawn') {
|
||||
const rc = rough.svg(elem);
|
||||
Object.assign([], lineData);
|
||||
// const svgPathNode = rc.path(lineFunction(ld.splice(0, ld.length-1)), {
|
||||
// const svgPathNode = rc.path(lineFunction(ld), {
|
||||
// roughness: 0.3,
|
||||
// seed: handdrawnSeed,
|
||||
// });
|
||||
|
||||
const svgPathNode = rc.path(linePath, {
|
||||
roughness: 0.3,
|
||||
seed: handdrawnSeed,
|
||||
@@ -580,10 +523,9 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
||||
|
||||
svgPath = select(svgPathNode)
|
||||
.select('path')
|
||||
// .attr('d', lineFunction(lineData))
|
||||
.attr('id', edge.id)
|
||||
.attr('class', ' ' + strokeClasses + (edge.classes ? ' ' + edge.classes : ''))
|
||||
.attr('style', edge.style);
|
||||
.attr('style', edgeStyles ? edgeStyles.reduce((acc, style) => acc + ';' + style, '') : '');
|
||||
let d = svgPath.attr('d');
|
||||
svgPath.attr('d', d);
|
||||
elem.node().appendChild(svgPath.node());
|
||||
@@ -593,7 +535,7 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
||||
.attr('d', linePath)
|
||||
.attr('id', edge.id)
|
||||
.attr('class', ' ' + strokeClasses + (edge.classes ? ' ' + edge.classes : ''))
|
||||
.attr('style', edge.style);
|
||||
.attr('style', edgeStyles ? edgeStyles.reduce((acc, style) => acc + ';' + style, '') : '');
|
||||
}
|
||||
|
||||
// MC Special
|
||||
@@ -611,18 +553,7 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
||||
// .attr('cy', point.y);
|
||||
// });
|
||||
|
||||
// lineData.forEach((point) => {
|
||||
// elem
|
||||
// .append('circle')
|
||||
// .style('stroke', 'red')
|
||||
// .style('fill', 'red')
|
||||
// .attr('r', 1)
|
||||
// .attr('cx', point.x)
|
||||
// .attr('cy', point.y);
|
||||
// });
|
||||
|
||||
let url = '';
|
||||
// // TODO: Can we load this config only from the rendered graph type?
|
||||
if (getConfig().flowchart.arrowMarkerAbsolute || getConfig().state.arrowMarkerAbsolute) {
|
||||
url =
|
||||
window.location.protocol +
|
||||
@@ -630,8 +561,7 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
||||
window.location.host +
|
||||
window.location.pathname +
|
||||
window.location.search;
|
||||
url = url.replace(/\(/g, '\\(');
|
||||
url = url.replace(/\)/g, '\\)');
|
||||
url = url.replace(/\(/g, '\\(').replace(/\)/g, '\\)');
|
||||
}
|
||||
log.info('arrowTypeStart', edge.arrowTypeStart);
|
||||
log.info('arrowTypeEnd', edge.arrowTypeEnd);
|
||||
|
||||
@@ -23,8 +23,8 @@ export const labelRect = async (parent: SVGElement, node: Node) => {
|
||||
const rect = shapeSvg.insert('rect', ':first-child');
|
||||
|
||||
// Hide the rect we are only after the label
|
||||
const totalWidth = 0;
|
||||
const totalHeight = 0;
|
||||
const totalWidth = 0.1;
|
||||
const totalHeight = 0.1;
|
||||
rect.attr('width', totalWidth).attr('height', totalHeight);
|
||||
shapeSvg.attr('class', 'label edgeLabel');
|
||||
|
||||
@@ -40,6 +40,8 @@ export const labelRect = async (parent: SVGElement, node: Node) => {
|
||||
// }
|
||||
|
||||
updateNodeBounds(node, rect);
|
||||
// node.width = 1;
|
||||
// node.height = 1;
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersect.rect(node, point);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export type MarkdownWordType = 'normal' | 'strong' | 'em';
|
||||
import type { MermaidConfig } from '../../dist/config.type';
|
||||
export type MarkdownWordType = 'normal' | 'strong' | 'emphasis';
|
||||
export interface MarkdownWord {
|
||||
content: string;
|
||||
type: MarkdownWordType;
|
||||
|
||||
@@ -101,14 +101,17 @@ properties:
|
||||
type: integer
|
||||
default: 500
|
||||
minimum: 0
|
||||
elk.mergeEdges:
|
||||
elk:
|
||||
type: object
|
||||
properties:
|
||||
mergeEdges:
|
||||
description: |
|
||||
Elk specific option that allows egdes to share path where it convenient. It can make for pretty diagrams but can also make it harder to read the diagram.
|
||||
Elk specific option that allows edges to share path where it convenient. It can make for pretty diagrams but can also make it harder to read the diagram.
|
||||
type: boolean
|
||||
default: false
|
||||
elk.nodePlacement.strategy:
|
||||
nodePlacementStrategy:
|
||||
description: |
|
||||
Elk specific option affedcting how nodes are placed.
|
||||
Elk specific option affecting how nodes are placed.
|
||||
type: string
|
||||
enum:
|
||||
- SIMPLE
|
||||
|
||||
@@ -104,7 +104,10 @@ export class MockedD3 {
|
||||
// This allows different tests to succeed -- some need a top level 'svg' and some need a 'svg' element to be the firstChild
|
||||
// Real implementation returns an HTML Element
|
||||
public node = vi.fn().mockImplementation(() => {
|
||||
//create a top level svg element
|
||||
const topElem = this._containingHTMLdoc.createElement('svg');
|
||||
//@ts-ignore - this is a mock SVG element
|
||||
topElem.getBBox = this.getBBox;
|
||||
const elem_svgChild = this._containingHTMLdoc.createElement('svg'); // another svg element
|
||||
topElem.appendChild(elem_svgChild);
|
||||
return topElem;
|
||||
|
||||
@@ -567,7 +567,7 @@ export const wrapLabel: (label: string, maxWidth: number, config: WrapLabelConfi
|
||||
if (common.lineBreakRegex.test(label)) {
|
||||
return label;
|
||||
}
|
||||
const words = label.split(' ');
|
||||
const words = label.split(' ').filter(Boolean);
|
||||
const completedLines: string[] = [];
|
||||
let nextLine = '';
|
||||
words.forEach((word, index) => {
|
||||
|
||||
2114
pnpm-lock.yaml
generated
2114
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -19,10 +19,12 @@ pnpm build:esbuild
|
||||
pnpm build:types
|
||||
|
||||
# Clone the Mermaid Live Editor repository
|
||||
rm -rf mermaid-live-editor
|
||||
if [ ! -d "mermaid-live-editor" ]; then
|
||||
git clone --single-branch https://github.com/mermaid-js/mermaid-live-editor.git
|
||||
|
||||
fi
|
||||
cd mermaid-live-editor
|
||||
git clean -xdf
|
||||
rm -rf docs/
|
||||
|
||||
# We have to use npm instead of yarn because it causes trouble in netlify
|
||||
# Install dependencies
|
||||
|
||||
@@ -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'];
|
||||
|
||||
@@ -9,7 +9,7 @@ export default defineConfig({
|
||||
extensions: ['.js'],
|
||||
alias: {
|
||||
// Define your alias here
|
||||
'$root/*': path.resolve(__dirname, 'src/*'),
|
||||
$root: path.resolve(__dirname, 'packages/mermaid/src'),
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
|
||||
Reference in New Issue
Block a user