Merge branch 'develop' into bug/4645_graph_node_containing_keyword
This commit is contained in:
commit
f48a9c8696
|
@ -13,6 +13,6 @@ Describe the way your implementation works or what design decisions you made if
|
|||
Make sure you
|
||||
|
||||
- [ ] :book: have read the [contribution guidelines](https://github.com/mermaid-js/mermaid/blob/develop/CONTRIBUTING.md)
|
||||
- [ ] :computer: have added unit/e2e tests (if appropriate)
|
||||
- [ ] :notebook: have added documentation (if appropriate)
|
||||
- [ ] :computer: have added necessary unit/e2e tests.
|
||||
- [ ] :notebook: have added documentation. Make sure [`MERMAID_RELEASE_VERSION`](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/docs/community/development.md#3-update-documentation) is used for all new features.
|
||||
- [ ] :bookmark: targeted `develop` branch
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
name: Build Vitepress docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release/*
|
||||
pull_request:
|
||||
merge_group:
|
||||
|
||||
|
@ -25,5 +29,9 @@ jobs:
|
|||
- name: Install Packages
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Verify release verion
|
||||
if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release')) }}
|
||||
run: pnpm --filter mermaid run docs:verify-version
|
||||
|
||||
- name: Run Build
|
||||
run: pnpm --filter mermaid run docs:build:vitepress
|
||||
|
|
|
@ -45,6 +45,7 @@ jobs:
|
|||
env:
|
||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
||||
VITEST_COVERAGE: true
|
||||
CYPRESS_COMMIT: ${{ github.sha }}
|
||||
- name: Upload Coverage to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
# Run step only pushes to develop and pull_requests
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
"name": "Docs generation",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"args": ["src/docs.mts"],
|
||||
"args": ["scripts/docs.cli.mts"],
|
||||
"runtimeArgs": ["--loader", "ts-node/esm"],
|
||||
"cwd": "${workspaceRoot}/packages/mermaid",
|
||||
"skipFiles": ["<node_internals>/**", "**/node_modules/**"],
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
const utf8ToB64 = (str) => {
|
||||
return window.btoa(unescape(encodeURIComponent(str)));
|
||||
};
|
||||
|
||||
const batchId = 'mermaid-batch' + new Date().getTime();
|
||||
|
||||
export const mermaidUrl = (graphStr, options, api) => {
|
||||
const obj = {
|
||||
code: graphStr,
|
||||
mermaid: options,
|
||||
};
|
||||
const objStr = JSON.stringify(obj);
|
||||
let url = 'http://localhost:9000/e2e.html?graph=' + utf8ToB64(objStr);
|
||||
if (api) {
|
||||
url = 'http://localhost:9000/xss.html?graph=' + graphStr;
|
||||
}
|
||||
|
||||
if (options.listUrl) {
|
||||
cy.log(options.listId, ' ', url);
|
||||
}
|
||||
|
||||
return url;
|
||||
};
|
||||
|
||||
export const imgSnapshotTest = (graphStr, _options = {}, api = false, validation = undefined) => {
|
||||
cy.log(_options);
|
||||
const options = Object.assign(_options);
|
||||
if (!options.fontFamily) {
|
||||
options.fontFamily = 'courier';
|
||||
}
|
||||
if (!options.sequence) {
|
||||
options.sequence = {};
|
||||
}
|
||||
if (!options.sequence || (options.sequence && !options.sequence.actorFontFamily)) {
|
||||
options.sequence.actorFontFamily = 'courier';
|
||||
}
|
||||
if (options.sequence && !options.sequence.noteFontFamily) {
|
||||
options.sequence.noteFontFamily = 'courier';
|
||||
}
|
||||
options.sequence.actorFontFamily = 'courier';
|
||||
options.sequence.noteFontFamily = 'courier';
|
||||
options.sequence.messageFontFamily = 'courier';
|
||||
if (options.sequence && !options.sequence.actorFontFamily) {
|
||||
options.sequence.actorFontFamily = 'courier';
|
||||
}
|
||||
if (!options.fontSize) {
|
||||
options.fontSize = '16px';
|
||||
}
|
||||
const url = mermaidUrl(graphStr, options, api);
|
||||
openURLAndVerifyRendering(url, options, validation);
|
||||
};
|
||||
|
||||
export const urlSnapshotTest = (url, _options, api = false, validation) => {
|
||||
const options = Object.assign(_options);
|
||||
openURLAndVerifyRendering(url, options, validation);
|
||||
};
|
||||
|
||||
export const renderGraph = (graphStr, options, api) => {
|
||||
const url = mermaidUrl(graphStr, options, api);
|
||||
openURLAndVerifyRendering(url, options);
|
||||
};
|
||||
|
||||
export const openURLAndVerifyRendering = (url, options, validation = undefined) => {
|
||||
const useAppli = Cypress.env('useAppli');
|
||||
const name = (options.name || cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
|
||||
|
||||
if (useAppli) {
|
||||
cy.log('Opening eyes ' + Cypress.spec.name + ' --- ' + name);
|
||||
cy.eyesOpen({
|
||||
appName: 'Mermaid',
|
||||
testName: name,
|
||||
batchName: Cypress.spec.name,
|
||||
batchId: batchId + Cypress.spec.name,
|
||||
});
|
||||
}
|
||||
|
||||
cy.visit(url);
|
||||
cy.window().should('have.property', 'rendered', true);
|
||||
cy.get('svg').should('be.visible');
|
||||
|
||||
if (validation) {
|
||||
cy.get('svg').should(validation);
|
||||
}
|
||||
|
||||
if (useAppli) {
|
||||
cy.log('Check eyes' + Cypress.spec.name);
|
||||
cy.eyesCheckWindow('Click!');
|
||||
cy.log('Closing eyes' + Cypress.spec.name);
|
||||
cy.eyesClose();
|
||||
} else {
|
||||
cy.matchImageSnapshot(name);
|
||||
}
|
||||
};
|
|
@ -0,0 +1,132 @@
|
|||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { Buffer } from 'buffer';
|
||||
import type { MermaidConfig } from '../../packages/mermaid/src/config.type.js';
|
||||
|
||||
interface CypressConfig {
|
||||
listUrl?: boolean;
|
||||
listId?: string;
|
||||
name?: string;
|
||||
}
|
||||
type CypressMermaidConfig = MermaidConfig & CypressConfig;
|
||||
|
||||
interface CodeObject {
|
||||
code: string;
|
||||
mermaid: CypressMermaidConfig;
|
||||
}
|
||||
|
||||
const utf8ToB64 = (str: string): string => {
|
||||
return Buffer.from(decodeURIComponent(encodeURIComponent(str))).toString('base64');
|
||||
};
|
||||
|
||||
const batchId: string = 'mermaid-batch-' + Cypress.env('CYPRESS_COMMIT') || Date.now().toString();
|
||||
|
||||
export const mermaidUrl = (
|
||||
graphStr: string,
|
||||
options: CypressMermaidConfig,
|
||||
api: boolean
|
||||
): string => {
|
||||
const codeObject: CodeObject = {
|
||||
code: graphStr,
|
||||
mermaid: options,
|
||||
};
|
||||
const objStr: string = JSON.stringify(codeObject);
|
||||
let url = `http://localhost:9000/e2e.html?graph=${utf8ToB64(objStr)}`;
|
||||
if (api) {
|
||||
url = `http://localhost:9000/xss.html?graph=${graphStr}`;
|
||||
}
|
||||
|
||||
if (options.listUrl) {
|
||||
cy.log(options.listId, ' ', url);
|
||||
}
|
||||
|
||||
return url;
|
||||
};
|
||||
|
||||
export const imgSnapshotTest = (
|
||||
graphStr: string,
|
||||
_options: CypressMermaidConfig = {},
|
||||
api = false,
|
||||
validation?: any
|
||||
): void => {
|
||||
cy.log(JSON.stringify(_options));
|
||||
const options: CypressMermaidConfig = Object.assign(_options);
|
||||
if (!options.fontFamily) {
|
||||
options.fontFamily = 'courier';
|
||||
}
|
||||
if (!options.sequence) {
|
||||
options.sequence = {};
|
||||
}
|
||||
if (!options.sequence || (options.sequence && !options.sequence.actorFontFamily)) {
|
||||
options.sequence.actorFontFamily = 'courier';
|
||||
}
|
||||
if (options.sequence && !options.sequence.noteFontFamily) {
|
||||
options.sequence.noteFontFamily = 'courier';
|
||||
}
|
||||
options.sequence.actorFontFamily = 'courier';
|
||||
options.sequence.noteFontFamily = 'courier';
|
||||
options.sequence.messageFontFamily = 'courier';
|
||||
if (options.sequence && !options.sequence.actorFontFamily) {
|
||||
options.sequence.actorFontFamily = 'courier';
|
||||
}
|
||||
if (!options.fontSize) {
|
||||
options.fontSize = 16;
|
||||
}
|
||||
|
||||
const url: string = mermaidUrl(graphStr, options, api);
|
||||
openURLAndVerifyRendering(url, options, validation);
|
||||
};
|
||||
|
||||
export const urlSnapshotTest = (
|
||||
url: string,
|
||||
_options: CypressMermaidConfig,
|
||||
_api = false,
|
||||
validation?: any
|
||||
): void => {
|
||||
const options: CypressMermaidConfig = Object.assign(_options);
|
||||
openURLAndVerifyRendering(url, options, validation);
|
||||
};
|
||||
|
||||
export const renderGraph = (
|
||||
graphStr: string,
|
||||
options: CypressMermaidConfig = {},
|
||||
api = false
|
||||
): void => {
|
||||
const url: string = mermaidUrl(graphStr, options, api);
|
||||
openURLAndVerifyRendering(url, options);
|
||||
};
|
||||
|
||||
export const openURLAndVerifyRendering = (
|
||||
url: string,
|
||||
options: CypressMermaidConfig,
|
||||
validation?: any
|
||||
): void => {
|
||||
const useAppli: boolean = Cypress.env('useAppli');
|
||||
const name: string = (options.name || cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
|
||||
|
||||
if (useAppli) {
|
||||
cy.log(`Opening eyes ${Cypress.spec.name} --- ${name}`);
|
||||
cy.eyesOpen({
|
||||
appName: 'Mermaid',
|
||||
testName: name,
|
||||
batchName: Cypress.spec.name,
|
||||
batchId: batchId + Cypress.spec.name,
|
||||
});
|
||||
}
|
||||
|
||||
cy.visit(url);
|
||||
cy.window().should('have.property', 'rendered', true);
|
||||
cy.get('svg').should('be.visible');
|
||||
|
||||
if (validation) {
|
||||
cy.get('svg').should(validation);
|
||||
}
|
||||
|
||||
if (useAppli) {
|
||||
cy.log(`Check eyes ${Cypress.spec.name}`);
|
||||
cy.eyesCheckWindow('Click!');
|
||||
cy.log(`Closing eyes ${Cypress.spec.name}`);
|
||||
cy.eyesClose();
|
||||
} else {
|
||||
cy.matchImageSnapshot(name);
|
||||
}
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
import { renderGraph } from '../../helpers/util.js';
|
||||
import { renderGraph } from '../../helpers/util.ts';
|
||||
describe('Configuration', () => {
|
||||
describe('arrowMarkerAbsolute', () => {
|
||||
it('should handle default value false of arrowMarkerAbsolute', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { urlSnapshotTest } from '../../helpers/util.js';
|
||||
import { urlSnapshotTest } from '../../helpers/util.ts';
|
||||
|
||||
describe('mermaid', () => {
|
||||
describe('registerDiagram', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { urlSnapshotTest, openURLAndVerifyRendering } from '../../helpers/util.js';
|
||||
import { urlSnapshotTest, openURLAndVerifyRendering } from '../../helpers/util.ts';
|
||||
|
||||
describe('CSS injections', () => {
|
||||
it('should not allow CSS injections outside of the diagram', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { mermaidUrl } from '../../helpers/util.js';
|
||||
import { mermaidUrl } from '../../helpers/util.ts';
|
||||
describe('XSS', () => {
|
||||
it('should handle xss in tags', () => {
|
||||
const str =
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest } from '../../helpers/util.ts';
|
||||
|
||||
describe('Git Graph diagram', () => {
|
||||
it('1: should render a simple gitgraph with commit on main branch', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
describe('C4 diagram', () => {
|
||||
it('should render a simple C4Context diagram', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest } from '../../helpers/util.ts';
|
||||
describe('Class diagram V2', () => {
|
||||
it('0: should render a simple class diagram', () => {
|
||||
imgSnapshotTest(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
describe('Class diagram', () => {
|
||||
it('1: should render a simple class diagram', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest } from '../../helpers/util.ts';
|
||||
|
||||
describe('Configuration and directives - nodes should be light blue', () => {
|
||||
it('No config - use default', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest } from '../../helpers/util.ts';
|
||||
|
||||
describe('Current diagram', () => {
|
||||
it('should render a state with states in it', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest } from '../../helpers/util.ts';
|
||||
|
||||
describe('Flowchart', () => {
|
||||
it('34: testing the label width in percy', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
describe('Entity Relationship Diagram', () => {
|
||||
it('should render a simple ER diagram', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
describe.skip('Flowchart ELK', () => {
|
||||
it('1-elk: should render a simple flowchart', () => {
|
||||
|
@ -681,7 +681,7 @@ title: Simple flowchart
|
|||
flowchart-elk TD
|
||||
A --> B
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('elk: should include classes on the edges', () => {
|
||||
|
@ -710,7 +710,7 @@ flowchart-elk LR
|
|||
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
|
||||
classDef someclass fill:#f96
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('With formatting in a node', () => {
|
||||
|
@ -726,7 +726,7 @@ flowchart-elk LR
|
|||
b --> d(The dog in the hog)
|
||||
c --> d
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('New line in node and formatted edge label', () => {
|
||||
|
@ -736,7 +736,7 @@ flowchart-elk LR
|
|||
b("\`The dog in **the** hog.(1)
|
||||
NL\`") --"\`1o **bold**\`"--> c
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('Wrapping long text with a new line', () => {
|
||||
|
@ -749,7 +749,7 @@ Word!
|
|||
Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. \`) --> c
|
||||
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('Sub graphs and markdown strings', () => {
|
||||
|
@ -766,7 +766,7 @@ subgraph "\`**Two**\`"
|
|||
end
|
||||
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -782,7 +782,7 @@ flowchart-elk LR
|
|||
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
|
||||
classDef someclass fill:#f96
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('With formatting in a node', () => {
|
||||
|
@ -798,7 +798,7 @@ flowchart-elk LR
|
|||
b --> d(The dog in the hog)
|
||||
c --> d
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('New line in node and formatted edge label', () => {
|
||||
|
@ -808,7 +808,7 @@ flowchart-elk LR
|
|||
b("\`The dog in **the** hog.(1)
|
||||
NL\`") --"\`1o **bold**\`"--> c
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('Wrapping long text with a new line', () => {
|
||||
|
@ -821,7 +821,7 @@ Word!
|
|||
Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. \`") --> c
|
||||
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('Sub graphs and markdown strings', () => {
|
||||
|
@ -838,7 +838,7 @@ subgraph "\`**Two**\`"
|
|||
end
|
||||
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
describe('Flowchart v2', () => {
|
||||
it('1: should render a simple flowchart', () => {
|
||||
|
@ -671,7 +671,7 @@ title: Simple flowchart
|
|||
flowchart TD
|
||||
A --> B
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('3192: It should be possieble to render flowcharts with invisible edges', () => {
|
||||
|
@ -682,7 +682,7 @@ title: Simple flowchart with invisible edges
|
|||
flowchart TD
|
||||
A ~~~ B
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('4023: Should render html labels with images and-or text correctly', () => {
|
||||
|
@ -716,7 +716,7 @@ flowchart LR
|
|||
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
|
||||
classDef someclass fill:#f96
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('With formatting in a node', () => {
|
||||
|
@ -732,7 +732,7 @@ flowchart LR
|
|||
b --> d(The dog in the hog)
|
||||
c --> d
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('New line in node and formatted edge label', () => {
|
||||
|
@ -742,7 +742,7 @@ flowchart LR
|
|||
b("\`The dog in **the** hog.(1)
|
||||
NL\`") --"\`1o **bold**\`"--> c
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('Wrapping long text with a new line', () => {
|
||||
|
@ -755,7 +755,7 @@ Word!
|
|||
Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. \`") --> c
|
||||
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('Sub graphs and markdown strings', () => {
|
||||
|
@ -772,7 +772,7 @@ subgraph "\`**Two**\`"
|
|||
end
|
||||
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -788,7 +788,7 @@ flowchart LR
|
|||
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
|
||||
classDef someclass fill:#f96
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('With formatting in a node', () => {
|
||||
|
@ -804,7 +804,7 @@ flowchart LR
|
|||
b --> d(The dog in the hog)
|
||||
c --> d
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('New line in node and formatted edge label', () => {
|
||||
|
@ -814,7 +814,7 @@ flowchart LR
|
|||
b("\`The dog in **the** hog.(1)
|
||||
NL\`") --"\`1o **bold**\`"--> c
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('Wrapping long text with a new line', () => {
|
||||
|
@ -827,7 +827,7 @@ Word!
|
|||
Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. \`") --> c
|
||||
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('Sub graphs and markdown strings', () => {
|
||||
|
@ -844,7 +844,7 @@ subgraph "\`**Two**\`"
|
|||
end
|
||||
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
describe('Graph', () => {
|
||||
it('1: should render a simple flowchart no htmlLabels', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
describe('Gantt diagram', () => {
|
||||
beforeEach(() => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest } from '../../helpers/util.ts';
|
||||
|
||||
describe('Git Graph diagram', () => {
|
||||
it('1: should render a simple gitgraph with commit on main branch', () => {
|
||||
|
@ -333,4 +333,372 @@ gitGraph
|
|||
{}
|
||||
);
|
||||
});
|
||||
it('15: should render a simple gitgraph with commit on main branch | Vertical Branch', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph TB:
|
||||
commit id: "1"
|
||||
commit id: "2"
|
||||
commit id: "3"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('16: should render a simple gitgraph with commit on main branch with Id | Vertical Branch', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph TB:
|
||||
commit id: "One"
|
||||
commit id: "Two"
|
||||
commit id: "Three"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('17: should render a simple gitgraph with different commitTypes on main branch | Vertical Branch', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph TB:
|
||||
commit id: "Normal Commit"
|
||||
commit id: "Reverse Commit" type: REVERSE
|
||||
commit id: "Hightlight Commit" type: HIGHLIGHT
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('18: should render a simple gitgraph with tags commitTypes on main branch | Vertical Branch', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph TB:
|
||||
commit id: "Normal Commit with tag" tag: "v1.0.0"
|
||||
commit id: "Reverse Commit with tag" type: REVERSE tag: "RC_1"
|
||||
commit id: "Hightlight Commit" type: HIGHLIGHT tag: "8.8.4"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('19: should render a simple gitgraph with two branches | Vertical Branch', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph TB:
|
||||
commit id: "1"
|
||||
commit id: "2"
|
||||
branch develop
|
||||
checkout develop
|
||||
commit id: "3"
|
||||
commit id: "4"
|
||||
checkout main
|
||||
commit id: "5"
|
||||
commit id: "6"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('20: should render a simple gitgraph with two branches and merge commit | Vertical Branch', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph TB:
|
||||
commit id: "1"
|
||||
commit id: "2"
|
||||
branch develop
|
||||
checkout develop
|
||||
commit id: "3"
|
||||
commit id: "4"
|
||||
checkout main
|
||||
merge develop
|
||||
commit id: "5"
|
||||
commit id: "6"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('21: should render a simple gitgraph with three branches and tagged merge commit | Vertical Branch', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph TB:
|
||||
commit id: "1"
|
||||
commit id: "2"
|
||||
branch nice_feature
|
||||
checkout nice_feature
|
||||
commit id: "3"
|
||||
checkout main
|
||||
commit id: "4"
|
||||
checkout nice_feature
|
||||
branch very_nice_feature
|
||||
checkout very_nice_feature
|
||||
commit id: "5"
|
||||
checkout main
|
||||
commit id: "6"
|
||||
checkout nice_feature
|
||||
commit id: "7"
|
||||
checkout main
|
||||
merge nice_feature id: "12345" tag: "my merge commit"
|
||||
checkout very_nice_feature
|
||||
commit id: "8"
|
||||
checkout main
|
||||
commit id: "9"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('22: should render a simple gitgraph with more than 8 branchs & overriding variables | Vertical Branch', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': {
|
||||
'gitBranchLabel0': '#ffffff',
|
||||
'gitBranchLabel1': '#ffffff',
|
||||
'gitBranchLabel2': '#ffffff',
|
||||
'gitBranchLabel3': '#ffffff',
|
||||
'gitBranchLabel4': '#ffffff',
|
||||
'gitBranchLabel5': '#ffffff',
|
||||
'gitBranchLabel6': '#ffffff',
|
||||
'gitBranchLabel7': '#ffffff',
|
||||
} } }%%
|
||||
gitGraph TB:
|
||||
checkout main
|
||||
branch branch1
|
||||
branch branch2
|
||||
branch branch3
|
||||
branch branch4
|
||||
branch branch5
|
||||
branch branch6
|
||||
branch branch7
|
||||
branch branch8
|
||||
branch branch9
|
||||
checkout branch1
|
||||
commit id: "1"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('23: should render a simple gitgraph with rotated labels | Vertical Branch', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'gitGraph': {
|
||||
'rotateCommitLabel': true
|
||||
} } }%%
|
||||
gitGraph TB:
|
||||
commit id: "75f7219e83b321cd3fdde7dcf83bc7c1000a6828"
|
||||
commit id: "0db4784daf82736dec4569e0dc92980d328c1f2e"
|
||||
commit id: "7067e9973f9eaa6cd4a4b723c506d1eab598e83e"
|
||||
commit id: "66972321ad6c199013b5b31f03b3a86fa3f9817d"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('24: should render a simple gitgraph with horizontal labels | Vertical Branch', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'gitGraph': {
|
||||
'rotateCommitLabel': false
|
||||
} } }%%
|
||||
gitGraph TB:
|
||||
commit id: "Alpha"
|
||||
commit id: "Beta"
|
||||
commit id: "Gamma"
|
||||
commit id: "Delta"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('25: should render a simple gitgraph with cherry pick commit | Vertical Branch', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gitGraph TB:
|
||||
commit id: "ZERO"
|
||||
branch develop
|
||||
commit id:"A"
|
||||
checkout main
|
||||
commit id:"ONE"
|
||||
checkout develop
|
||||
commit id:"B"
|
||||
checkout main
|
||||
commit id:"TWO"
|
||||
cherry-pick id:"A"
|
||||
commit id:"THREE"
|
||||
checkout develop
|
||||
commit id:"C"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('26: should render a gitgraph with cherry pick commit with custom tag | Vertical Branch', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gitGraph TB:
|
||||
commit id: "ZERO"
|
||||
branch develop
|
||||
commit id:"A"
|
||||
checkout main
|
||||
commit id:"ONE"
|
||||
checkout develop
|
||||
commit id:"B"
|
||||
checkout main
|
||||
commit id:"TWO"
|
||||
cherry-pick id:"A" tag: "snapshot"
|
||||
commit id:"THREE"
|
||||
checkout develop
|
||||
commit id:"C"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('27: should render a gitgraph with cherry pick commit with no tag | Vertical Branch', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gitGraph TB:
|
||||
commit id: "ZERO"
|
||||
branch develop
|
||||
commit id:"A"
|
||||
checkout main
|
||||
commit id:"ONE"
|
||||
checkout develop
|
||||
commit id:"B"
|
||||
checkout main
|
||||
commit id:"TWO"
|
||||
cherry-pick id:"A" tag: ""
|
||||
commit id:"THREE"
|
||||
checkout develop
|
||||
commit id:"C"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('28: should render a simple gitgraph with two cherry pick commit | Vertical Branch', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gitGraph TB:
|
||||
commit id: "ZERO"
|
||||
branch develop
|
||||
commit id:"A"
|
||||
checkout main
|
||||
commit id:"ONE"
|
||||
checkout develop
|
||||
commit id:"B"
|
||||
branch featureA
|
||||
commit id:"FIX"
|
||||
commit id: "FIX-2"
|
||||
checkout main
|
||||
commit id:"TWO"
|
||||
cherry-pick id:"A"
|
||||
commit id:"THREE"
|
||||
cherry-pick id:"FIX"
|
||||
checkout develop
|
||||
commit id:"C"
|
||||
merge featureA
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('29: should render commits for more than 8 branches | Vertical Branch', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gitGraph TB:
|
||||
checkout main
|
||||
%% Make sure to manually set the ID of all commits, for consistent visual tests
|
||||
commit id: "1-abcdefg"
|
||||
checkout main
|
||||
branch branch1
|
||||
commit id: "2-abcdefg"
|
||||
checkout main
|
||||
merge branch1
|
||||
branch branch2
|
||||
commit id: "3-abcdefg"
|
||||
checkout main
|
||||
merge branch2
|
||||
branch branch3
|
||||
commit id: "4-abcdefg"
|
||||
checkout main
|
||||
merge branch3
|
||||
branch branch4
|
||||
commit id: "5-abcdefg"
|
||||
checkout main
|
||||
merge branch4
|
||||
branch branch5
|
||||
commit id: "6-abcdefg"
|
||||
checkout main
|
||||
merge branch5
|
||||
branch branch6
|
||||
commit id: "7-abcdefg"
|
||||
checkout main
|
||||
merge branch6
|
||||
branch branch7
|
||||
commit id: "8-abcdefg"
|
||||
checkout main
|
||||
merge branch7
|
||||
branch branch8
|
||||
commit id: "9-abcdefg"
|
||||
checkout main
|
||||
merge branch8
|
||||
branch branch9
|
||||
commit id: "10-abcdefg"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('30: should render a simple gitgraph with three branches,custom merge commit id,tag,type | Vertical Branch', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph TB:
|
||||
commit id: "1"
|
||||
commit id: "2"
|
||||
branch nice_feature
|
||||
checkout nice_feature
|
||||
commit id: "3"
|
||||
checkout main
|
||||
commit id: "4"
|
||||
checkout nice_feature
|
||||
branch very_nice_feature
|
||||
checkout very_nice_feature
|
||||
commit id: "5"
|
||||
checkout main
|
||||
commit id: "6"
|
||||
checkout nice_feature
|
||||
commit id: "7"
|
||||
checkout main
|
||||
merge nice_feature id: "customID" tag: "customTag" type: REVERSE
|
||||
checkout very_nice_feature
|
||||
commit id: "8"
|
||||
checkout main
|
||||
commit id: "9"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('31: should render a simple gitgraph with a title | Vertical Branch', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
title: simple gitGraph
|
||||
---
|
||||
gitGraph TB:
|
||||
commit id: "1-abcdefg"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('32: should render a simple gitgraph overlapping commits | Vertical Branch', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph TB:
|
||||
commit id:"s1"
|
||||
commit id:"s2"
|
||||
branch branch1
|
||||
commit id:"s3"
|
||||
commit id:"s4"
|
||||
checkout main
|
||||
commit id:"s5"
|
||||
checkout branch1
|
||||
commit id:"s6"
|
||||
commit id:"s7"
|
||||
merge main
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('33: should render a simple gitgraph overlapping commits', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph
|
||||
commit id:"s1"
|
||||
commit id:"s2"
|
||||
branch branch1
|
||||
commit id:"s3"
|
||||
commit id:"s4"
|
||||
checkout main
|
||||
commit id:"s5"
|
||||
checkout branch1
|
||||
commit id:"s6"
|
||||
commit id:"s7"
|
||||
merge main
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest } from '../../helpers/util.ts';
|
||||
|
||||
describe('info diagram', () => {
|
||||
it('should handle an info definition', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
describe('User journey diagram', () => {
|
||||
it('Simple test', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest } from '../../helpers/util.ts';
|
||||
|
||||
/**
|
||||
* Check whether the SVG Element has a Mindmap root
|
||||
|
@ -242,8 +242,7 @@ mindmap
|
|||
a second line 😎\`]
|
||||
id2[\`The dog in **the** hog... a *very long text* about it
|
||||
Word!\`]
|
||||
`,
|
||||
{ titleTopMargin: 0 }
|
||||
`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
describe('Pie Chart', () => {
|
||||
it('should render a simple pie diagram', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
describe('Quadrant Chart', () => {
|
||||
it('should render if only chart type is provided', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
describe('Requirement diagram', () => {
|
||||
it('sample', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
describe('Sankey Diagram', () => {
|
||||
it('should render a simple example', () => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/// <reference types="Cypress" />
|
||||
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
context('Sequence diagram', () => {
|
||||
it('should render a sequence diagram with boxes', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
describe('State diagram', () => {
|
||||
it('v2 should render a simple info', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
describe('State diagram', () => {
|
||||
it('should render a simple state diagrams', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest } from '../../helpers/util.ts';
|
||||
|
||||
describe('themeCSS balancing, it', () => {
|
||||
it('should not allow unbalanced CSS definitions', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest } from '../../helpers/util.ts';
|
||||
|
||||
describe('Timeline diagram', () => {
|
||||
it('1: should render a simple timeline with no specific sections', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { imgSnapshotTest } from '../../helpers/util.js';
|
||||
import { imgSnapshotTest } from '../../helpers/util.ts';
|
||||
|
||||
describe('Zen UML', () => {
|
||||
it('Basic Zen UML diagram', () => {
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
"compilerOptions": {
|
||||
"target": "es2020",
|
||||
"lib": ["es2020", "dom"],
|
||||
"types": ["cypress", "node"]
|
||||
"types": ["cypress", "node"],
|
||||
"allowImportingTsExtensions": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["**/*.ts"]
|
||||
}
|
||||
|
|
|
@ -223,6 +223,9 @@ If the users have no way to know that things have changed, then you haven't real
|
|||
Likewise, if users don't know that there is a new feature that you've implemented, it will forever remain unknown and unused.
|
||||
|
||||
The documentation has to be updated to users know that things have changed and added!
|
||||
If you are adding a new feature, add `(v<MERMAID_RELEASE_VERSION>+)` in the title or description. It will be replaced automatically with the current version number when the release happens.
|
||||
|
||||
eg: `# Feature Name (v<MERMAID_RELEASE_VERSION>+)`
|
||||
|
||||
We know it can sometimes be hard to code _and_ write user documentation.
|
||||
|
||||
|
|
|
@ -825,6 +825,82 @@ NOTE: Because we have overridden the `mainBranchOrder` to `2`, the `main` branch
|
|||
|
||||
Here, we have changed the default main branch name to `MetroLine1`.
|
||||
|
||||
## Orientation
|
||||
|
||||
In Mermaid, the default orientation is Left to Right. The branches are lined vertically.
|
||||
|
||||
Usage example:
|
||||
|
||||
```mermaid-example
|
||||
gitGraph
|
||||
commit
|
||||
commit
|
||||
branch develop
|
||||
commit
|
||||
commit
|
||||
commit
|
||||
checkout main
|
||||
commit
|
||||
commit
|
||||
merge develop
|
||||
commit
|
||||
commit
|
||||
```
|
||||
|
||||
```mermaid
|
||||
gitGraph
|
||||
commit
|
||||
commit
|
||||
branch develop
|
||||
commit
|
||||
commit
|
||||
commit
|
||||
checkout main
|
||||
commit
|
||||
commit
|
||||
merge develop
|
||||
commit
|
||||
commit
|
||||
```
|
||||
|
||||
Sometimes we may want to change the orientation. Currently, Mermaid supports two orientations: **Left to Right**(default) and **Top to Bottom**.
|
||||
|
||||
In order to change the orientation from top to bottom i.e. branches lined horizontally, you need to add `TB` along with `gitGraph`.
|
||||
|
||||
Usage example:
|
||||
|
||||
```mermaid-example
|
||||
gitGraph TB:
|
||||
commit
|
||||
commit
|
||||
branch develop
|
||||
commit
|
||||
commit
|
||||
commit
|
||||
checkout main
|
||||
commit
|
||||
commit
|
||||
merge develop
|
||||
commit
|
||||
commit
|
||||
```
|
||||
|
||||
```mermaid
|
||||
gitGraph TB:
|
||||
commit
|
||||
commit
|
||||
branch develop
|
||||
commit
|
||||
commit
|
||||
commit
|
||||
checkout main
|
||||
commit
|
||||
commit
|
||||
merge develop
|
||||
commit
|
||||
commit
|
||||
```
|
||||
|
||||
## Themes
|
||||
|
||||
Mermaid supports a bunch of pre-defined themes which you can use to find the right one for you. PS: you can actually override an existing theme's variable to get your own custom theme going. Learn more about theming your diagram [here](../config/theming.md).
|
||||
|
|
|
@ -25,14 +25,16 @@
|
|||
"scripts": {
|
||||
"clean": "rimraf dist",
|
||||
"docs:code": "typedoc src/defaultConfig.ts src/config.ts src/mermaidAPI.ts && prettier --write ./src/docs/config/setup",
|
||||
"docs:build": "rimraf ../../docs && pnpm docs:spellcheck && pnpm docs:code && ts-node-esm src/docs.mts",
|
||||
"docs:verify": "pnpm docs:spellcheck && pnpm docs:code && ts-node-esm src/docs.mts --verify",
|
||||
"docs:pre:vitepress": "pnpm --filter ./src/docs prefetch && rimraf src/vitepress && pnpm docs:code && ts-node-esm src/docs.mts --vitepress && pnpm --filter ./src/vitepress install --no-frozen-lockfile --ignore-scripts",
|
||||
"docs:build": "rimraf ../../docs && pnpm docs:spellcheck && pnpm docs:code && ts-node-esm scripts/docs.cli.mts",
|
||||
"docs:verify": "pnpm docs:spellcheck && pnpm docs:code && ts-node-esm scripts/docs.cli.mts --verify",
|
||||
"docs:pre:vitepress": "pnpm --filter ./src/docs prefetch && rimraf src/vitepress && pnpm docs:code && ts-node-esm scripts/docs.cli.mts --vitepress && pnpm --filter ./src/vitepress install --no-frozen-lockfile --ignore-scripts",
|
||||
"docs:build:vitepress": "pnpm docs:pre:vitepress && (cd src/vitepress && pnpm run build) && cpy --flat src/docs/landing/ ./src/vitepress/.vitepress/dist/landing",
|
||||
"docs:dev": "pnpm docs:pre:vitepress && concurrently \"pnpm --filter ./src/vitepress dev\" \"ts-node-esm src/docs.mts --watch --vitepress\"",
|
||||
"docs:dev:docker": "pnpm docs:pre:vitepress && concurrently \"pnpm --filter ./src/vitepress dev:docker\" \"ts-node-esm src/docs.mts --watch --vitepress\"",
|
||||
"docs:dev": "pnpm docs:pre:vitepress && concurrently \"pnpm --filter ./src/vitepress dev\" \"ts-node-esm scripts/docs.cli.mts --watch --vitepress\"",
|
||||
"docs:dev:docker": "pnpm docs:pre:vitepress && concurrently \"pnpm --filter ./src/vitepress dev:docker\" \"ts-node-esm scripts/docs.cli.mts --watch --vitepress\"",
|
||||
"docs:serve": "pnpm docs:build:vitepress && vitepress serve src/vitepress",
|
||||
"docs:spellcheck": "cspell --config ../../cSpell.json \"src/docs/**/*.md\"",
|
||||
"docs:release-version": "ts-node-esm scripts/update-release-version.mts",
|
||||
"docs:verify-version": "ts-node-esm scripts/update-release-version.mts --verify",
|
||||
"types:build-config": "ts-node-esm --transpileOnly scripts/create-types-from-json-schema.mts",
|
||||
"types:verify-config": "ts-node-esm scripts/create-types-from-json-schema.mts --verify",
|
||||
"release": "pnpm build",
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
import { processDocs } from './docs.mjs';
|
||||
|
||||
void processDocs();
|
|
@ -27,14 +27,21 @@
|
|||
* get their absolute paths. Ensures that the location of those 2 directories is not dependent on
|
||||
* where this file resides.
|
||||
*
|
||||
* @todo Write a test file for this. (Will need to be able to deal .mts file. Jest has trouble with
|
||||
* it.)
|
||||
*/
|
||||
// @ts-ignore: we're importing internal jsonschema2md functions
|
||||
import { default as schemaLoader } from '@adobe/jsonschema2md/lib/schemaProxy.js';
|
||||
// @ts-ignore: we're importing internal jsonschema2md functions
|
||||
import { default as traverseSchemas } from '@adobe/jsonschema2md/lib/traverseSchema.js';
|
||||
// @ts-ignore: we're importing internal jsonschema2md functions
|
||||
import { default as buildMarkdownFromSchema } from '@adobe/jsonschema2md/lib/markdownBuilder.js';
|
||||
// @ts-ignore: we're importing internal jsonschema2md functions
|
||||
import { default as jsonSchemaReadmeBuilder } from '@adobe/jsonschema2md/lib/readmeBuilder.js';
|
||||
import { readFileSync, writeFileSync, mkdirSync, existsSync, rmSync, rmdirSync } from 'fs';
|
||||
import { exec } from 'child_process';
|
||||
import { globby } from 'globby';
|
||||
import { JSDOM } from 'jsdom';
|
||||
import type { Code, ListItem, Root, Text } from 'mdast';
|
||||
import { dump, load, JSON_SCHEMA } from 'js-yaml';
|
||||
import type { Code, ListItem, Root, Text, YAML } from 'mdast';
|
||||
import { posix, dirname, relative, join } from 'path';
|
||||
import prettier from 'prettier';
|
||||
import { remark } from 'remark';
|
||||
|
@ -46,9 +53,9 @@ import mm from 'micromatch';
|
|||
import flatmap from 'unist-util-flatmap';
|
||||
import { visit } from 'unist-util-visit';
|
||||
|
||||
const MERMAID_MAJOR_VERSION = (
|
||||
JSON.parse(readFileSync('../mermaid/package.json', 'utf8')).version as string
|
||||
).split('.')[0];
|
||||
export const MERMAID_RELEASE_VERSION = JSON.parse(readFileSync('../mermaid/package.json', 'utf8'))
|
||||
.version as string;
|
||||
const MERMAID_MAJOR_VERSION = MERMAID_RELEASE_VERSION.split('.')[0];
|
||||
const CDN_URL = 'https://cdn.jsdelivr.net/npm'; // 'https://unpkg.com';
|
||||
|
||||
const MERMAID_KEYWORD = 'mermaid';
|
||||
|
@ -71,7 +78,7 @@ const vitepress: boolean = process.argv.includes('--vitepress');
|
|||
const noHeader: boolean = process.argv.includes('--noHeader') || vitepress;
|
||||
|
||||
// These paths are from the root of the mono-repo, not from the mermaid subdirectory
|
||||
const SOURCE_DOCS_DIR = 'src/docs';
|
||||
export const SOURCE_DOCS_DIR = 'src/docs';
|
||||
const FINAL_DOCS_DIR = vitepress ? 'src/vitepress' : '../../docs';
|
||||
|
||||
const LOGMSG_TRANSFORMED = 'transformed';
|
||||
|
@ -158,7 +165,7 @@ const copyTransformedContents = (filename: string, doCopy = false, transformedCo
|
|||
logWasOrShouldBeTransformed(fileInFinalDocDir, doCopy);
|
||||
};
|
||||
|
||||
const readSyncedUTF8file = (filename: string): string => {
|
||||
export const readSyncedUTF8file = (filename: string): string => {
|
||||
return readFileSync(filename, 'utf8');
|
||||
};
|
||||
|
||||
|
@ -209,6 +216,8 @@ interface TransformMarkdownAstOptions {
|
|||
originalFilename: string;
|
||||
/** If `true`, add a warning that the file is autogenerated */
|
||||
addAutogeneratedWarning?: boolean;
|
||||
/** If `true`, adds an `editLink: "https://..."` YAML frontmatter field */
|
||||
addEditLink?: boolean;
|
||||
/**
|
||||
* If `true`, remove the YAML metadata from the Markdown input.
|
||||
* Generally, YAML metadata is only used for Vitepress.
|
||||
|
@ -231,6 +240,7 @@ interface TransformMarkdownAstOptions {
|
|||
export function transformMarkdownAst({
|
||||
originalFilename,
|
||||
addAutogeneratedWarning,
|
||||
addEditLink,
|
||||
removeYAML,
|
||||
}: TransformMarkdownAstOptions) {
|
||||
return (tree: Root, _file?: any): Root => {
|
||||
|
@ -270,6 +280,27 @@ export function transformMarkdownAst({
|
|||
}
|
||||
}
|
||||
|
||||
if (addEditLink) {
|
||||
// add originalFilename as custom editLink in YAML frontmatter
|
||||
let yamlFrontMatter: YAML;
|
||||
if (astWithTransformedBlocks.children[0].type === 'yaml') {
|
||||
yamlFrontMatter = astWithTransformedBlocks.children[0];
|
||||
} else {
|
||||
yamlFrontMatter = {
|
||||
type: 'yaml',
|
||||
value: '',
|
||||
};
|
||||
astWithTransformedBlocks.children.unshift(yamlFrontMatter);
|
||||
}
|
||||
const filePathFromRoot = posix.join('packages/mermaid', originalFilename);
|
||||
yamlFrontMatter.value = dump({
|
||||
...(load(yamlFrontMatter.value, { schema: JSON_SCHEMA }) as
|
||||
| Record<string, unknown>
|
||||
| undefined),
|
||||
editLink: `https://github.com/mermaid-js/mermaid/edit/develop/${filePathFromRoot}`,
|
||||
});
|
||||
}
|
||||
|
||||
if (removeYAML) {
|
||||
const firstNode = astWithTransformedBlocks.children[0];
|
||||
if (firstNode.type == 'yaml') {
|
||||
|
@ -306,6 +337,7 @@ const transformMarkdown = (file: string) => {
|
|||
// mermaid project specific plugin
|
||||
originalFilename: file,
|
||||
addAutogeneratedWarning: !noHeader,
|
||||
addEditLink: noHeader,
|
||||
removeYAML: !noHeader,
|
||||
})
|
||||
.processSync(doc)
|
||||
|
@ -323,20 +355,10 @@ const transformMarkdown = (file: string) => {
|
|||
copyTransformedContents(file, !verifyOnly, formatted);
|
||||
};
|
||||
|
||||
import { load, JSON_SCHEMA } from 'js-yaml';
|
||||
// @ts-ignore: we're importing internal jsonschema2md functions
|
||||
import { default as schemaLoader } from '@adobe/jsonschema2md/lib/schemaProxy.js';
|
||||
// @ts-ignore: we're importing internal jsonschema2md functions
|
||||
import { default as traverseSchemas } from '@adobe/jsonschema2md/lib/traverseSchema.js';
|
||||
// @ts-ignore: we're importing internal jsonschema2md functions
|
||||
import { default as buildMarkdownFromSchema } from '@adobe/jsonschema2md/lib/markdownBuilder.js';
|
||||
// @ts-ignore: we're importing internal jsonschema2md functions
|
||||
import { default as jsonSchemaReadmeBuilder } from '@adobe/jsonschema2md/lib/readmeBuilder.js';
|
||||
|
||||
/**
|
||||
* Transforms the given JSON Schema into Markdown documentation
|
||||
*/
|
||||
async function transormJsonSchema(file: string) {
|
||||
async function transformJsonSchema(file: string) {
|
||||
const yamlContents = readSyncedUTF8file(file);
|
||||
const jsonSchema = load(yamlContents, {
|
||||
filename: file,
|
||||
|
@ -420,16 +442,18 @@ async function transormJsonSchema(file: string) {
|
|||
}
|
||||
});
|
||||
|
||||
const transformed = remark()
|
||||
const transformer = remark()
|
||||
.use(remarkGfm)
|
||||
.use(remarkFrontmatter, ['yaml']) // support YAML front-matter in Markdown
|
||||
.use(transformMarkdownAst, {
|
||||
// mermaid project specific plugin
|
||||
originalFilename: file,
|
||||
addAutogeneratedWarning: !noHeader,
|
||||
addEditLink: noHeader,
|
||||
removeYAML: !noHeader,
|
||||
})
|
||||
.stringify(markdownAst as Root);
|
||||
});
|
||||
|
||||
const transformed = transformer.stringify(await transformer.run(markdownAst as Root));
|
||||
|
||||
const formatted = prettier.format(transformed, {
|
||||
parser: 'markdown',
|
||||
|
@ -480,7 +504,7 @@ const transformHtml = (filename: string) => {
|
|||
copyTransformedContents(filename, !verifyOnly, formattedHTML);
|
||||
};
|
||||
|
||||
const getGlobs = (globs: string[]): string[] => {
|
||||
export const getGlobs = (globs: string[]): string[] => {
|
||||
globs.push('!**/dist/**', '!**/redirect.spec.ts', '!**/landing/**', '!**/node_modules/**');
|
||||
if (!vitepress) {
|
||||
globs.push(
|
||||
|
@ -494,12 +518,12 @@ const getGlobs = (globs: string[]): string[] => {
|
|||
return globs;
|
||||
};
|
||||
|
||||
const getFilesFromGlobs = async (globs: string[]): Promise<string[]> => {
|
||||
export const getFilesFromGlobs = async (globs: string[]): Promise<string[]> => {
|
||||
return await globby(globs, { dot: true });
|
||||
};
|
||||
|
||||
/** Main method (entry point) */
|
||||
const main = async () => {
|
||||
export const processDocs = async () => {
|
||||
if (verifyOnly) {
|
||||
console.log('Verifying that all files are in sync with the source files');
|
||||
}
|
||||
|
@ -509,7 +533,7 @@ const main = async () => {
|
|||
|
||||
if (vitepress) {
|
||||
console.log(`${action} 1 .schema.yaml file`);
|
||||
await transormJsonSchema('src/schemas/config.schema.yaml');
|
||||
await transformJsonSchema('src/schemas/config.schema.yaml');
|
||||
} else {
|
||||
// skip because this creates so many Markdown files that it lags git
|
||||
console.log('Skipping 1 .schema.yaml file');
|
||||
|
@ -577,5 +601,3 @@ const main = async () => {
|
|||
});
|
||||
}
|
||||
};
|
||||
|
||||
void main();
|
|
@ -105,6 +105,29 @@ This Markdown should be kept.
|
|||
});
|
||||
});
|
||||
|
||||
it('should add an editLink in the YAML frontmatter if `addEditLink: true`', async () => {
|
||||
const contents = `---
|
||||
title: Flowcharts Syntax
|
||||
---
|
||||
|
||||
This Markdown should be kept.
|
||||
`;
|
||||
const withYaml = (
|
||||
await remarkBuilder()
|
||||
.use(transformMarkdownAst, { originalFilename, addEditLink: true })
|
||||
.process(contents)
|
||||
).toString();
|
||||
expect(withYaml).toEqual(`---
|
||||
title: Flowcharts Syntax
|
||||
editLink: >-
|
||||
https://github.com/mermaid-js/mermaid/edit/develop/packages/mermaid/example-input-filename.md
|
||||
|
||||
---
|
||||
|
||||
This Markdown should be kept.
|
||||
`);
|
||||
});
|
||||
|
||||
describe('transformToBlockQuote', () => {
|
||||
// TODO Is there a way to test this with --vitepress given as a process argument?
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/* eslint-disable no-console */
|
||||
|
||||
/**
|
||||
* @file Update the MERMAID_RELEASE_VERSION placeholder in the documentation source files with the current version of mermaid.
|
||||
* So contributors adding new features will only have to add the placeholder and not worry about updating the version number.
|
||||
*
|
||||
*/
|
||||
import { posix } from 'path';
|
||||
import {
|
||||
getGlobs,
|
||||
getFilesFromGlobs,
|
||||
SOURCE_DOCS_DIR,
|
||||
readSyncedUTF8file,
|
||||
MERMAID_RELEASE_VERSION,
|
||||
} from './docs.mjs';
|
||||
import { writeFile } from 'fs/promises';
|
||||
|
||||
const verifyOnly: boolean = process.argv.includes('--verify');
|
||||
const versionPlaceholder = '<MERMAID_RELEASE_VERSION>';
|
||||
|
||||
const main = async () => {
|
||||
const sourceDirGlob = posix.join('.', SOURCE_DOCS_DIR, '**');
|
||||
const mdFileGlobs = getGlobs([posix.join(sourceDirGlob, '*.md')]);
|
||||
mdFileGlobs.push('!**/community/development.md');
|
||||
const mdFiles = await getFilesFromGlobs(mdFileGlobs);
|
||||
mdFiles.sort();
|
||||
const mdFilesWithPlaceholder: string[] = [];
|
||||
for (const mdFile of mdFiles) {
|
||||
const content = readSyncedUTF8file(mdFile);
|
||||
if (content.includes(versionPlaceholder)) {
|
||||
mdFilesWithPlaceholder.push(mdFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (mdFilesWithPlaceholder.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (verifyOnly) {
|
||||
console.log(
|
||||
`${mdFilesWithPlaceholder.length} file(s) were found with the placeholder ${versionPlaceholder}. Run \`pnpm --filter mermaid docs:release-version\` to update them.`
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
for (const mdFile of mdFilesWithPlaceholder) {
|
||||
const content = readSyncedUTF8file(mdFile);
|
||||
const newContent = content.replace(versionPlaceholder, MERMAID_RELEASE_VERSION);
|
||||
await writeFile(mdFile, newContent);
|
||||
}
|
||||
};
|
||||
|
||||
void main();
|
|
@ -19,12 +19,14 @@ let branchPos = {};
|
|||
let commitPos = {};
|
||||
let lanes = [];
|
||||
let maxPos = 0;
|
||||
let dir = 'LR';
|
||||
const clear = () => {
|
||||
branchPos = {};
|
||||
commitPos = {};
|
||||
allCommitsDict = {};
|
||||
maxPos = 0;
|
||||
lanes = [];
|
||||
dir = 'LR';
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -77,6 +79,10 @@ const drawCommits = (svg, commits, modifyGraph) => {
|
|||
const gLabels = svg.append('g').attr('class', 'commit-labels');
|
||||
let pos = 0;
|
||||
|
||||
if (dir === 'TB') {
|
||||
pos = 30;
|
||||
}
|
||||
|
||||
const keys = Object.keys(commits);
|
||||
const sortedKeys = keys.sort((a, b) => {
|
||||
return commits[a].seq - commits[b].seq;
|
||||
|
@ -84,8 +90,9 @@ const drawCommits = (svg, commits, modifyGraph) => {
|
|||
sortedKeys.forEach((key) => {
|
||||
const commit = commits[key];
|
||||
|
||||
const y = branchPos[commit.branch].pos;
|
||||
const x = pos + 10;
|
||||
const y = dir === 'TB' ? pos + 10 : branchPos[commit.branch].pos;
|
||||
const x = dir === 'TB' ? branchPos[commit.branch].pos : pos + 10;
|
||||
|
||||
// Don't draw the commits now but calculate the positioning which is used by the branch lines etc.
|
||||
if (modifyGraph) {
|
||||
let typeClass;
|
||||
|
@ -208,7 +215,11 @@ const drawCommits = (svg, commits, modifyGraph) => {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (dir === 'TB') {
|
||||
commitPos[commit.id] = { x: x, y: pos + 10 };
|
||||
} else {
|
||||
commitPos[commit.id] = { x: pos + 10, y: y };
|
||||
}
|
||||
|
||||
// The first iteration over the commits are for positioning purposes, this
|
||||
// is required for drawing the lines. The circles and labels is drawn after the labels
|
||||
|
@ -240,8 +251,20 @@ const drawCommits = (svg, commits, modifyGraph) => {
|
|||
.attr('y', y + 13.5)
|
||||
.attr('width', bbox.width + 2 * py)
|
||||
.attr('height', bbox.height + 2 * py);
|
||||
|
||||
if (dir === 'TB') {
|
||||
labelBkg.attr('x', x - (bbox.width + 4 * px + 5)).attr('y', y - 12);
|
||||
text.attr('x', x - (bbox.width + 4 * px)).attr('y', y + bbox.height - 12);
|
||||
}
|
||||
|
||||
if (dir !== 'TB') {
|
||||
text.attr('x', pos + 10 - bbox.width / 2);
|
||||
}
|
||||
if (gitGraphConfig.rotateCommitLabel) {
|
||||
if (dir === 'TB') {
|
||||
text.attr('transform', 'rotate(' + -45 + ', ' + x + ', ' + y + ')');
|
||||
labelBkg.attr('transform', 'rotate(' + -45 + ', ' + x + ', ' + y + ')');
|
||||
} else {
|
||||
let r_x = -7.5 - ((bbox.width + 10) / 25) * 9.5;
|
||||
let r_y = 10 + (bbox.width / 25) * 8.5;
|
||||
wrapper.attr(
|
||||
|
@ -250,6 +273,7 @@ const drawCommits = (svg, commits, modifyGraph) => {
|
|||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (commit.tag) {
|
||||
const rect = gLabels.insert('polygon');
|
||||
const hole = gLabels.append('circle');
|
||||
|
@ -280,6 +304,30 @@ const drawCommits = (svg, commits, modifyGraph) => {
|
|||
.attr('cy', ly)
|
||||
.attr('r', 1.5)
|
||||
.attr('class', 'tag-hole');
|
||||
|
||||
if (dir === 'TB') {
|
||||
rect
|
||||
.attr('class', 'tag-label-bkg')
|
||||
.attr(
|
||||
'points',
|
||||
`
|
||||
${x},${pos + py}
|
||||
${x},${pos - py}
|
||||
${x + 10},${pos - h2 - py}
|
||||
${x + 10 + tagBbox.width + px},${pos - h2 - py}
|
||||
${x + 10 + tagBbox.width + px},${pos + h2 + py}
|
||||
${x + 10},${pos + h2 + py}`
|
||||
)
|
||||
.attr('transform', 'translate(12,12) rotate(45, ' + x + ',' + pos + ')');
|
||||
hole
|
||||
.attr('cx', x + px / 2)
|
||||
.attr('cy', pos)
|
||||
.attr('transform', 'translate(12,12) rotate(45, ' + x + ',' + pos + ')');
|
||||
tag
|
||||
.attr('x', x + 5)
|
||||
.attr('y', pos + 3)
|
||||
.attr('transform', 'translate(14,14) rotate(45, ' + x + ',' + pos + ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
pos += 50;
|
||||
|
@ -365,16 +413,63 @@ const drawArrow = (svg, commit1, commit2, allCommits) => {
|
|||
colorClassNum = branchPos[commit2.branch].index;
|
||||
|
||||
const lineY = p1.y < p2.y ? findLane(p1.y, p2.y) : findLane(p2.y, p1.y);
|
||||
const lineX = p1.x < p2.x ? findLane(p1.x, p2.x) : findLane(p2.x, p1.x);
|
||||
|
||||
if (dir === 'TB') {
|
||||
if (p1.x < p2.x) {
|
||||
lineDef = `M ${p1.x} ${p1.y} L ${lineX - radius} ${p1.y} ${arc2} ${lineX} ${
|
||||
p1.y + offset
|
||||
} L ${lineX} ${p2.y - radius} ${arc} ${lineX + offset} ${p2.y} L ${p2.x} ${p2.y}`;
|
||||
} else {
|
||||
lineDef = `M ${p1.x} ${p1.y} L ${lineX + radius} ${p1.y} ${arc} ${lineX} ${
|
||||
p1.y + offset
|
||||
} L ${lineX} ${p2.y - radius} ${arc2} ${lineX - offset} ${p2.y} L ${p2.x} ${p2.y}`;
|
||||
}
|
||||
} else {
|
||||
if (p1.y < p2.y) {
|
||||
lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${lineY - radius} ${arc} ${p1.x + offset} ${lineY} L ${
|
||||
p2.x - radius
|
||||
} ${lineY} ${arc2} ${p2.x} ${lineY + offset} L ${p2.x} ${p2.y}`;
|
||||
lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${lineY - radius} ${arc} ${
|
||||
p1.x + offset
|
||||
} ${lineY} L ${p2.x - radius} ${lineY} ${arc2} ${p2.x} ${lineY + offset} L ${p2.x} ${p2.y}`;
|
||||
} else {
|
||||
lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${lineY + radius} ${arc2} ${
|
||||
p1.x + offset
|
||||
} ${lineY} L ${p2.x - radius} ${lineY} ${arc} ${p2.x} ${lineY - offset} L ${p2.x} ${p2.y}`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (dir === 'TB') {
|
||||
if (p1.x < p2.x) {
|
||||
arc = 'A 20 20, 0, 0, 0,';
|
||||
arc2 = 'A 20 20, 0, 0, 1,';
|
||||
radius = 20;
|
||||
offset = 20;
|
||||
|
||||
// Figure out the color of the arrow,arrows going down take the color from the destination branch
|
||||
colorClassNum = branchPos[commit2.branch].index;
|
||||
|
||||
lineDef = `M ${p1.x} ${p1.y} L ${p2.x - radius} ${p1.y} ${arc2} ${p2.x} ${
|
||||
p1.y + offset
|
||||
} L ${p2.x} ${p2.y}`;
|
||||
}
|
||||
if (p1.x > p2.x) {
|
||||
arc = 'A 20 20, 0, 0, 0,';
|
||||
arc2 = 'A 20 20, 0, 0, 1,';
|
||||
radius = 20;
|
||||
offset = 20;
|
||||
|
||||
// Arrows going up take the color from the source branch
|
||||
colorClassNum = branchPos[commit1.branch].index;
|
||||
lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${p2.y - radius} ${arc2} ${p1.x - offset} ${
|
||||
p2.y
|
||||
} L ${p2.x} ${p2.y}`;
|
||||
}
|
||||
|
||||
if (p1.x === p2.x) {
|
||||
colorClassNum = branchPos[commit1.branch].index;
|
||||
lineDef = `M ${p1.x} ${p1.y} L ${p1.x + radius} ${p1.y} ${arc} ${p1.x + offset} ${
|
||||
p2.y + radius
|
||||
} L ${p2.x} ${p2.y}`;
|
||||
}
|
||||
} else {
|
||||
if (p1.y < p2.y) {
|
||||
arc = 'A 20 20, 0, 0, 0,';
|
||||
|
@ -407,6 +502,7 @@ const drawArrow = (svg, commit1, commit2, allCommits) => {
|
|||
} ${p2.y}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
svg
|
||||
.append('path')
|
||||
.attr('d', lineDef)
|
||||
|
@ -445,6 +541,13 @@ const drawBranches = (svg, branches) => {
|
|||
line.attr('y2', pos);
|
||||
line.attr('class', 'branch branch' + adjustIndexForTheme);
|
||||
|
||||
if (dir === 'TB') {
|
||||
line.attr('y1', 30);
|
||||
line.attr('x1', pos);
|
||||
line.attr('y2', maxPos);
|
||||
line.attr('x2', pos);
|
||||
}
|
||||
|
||||
lanes.push(pos);
|
||||
|
||||
let name = branch.name;
|
||||
|
@ -467,7 +570,6 @@ const drawBranches = (svg, branches) => {
|
|||
.attr('y', -bbox.height / 2 + 8)
|
||||
.attr('width', bbox.width + 18)
|
||||
.attr('height', bbox.height + 4);
|
||||
|
||||
label.attr(
|
||||
'transform',
|
||||
'translate(' +
|
||||
|
@ -476,7 +578,13 @@ const drawBranches = (svg, branches) => {
|
|||
(pos - bbox.height / 2 - 1) +
|
||||
')'
|
||||
);
|
||||
if (dir === 'TB') {
|
||||
bkg.attr('x', pos - bbox.width / 2 - 10).attr('y', 0);
|
||||
label.attr('transform', 'translate(' + (pos - bbox.width / 2 - 5) + ', ' + 0 + ')');
|
||||
}
|
||||
if (dir !== 'TB') {
|
||||
bkg.attr('transform', 'translate(' + -19 + ', ' + (pos - bbox.height / 2) + ')');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -495,15 +603,24 @@ export const draw = function (txt, id, ver, diagObj) {
|
|||
|
||||
allCommitsDict = diagObj.db.getCommits();
|
||||
const branches = diagObj.db.getBranchesAsObjArray();
|
||||
|
||||
// Position branches vertically
|
||||
dir = diagObj.db.getDirection();
|
||||
const diagram = select(`[id="${id}"]`);
|
||||
// Position branches
|
||||
let pos = 0;
|
||||
branches.forEach((branch, index) => {
|
||||
branchPos[branch.name] = { pos, index };
|
||||
pos += 50 + (gitGraphConfig.rotateCommitLabel ? 40 : 0);
|
||||
});
|
||||
const labelElement = drawText(branch.name);
|
||||
const g = diagram.append('g');
|
||||
const branchLabel = g.insert('g').attr('class', 'branchLabel');
|
||||
const label = branchLabel.insert('g').attr('class', 'label branch-label');
|
||||
label.node().appendChild(labelElement);
|
||||
let bbox = labelElement.getBBox();
|
||||
|
||||
const diagram = select(`[id="${id}"]`);
|
||||
branchPos[branch.name] = { pos, index };
|
||||
pos += 50 + (gitGraphConfig.rotateCommitLabel ? 40 : 0) + (dir === 'TB' ? bbox.width / 2 : 0);
|
||||
label.remove();
|
||||
branchLabel.remove();
|
||||
g.remove();
|
||||
});
|
||||
|
||||
drawCommits(diagram, allCommitsDict, false);
|
||||
if (gitGraphConfig.showBranches) {
|
||||
|
|
|
@ -51,7 +51,7 @@ cherry\-pick(?=\s|$) return 'CHERRY_PICK';
|
|||
// "reset" return 'RESET';
|
||||
checkout(?=\s|$) return 'CHECKOUT';
|
||||
"LR" return 'DIR';
|
||||
"BT" return 'DIR';
|
||||
"TB" return 'DIR';
|
||||
":" return ':';
|
||||
"^" return 'CARET'
|
||||
"options"\r?\n this.begin("options"); //
|
||||
|
|
|
@ -35,7 +35,12 @@ export default defineConfig({
|
|||
themeConfig: {
|
||||
nav: nav(),
|
||||
editLink: {
|
||||
pattern: 'https://github.com/mermaid-js/mermaid/edit/develop/packages/mermaid/src/docs/:path',
|
||||
pattern: ({ filePath, frontmatter }) => {
|
||||
if (typeof frontmatter.editLink === 'string') {
|
||||
return frontmatter.editLink;
|
||||
}
|
||||
return `https://github.com/mermaid-js/mermaid/edit/develop/packages/mermaid/src/docs/${filePath}`;
|
||||
},
|
||||
text: 'Edit this page on GitHub',
|
||||
},
|
||||
sidebar: {
|
||||
|
|
|
@ -212,6 +212,9 @@ If the users have no way to know that things have changed, then you haven't real
|
|||
Likewise, if users don't know that there is a new feature that you've implemented, it will forever remain unknown and unused.
|
||||
|
||||
The documentation has to be updated to users know that things have changed and added!
|
||||
If you are adding a new feature, add `(v<MERMAID_RELEASE_VERSION>+)` in the title or description. It will be replaced automatically with the current version number when the release happens.
|
||||
|
||||
eg: `# Feature Name (v<MERMAID_RELEASE_VERSION>+)`
|
||||
|
||||
We know it can sometimes be hard to code _and_ write user documentation.
|
||||
|
||||
|
|
|
@ -511,6 +511,50 @@ NOTE: Because we have overridden the `mainBranchOrder` to `2`, the `main` branch
|
|||
|
||||
Here, we have changed the default main branch name to `MetroLine1`.
|
||||
|
||||
## Orientation
|
||||
|
||||
In Mermaid, the default orientation is Left to Right. The branches are lined vertically.
|
||||
|
||||
Usage example:
|
||||
|
||||
```mermaid-example
|
||||
gitGraph
|
||||
commit
|
||||
commit
|
||||
branch develop
|
||||
commit
|
||||
commit
|
||||
commit
|
||||
checkout main
|
||||
commit
|
||||
commit
|
||||
merge develop
|
||||
commit
|
||||
commit
|
||||
```
|
||||
|
||||
Sometimes we may want to change the orientation. Currently, Mermaid supports two orientations: **Left to Right**(default) and **Top to Bottom**.
|
||||
|
||||
In order to change the orientation from top to bottom i.e. branches lined horizontally, you need to add `TB` along with `gitGraph`.
|
||||
|
||||
Usage example:
|
||||
|
||||
```mermaid-example
|
||||
gitGraph TB:
|
||||
commit
|
||||
commit
|
||||
branch develop
|
||||
commit
|
||||
commit
|
||||
commit
|
||||
checkout main
|
||||
commit
|
||||
commit
|
||||
merge develop
|
||||
commit
|
||||
commit
|
||||
```
|
||||
|
||||
## Themes
|
||||
|
||||
Mermaid supports a bunch of pre-defined themes which you can use to find the right one for you. PS: you can actually override an existing theme's variable to get your own custom theme going. Learn more about theming your diagram [here](../config/theming.md).
|
||||
|
|
|
@ -12469,7 +12469,7 @@ packages:
|
|||
levn: 0.3.0
|
||||
prelude-ls: 1.1.2
|
||||
type-check: 0.3.2
|
||||
word-wrap: 1.2.3
|
||||
word-wrap: 1.2.4
|
||||
dev: true
|
||||
|
||||
/optionator@0.9.1:
|
||||
|
@ -12481,7 +12481,7 @@ packages:
|
|||
levn: 0.4.1
|
||||
prelude-ls: 1.2.1
|
||||
type-check: 0.4.0
|
||||
word-wrap: 1.2.3
|
||||
word-wrap: 1.2.4
|
||||
dev: true
|
||||
|
||||
/ospath@1.2.2:
|
||||
|
@ -16073,8 +16073,8 @@ packages:
|
|||
resolution: {integrity: sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==}
|
||||
dev: true
|
||||
|
||||
/word-wrap@1.2.3:
|
||||
resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==}
|
||||
/word-wrap@1.2.4:
|
||||
resolution: {integrity: sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
|
|
Loading…
Reference in New Issue