mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-14 06:43:25 +08:00
#1252 Adding confuration options and some cleanup, swicth of graphType from git to gitGraph
This commit is contained in:
parent
57ac111d05
commit
87b56bdd9a
@ -9,7 +9,7 @@
|
|||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
/* background: rgb(221, 208, 208); */
|
/* background: rgb(221, 208, 208); */
|
||||||
background:#111;
|
/* background:#111; */
|
||||||
/* background:#333; */
|
/* background:#333; */
|
||||||
font-family: 'Arial';
|
font-family: 'Arial';
|
||||||
}
|
}
|
||||||
@ -43,6 +43,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="mermaid" style="width: 100%; height: 20%;">
|
<div class="mermaid" style="width: 100%; height: 20%;">
|
||||||
|
%%{init: { "gitGraph": { "showBranches": false, "mainBranchName": "APA" }}}%%
|
||||||
gitGraph
|
gitGraph
|
||||||
commit
|
commit
|
||||||
branch hotfix
|
branch hotfix
|
||||||
@ -101,7 +102,7 @@
|
|||||||
// console.error('Mermaid error: ', err);
|
// console.error('Mermaid error: ', err);
|
||||||
};
|
};
|
||||||
mermaid.initialize({
|
mermaid.initialize({
|
||||||
theme: 'dark',
|
theme: 'default',
|
||||||
themeVariables: {
|
themeVariables: {
|
||||||
// primaryColor: '#9400D3',
|
// primaryColor: '#9400D3',
|
||||||
// darkMode: false,
|
// darkMode: false,
|
||||||
@ -119,6 +120,7 @@
|
|||||||
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
|
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
|
||||||
logLevel: 1,
|
logLevel: 1,
|
||||||
flowchart: { curve: 'linear', htmlLabels: true },
|
flowchart: { curve: 'linear', htmlLabels: true },
|
||||||
|
// gitGraph: { showCommitLabel: false },
|
||||||
// gantt: { axisFormat: '%m/%d/%Y' },
|
// gantt: { axisFormat: '%m/%d/%Y' },
|
||||||
sequence: { actorMargin: 50, showSequenceNumbers: true },
|
sequence: { actorMargin: 50, showSequenceNumbers: true },
|
||||||
// sequenceDiagram: { actorMargin: 300 } // deprecated
|
// sequenceDiagram: { actorMargin: 300 } // deprecated
|
||||||
|
@ -756,19 +756,6 @@ available space if not the absolute space required is used.
|
|||||||
|
|
||||||
Default value: true
|
Default value: true
|
||||||
|
|
||||||
## useMaxWidth
|
|
||||||
|
|
||||||
| Parameter | Description | Type | Required | Values |
|
|
||||||
| ----------- | ----------- | ------- | -------- | ----------- |
|
|
||||||
| useMaxWidth | See notes | boolean | 4 | true, false |
|
|
||||||
|
|
||||||
**Notes:**
|
|
||||||
|
|
||||||
When this flag is set the height and width is set to 100% and is then scaling with the
|
|
||||||
available space if not the absolute space required is used.
|
|
||||||
|
|
||||||
Default value: true
|
|
||||||
|
|
||||||
## defaultRenderer
|
## defaultRenderer
|
||||||
|
|
||||||
| Parameter | Description | Type | Required | Values |
|
| Parameter | Description | Type | Required | Values |
|
||||||
|
@ -49,7 +49,7 @@ class Diagram {
|
|||||||
this.type = utils.detectType(txt, cnf);
|
this.type = utils.detectType(txt, cnf);
|
||||||
log.debug('Type ' + this.type);
|
log.debug('Type ' + this.type);
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case 'git':
|
case 'gitGraph':
|
||||||
this.parser = gitGraphParser;
|
this.parser = gitGraphParser;
|
||||||
this.parser.parser.yy = gitGraphAst;
|
this.parser.parser.yy = gitGraphAst;
|
||||||
this.db = gitGraphAst;
|
this.db = gitGraphAst;
|
||||||
|
@ -1,162 +0,0 @@
|
|||||||
import { assignWithDepth } from './utils';
|
|
||||||
import { log } from './logger'; // eslint-disable-line
|
|
||||||
import theme from './themes';
|
|
||||||
import config from './defaultConfig';
|
|
||||||
|
|
||||||
const handleThemeVariables = (value) => {
|
|
||||||
return theme[value] ? theme[value].getThemeVariables() : theme.default.getThemeVariables();
|
|
||||||
};
|
|
||||||
|
|
||||||
const manipulators = {
|
|
||||||
themeVariables: handleThemeVariables,
|
|
||||||
};
|
|
||||||
|
|
||||||
// debugger;
|
|
||||||
config.class.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
|
||||||
config.git.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
|
||||||
export const defaultConfig = Object.freeze(config);
|
|
||||||
|
|
||||||
const siteConfig = assignWithDepth({}, defaultConfig);
|
|
||||||
const currentConfig = assignWithDepth({}, defaultConfig);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ## setSiteConfig
|
|
||||||
*
|
|
||||||
* | Function | Description | Type | Values |
|
|
||||||
* | ------------- | ------------------------------------- | ----------- | --------------------------------------- |
|
|
||||||
* | setSiteConfig | Sets the siteConfig to desired values | Put Request | Any Values, except ones in secure array |
|
|
||||||
*
|
|
||||||
* **Notes:** Sets the siteConfig. The siteConfig is a protected configuration for repeat use. Calls
|
|
||||||
* to reset() will reset the currentConfig to siteConfig. Calls to reset(configApi.defaultConfig)
|
|
||||||
* will reset siteConfig and currentConfig to the defaultConfig Note: currentConfig is set in this
|
|
||||||
* function Default value: At default, will mirror Global Config
|
|
||||||
*
|
|
||||||
* @param {any} conf - The base currentConfig to use as siteConfig
|
|
||||||
* @returns {any} - The siteConfig
|
|
||||||
*/
|
|
||||||
export const setSiteConfig = (conf) => {
|
|
||||||
console.log('setSiteConfig');
|
|
||||||
|
|
||||||
Object.keys(conf).forEach((key) => {
|
|
||||||
const manipulator = manipulators[key];
|
|
||||||
conf[key] = manipulator ? manipulator(conf[key]) : conf[key];
|
|
||||||
});
|
|
||||||
|
|
||||||
assignWithDepth(currentConfig, conf, { clobber: true });
|
|
||||||
// Set theme variables if user has set the theme option
|
|
||||||
assignWithDepth(siteConfig, conf);
|
|
||||||
|
|
||||||
return getSiteConfig();
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* ## getSiteConfig
|
|
||||||
*
|
|
||||||
* | Function | Description | Type | Values |
|
|
||||||
* | ------------- | ------------------------------------------------- | ----------- | -------------------------------- |
|
|
||||||
* | setSiteConfig | Returns the current siteConfig base configuration | Get Request | Returns Any Values in siteConfig |
|
|
||||||
*
|
|
||||||
* **Notes**: Returns **any** values in siteConfig.
|
|
||||||
*
|
|
||||||
* @returns {any}
|
|
||||||
*/
|
|
||||||
export const getSiteConfig = () => {
|
|
||||||
return assignWithDepth({}, siteConfig);
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* ## setConfig
|
|
||||||
*
|
|
||||||
* | Function | Description | Type | Values |
|
|
||||||
* | ------------- | ------------------------------------- | ----------- | --------------------------------------- |
|
|
||||||
* | setSiteConfig | Sets the siteConfig to desired values | Put Request | Any Values, except ones in secure array |
|
|
||||||
*
|
|
||||||
* **Notes**: Sets the currentConfig. The parameter conf is sanitized based on the siteConfig.secure
|
|
||||||
* keys. Any values found in conf with key found in siteConfig.secure will be replaced with the
|
|
||||||
* corresponding siteConfig value.
|
|
||||||
*
|
|
||||||
* @param {any} conf - The potential currentConfig
|
|
||||||
* @returns {any} - The currentConfig merged with the sanitized conf
|
|
||||||
*/
|
|
||||||
export const setConfig = (conf) => {
|
|
||||||
console.log('setConfig');
|
|
||||||
sanitize(conf);
|
|
||||||
Object.keys(conf).forEach((key) => {
|
|
||||||
const manipulator = manipulators[key];
|
|
||||||
conf[key] = manipulator ? manipulator(conf[key]) : conf[key];
|
|
||||||
});
|
|
||||||
|
|
||||||
assignWithDepth(currentConfig, conf);
|
|
||||||
return getConfig();
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* ## getConfig
|
|
||||||
*
|
|
||||||
* | Function | Description | Type | Return Values |
|
|
||||||
* | --------- | ------------------------- | ----------- | ----------------------------- |
|
|
||||||
* | getConfig | Obtains the currentConfig | Get Request | Any Values from currentConfig |
|
|
||||||
*
|
|
||||||
* **Notes**: Returns **any** the currentConfig
|
|
||||||
*
|
|
||||||
* @returns {any} - The currentConfig
|
|
||||||
*/
|
|
||||||
export const getConfig = () => {
|
|
||||||
return assignWithDepth({}, currentConfig);
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* ## sanitize
|
|
||||||
*
|
|
||||||
* | Function | Description | Type | Values |
|
|
||||||
* | -------- | -------------------------------------- | ----------- | ------ |
|
|
||||||
* | sanitize | Sets the siteConfig to desired values. | Put Request | None |
|
|
||||||
*
|
|
||||||
* Ensures options parameter does not attempt to override siteConfig secure keys **Notes**: modifies
|
|
||||||
* options in-place
|
|
||||||
*
|
|
||||||
* @param {any} options - The potential setConfig parameter
|
|
||||||
*/
|
|
||||||
export const sanitize = (options) => {
|
|
||||||
Object.keys(siteConfig.secure).forEach((key) => {
|
|
||||||
if (typeof options[siteConfig.secure[key]] !== 'undefined') {
|
|
||||||
// DO NOT attempt to print options[siteConfig.secure[key]] within `${}` as a malicious script
|
|
||||||
// can exploit the logger's attempt to stringify the value and execute arbitrary code
|
|
||||||
log.trace(
|
|
||||||
`Denied attempt to modify a secure key ${siteConfig.secure[key]}`,
|
|
||||||
options[siteConfig.secure[key]]
|
|
||||||
);
|
|
||||||
delete options[siteConfig.secure[key]];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* ## reset
|
|
||||||
*
|
|
||||||
* | Function | Description | Type | Required | Values |
|
|
||||||
* | -------- | ---------------------------- | ----------- | -------- | ------ |
|
|
||||||
* | reset | Resets currentConfig to conf | Put Request | Required | None |
|
|
||||||
*
|
|
||||||
* | Parameter | Description |Type | Required | Values|
|
|
||||||
*
|
|
||||||
* | --- | --- | --- | --- | --- |
|
|
||||||
* | conf| base set of values, which currentConfig coul be **reset** to.| Dictionary | Required | Any Values, with respect to the secure Array|
|
|
||||||
*
|
|
||||||
* **Notes**: (default: current siteConfig ) (optional, default `getSiteConfig()`)
|
|
||||||
*
|
|
||||||
* @param {any} conf - The base currentConfig to reset to (default: current siteConfig )
|
|
||||||
*/
|
|
||||||
export const reset = (conf = getSiteConfig()) => {
|
|
||||||
console.warn('reset');
|
|
||||||
Object.keys(siteConfig).forEach((key) => delete siteConfig[key]);
|
|
||||||
Object.keys(currentConfig).forEach((key) => delete currentConfig[key]);
|
|
||||||
assignWithDepth(siteConfig, conf, { clobber: true });
|
|
||||||
assignWithDepth(currentConfig, conf, { clobber: true });
|
|
||||||
};
|
|
||||||
|
|
||||||
const configApi = Object.freeze({
|
|
||||||
sanitize,
|
|
||||||
setSiteConfig,
|
|
||||||
getSiteConfig,
|
|
||||||
setConfig,
|
|
||||||
getConfig,
|
|
||||||
reset,
|
|
||||||
defaultConfig,
|
|
||||||
});
|
|
||||||
export default configApi;
|
|
@ -844,25 +844,6 @@ const config = {
|
|||||||
*/
|
*/
|
||||||
defaultRenderer: 'dagre-wrapper',
|
defaultRenderer: 'dagre-wrapper',
|
||||||
},
|
},
|
||||||
git: {
|
|
||||||
arrowMarkerAbsolute: false,
|
|
||||||
|
|
||||||
useWidth: undefined,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* | Parameter | Description | Type | Required | Values |
|
|
||||||
* | ----------- | ----------- | ------- | -------- | ----------- |
|
|
||||||
* | useMaxWidth | See notes | boolean | 4 | true, false |
|
|
||||||
*
|
|
||||||
* **Notes:**
|
|
||||||
*
|
|
||||||
* When this flag is set the height and width is set to 100% and is then scaling with the
|
|
||||||
* available space if not the absolute space required is used.
|
|
||||||
*
|
|
||||||
* Default value: true
|
|
||||||
*/
|
|
||||||
useMaxWidth: true,
|
|
||||||
},
|
|
||||||
state: {
|
state: {
|
||||||
dividerMargin: 10,
|
dividerMargin: 10,
|
||||||
sizeUnit: 5,
|
sizeUnit: 5,
|
||||||
@ -1066,27 +1047,20 @@ const config = {
|
|||||||
},
|
},
|
||||||
gitGraph: {
|
gitGraph: {
|
||||||
diagramPadding: 8,
|
diagramPadding: 8,
|
||||||
nodeSpacing: 150,
|
|
||||||
nodeFillColor: 'yellow',
|
|
||||||
nodeStrokeWidth: 2,
|
|
||||||
nodeStrokeColor: 'grey',
|
|
||||||
lineStrokeWidth: 4,
|
|
||||||
branchOffset: 50,
|
|
||||||
lineColor: 'grey',
|
|
||||||
leftMargin: 50,
|
|
||||||
branchColors: ['#442f74', '#983351', '#609732', '#AA9A39'],
|
|
||||||
nodeRadius: 10,
|
|
||||||
nodeLabel: {
|
nodeLabel: {
|
||||||
width: 75,
|
width: 75,
|
||||||
height: 100,
|
height: 100,
|
||||||
x: -25,
|
x: -25,
|
||||||
y: 0,
|
y: 0,
|
||||||
},
|
},
|
||||||
|
mainBranchName: 'main',
|
||||||
|
showCommitLabel: true,
|
||||||
|
showBranches: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
config.class.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
config.class.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||||||
config.git.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
config.gitGraph.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||||||
|
|
||||||
const keyify = (obj, prefix = '') =>
|
const keyify = (obj, prefix = '') =>
|
||||||
Object.keys(obj).reduce((res, el) => {
|
Object.keys(obj).reduce((res, el) => {
|
||||||
|
@ -220,7 +220,6 @@ export const merge = function (otherBranch) {
|
|||||||
|
|
||||||
export const checkout = function (branch) {
|
export const checkout = function (branch) {
|
||||||
branch = common.sanitizeText(branch, configApi.getConfig());
|
branch = common.sanitizeText(branch, configApi.getConfig());
|
||||||
console.info(branches);
|
|
||||||
if (typeof branches[branch] === 'undefined') {
|
if (typeof branches[branch] === 'undefined') {
|
||||||
let error = new Error(
|
let error = new Error(
|
||||||
'Trying to checkout branch which is not yet created. (Help try using "branch ' + branch + '")'
|
'Trying to checkout branch which is not yet created. (Help try using "branch ' + branch + '")'
|
||||||
@ -238,9 +237,6 @@ export const checkout = function (branch) {
|
|||||||
} else {
|
} else {
|
||||||
curBranch = branch;
|
curBranch = branch;
|
||||||
const id = branches[curBranch];
|
const id = branches[curBranch];
|
||||||
console.log(id);
|
|
||||||
console.log('hi');
|
|
||||||
console.log(commits);
|
|
||||||
head = commits[id];
|
head = commits[id];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,18 +1,12 @@
|
|||||||
/* eslint-disable */
|
|
||||||
import { curveBasis, line, select } from 'd3';
|
import { curveBasis, line, select } from 'd3';
|
||||||
import { interpolateToCurve, getStylesFromArray, configureSvgSize } from '../../utils';
|
import { interpolateToCurve, getStylesFromArray, configureSvgSize } from '../../utils';
|
||||||
import db from './gitGraphAst';
|
import db from './gitGraphAst';
|
||||||
//import * as db from './mockDb';
|
|
||||||
import gitGraphParser from './parser/gitGraph';
|
import gitGraphParser from './parser/gitGraph';
|
||||||
import { log } from '../../logger';
|
import { log } from '../../logger';
|
||||||
/* eslint-disable */
|
|
||||||
import { getConfig } from '../../config';
|
import { getConfig } from '../../config';
|
||||||
//import * as configApi from '../../config';
|
|
||||||
let allCommitsDict = {};
|
let allCommitsDict = {};
|
||||||
let branchNum;
|
let branchNum;
|
||||||
|
|
||||||
//let conf = configApi.getConfig();
|
|
||||||
//const commitType = db.commitType;
|
|
||||||
const commitType = {
|
const commitType = {
|
||||||
NORMAL: 0,
|
NORMAL: 0,
|
||||||
REVERSE: 1,
|
REVERSE: 1,
|
||||||
@ -29,89 +23,55 @@ const clear = () => {
|
|||||||
commitPos = {};
|
commitPos = {};
|
||||||
allCommitsDict = {};
|
allCommitsDict = {};
|
||||||
maxPos = 0;
|
maxPos = 0;
|
||||||
lanes = []
|
lanes = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
// let apiConfig = {};
|
|
||||||
// export const setConf = function(c) {
|
|
||||||
// apiConfig = c;
|
|
||||||
// };
|
|
||||||
/** @param svg */
|
|
||||||
function svgCreateDefs(svg) {
|
|
||||||
const config = getConfig().gitGraph;
|
|
||||||
svg
|
|
||||||
.append('defs')
|
|
||||||
.append('g')
|
|
||||||
.attr('id', 'def-commit')
|
|
||||||
.append('circle')
|
|
||||||
.attr('r', config.nodeRadius)
|
|
||||||
.attr('cx', 0)
|
|
||||||
.attr('cy', 0);
|
|
||||||
svg
|
|
||||||
.select('#def-commit')
|
|
||||||
.append('foreignObject')
|
|
||||||
.attr('width', config.nodeLabel.width)
|
|
||||||
.attr('height', config.nodeLabel.height)
|
|
||||||
.attr('x', config.nodeLabel.x)
|
|
||||||
.attr('y', config.nodeLabel.y)
|
|
||||||
.attr('class', 'node-label')
|
|
||||||
.attr('requiredFeatures', 'http://www.w3.org/TR/SVG11/feature#Extensibility')
|
|
||||||
.append('p')
|
|
||||||
.html('');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param svg
|
* Draws a text, used for labels of the branches
|
||||||
* @param points
|
|
||||||
* @param colorIdx
|
|
||||||
* @param interpolate
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
// Pass in the element and its pre-transform coords
|
|
||||||
*
|
*
|
||||||
* @param element
|
* @param {string} txt The text
|
||||||
* @param coords
|
* @returns {SVGElement}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @param svg
|
|
||||||
* @param fromId
|
|
||||||
* @param toId
|
|
||||||
* @param direction
|
|
||||||
* @param color
|
|
||||||
*/
|
|
||||||
|
|
||||||
const drawText = (txt) => {
|
const drawText = (txt) => {
|
||||||
const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||||
// svgLabel.setAttribute('style', style.replace('color:', 'fill:'));
|
let rows = [];
|
||||||
let rows = [];
|
|
||||||
|
|
||||||
if (typeof txt === 'string') {
|
// Handling of new lines in the label
|
||||||
rows = txt.split(/\\n|\n|<br\s*\/?>/gi);
|
if (typeof txt === 'string') {
|
||||||
} else if (Array.isArray(txt)) {
|
rows = txt.split(/\\n|\n|<br\s*\/?>/gi);
|
||||||
rows = txt;
|
} else if (Array.isArray(txt)) {
|
||||||
} else {
|
rows = txt;
|
||||||
rows = [];
|
} else {
|
||||||
}
|
rows = [];
|
||||||
|
|
||||||
for (let j = 0; j < rows.length; j++) {
|
|
||||||
const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
|
|
||||||
tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
|
|
||||||
tspan.setAttribute('dy', '1em');
|
|
||||||
tspan.setAttribute('x', '0');
|
|
||||||
tspan.setAttribute('class', 'row');
|
|
||||||
tspan.textContent = rows[j].trim();
|
|
||||||
svgLabel.appendChild(tspan);
|
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param svg
|
for (let j = 0; j < rows.length; j++) {
|
||||||
* @param selector
|
const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
|
||||||
*/
|
tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
|
||||||
|
tspan.setAttribute('dy', '1em');
|
||||||
|
tspan.setAttribute('x', '0');
|
||||||
|
tspan.setAttribute('class', 'row');
|
||||||
|
tspan.textContent = rows[j].trim();
|
||||||
|
svgLabel.appendChild(tspan);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param svg
|
||||||
|
* @param selector
|
||||||
|
*/
|
||||||
return svgLabel;
|
return svgLabel;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the commits with its symbol and labels. The function has tywo modes, one which only
|
||||||
|
* calculates the positions and one that does the actual drawing. This for a simple way getting the
|
||||||
|
* vertical leyering rcorrect in the graph.
|
||||||
|
*
|
||||||
|
* @param {any} svg
|
||||||
|
* @param {any} commits
|
||||||
|
* @param {any} modifyGraph
|
||||||
|
*/
|
||||||
const drawCommits = (svg, commits, modifyGraph) => {
|
const drawCommits = (svg, commits, modifyGraph) => {
|
||||||
|
const gitGraphConfig = getConfig().gitGraph;
|
||||||
const gBullets = svg.append('g').attr('class', 'commit-bullets');
|
const gBullets = svg.append('g').attr('class', 'commit-bullets');
|
||||||
const gLabels = svg.append('g').attr('class', 'commit-labels');
|
const gLabels = svg.append('g').attr('class', 'commit-labels');
|
||||||
let pos = 0;
|
let pos = 0;
|
||||||
@ -119,20 +79,20 @@ const drawCommits = (svg, commits, modifyGraph) => {
|
|||||||
const keys = Object.keys(commits);
|
const keys = Object.keys(commits);
|
||||||
const sortedKeys = keys.sort((a, b) => {
|
const sortedKeys = keys.sort((a, b) => {
|
||||||
return commits[a].seq - commits[b].seq;
|
return commits[a].seq - commits[b].seq;
|
||||||
})
|
});
|
||||||
sortedKeys.forEach((key, index) => {
|
sortedKeys.forEach((key, index) => {
|
||||||
const commit = commits[key];
|
const commit = commits[key];
|
||||||
|
|
||||||
const y = branchPos[commit.branch].pos;
|
const y = branchPos[commit.branch].pos;
|
||||||
const x = pos + 10;
|
const x = pos + 10;
|
||||||
// Don't draw the commits now but calculate the positioning which is used by the branmch lines etc.
|
// Don't draw the commits now but calculate the positioning which is used by the branch lines etc.
|
||||||
if (modifyGraph) {
|
if (modifyGraph) {
|
||||||
let typeClass;
|
let typeClass;
|
||||||
switch(commit.type) {
|
switch (commit.type) {
|
||||||
case commitType.NORMAL:
|
case commitType.NORMAL:
|
||||||
typeClass = 'commit-normal';
|
typeClass = 'commit-normal';
|
||||||
break;
|
break;
|
||||||
case commitType.REVERSE:
|
case commitType.REVERSE:
|
||||||
typeClass = 'commit-reverse';
|
typeClass = 'commit-reverse';
|
||||||
break;
|
break;
|
||||||
case commitType.HIGHLIGHT:
|
case commitType.HIGHLIGHT:
|
||||||
@ -147,51 +107,77 @@ const drawCommits = (svg, commits, modifyGraph) => {
|
|||||||
|
|
||||||
if (commit.type === commitType.HIGHLIGHT) {
|
if (commit.type === commitType.HIGHLIGHT) {
|
||||||
const circle = gBullets.append('rect');
|
const circle = gBullets.append('rect');
|
||||||
circle.attr('x', x-10);
|
circle.attr('x', x - 10);
|
||||||
circle.attr('y', y-10);
|
circle.attr('y', y - 10);
|
||||||
circle.attr('height', 20);
|
circle.attr('height', 20);
|
||||||
circle.attr('width', 20);
|
circle.attr('width', 20);
|
||||||
circle.attr('class', 'commit ' + commit.id + ' commit-highlight' + branchPos[commit.branch].index + ' ' + typeClass+'-outer');
|
circle.attr(
|
||||||
gBullets.append('rect')
|
'class',
|
||||||
.attr('x', x-6)
|
'commit ' +
|
||||||
.attr('y', y-6)
|
commit.id +
|
||||||
.attr('height', 12)
|
' commit-highlight' +
|
||||||
.attr('width', 12)
|
branchPos[commit.branch].index +
|
||||||
.attr('class', 'commit ' + commit.id + ' commit' + branchPos[commit.branch].index + ' ' + typeClass+'-inner');
|
' ' +
|
||||||
|
typeClass +
|
||||||
|
'-outer'
|
||||||
|
);
|
||||||
|
gBullets
|
||||||
|
.append('rect')
|
||||||
|
.attr('x', x - 6)
|
||||||
|
.attr('y', y - 6)
|
||||||
|
.attr('height', 12)
|
||||||
|
.attr('width', 12)
|
||||||
|
.attr(
|
||||||
|
'class',
|
||||||
|
'commit ' +
|
||||||
|
commit.id +
|
||||||
|
' commit' +
|
||||||
|
branchPos[commit.branch].index +
|
||||||
|
' ' +
|
||||||
|
typeClass +
|
||||||
|
'-inner'
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
const circle = gBullets.append('circle');
|
const circle = gBullets.append('circle');
|
||||||
circle.attr('cx', x);
|
circle.attr('cx', x);
|
||||||
circle.attr('cy', y);
|
circle.attr('cy', y);
|
||||||
circle.attr('r', commit.type === commitType.MERGE ? 9:10);
|
circle.attr('r', commit.type === commitType.MERGE ? 9 : 10);
|
||||||
circle.attr('class', 'commit ' + commit.id + ' commit' + branchPos[commit.branch].index);
|
circle.attr('class', 'commit ' + commit.id + ' commit' + branchPos[commit.branch].index);
|
||||||
if(commit.type === commitType.MERGE) {
|
if (commit.type === commitType.MERGE) {
|
||||||
const circle2 = gBullets.append('circle');
|
const circle2 = gBullets.append('circle');
|
||||||
circle2.attr('cx', x);
|
circle2.attr('cx', x);
|
||||||
circle2.attr('cy', y);
|
circle2.attr('cy', y);
|
||||||
circle2.attr('r', 6);
|
circle2.attr('r', 6);
|
||||||
circle2.attr('class', 'commit '+typeClass + ' ' + commit.id + ' commit' + branchPos[commit.branch].index);
|
circle2.attr(
|
||||||
|
'class',
|
||||||
|
'commit ' + typeClass + ' ' + commit.id + ' commit' + branchPos[commit.branch].index
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if(commit.type === commitType.REVERSE) {
|
if (commit.type === commitType.REVERSE) {
|
||||||
const cross = gBullets.append('path');
|
const cross = gBullets.append('path');
|
||||||
cross
|
cross
|
||||||
.attr('d', `M ${x-5},${y-5}L${x+5},${y+5}M${x-5},${y+5}L${x+5},${y-5}`)
|
.attr('d', `M ${x - 5},${y - 5}L${x + 5},${y + 5}M${x - 5},${y + 5}L${x + 5},${y - 5}`)
|
||||||
.attr('class', 'commit '+typeClass + ' ' + commit.id + ' commit' + branchPos[commit.branch].index);
|
.attr(
|
||||||
|
'class',
|
||||||
|
'commit ' + typeClass + ' ' + commit.id + ' commit' + branchPos[commit.branch].index
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
commitPos[commit.id] = {x: pos + 10, y: y};
|
commitPos[commit.id] = { x: pos + 10, y: y };
|
||||||
|
|
||||||
// The first iteration over the commits are for positioning purposes, this
|
// 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
|
// is required for drawing the lines. The circles and labels is drawn after the labels
|
||||||
// placing them on top of the lines.
|
// placing them on top of the lines.
|
||||||
if (modifyGraph) {
|
if (modifyGraph) {
|
||||||
const px=4;
|
const px = 4;
|
||||||
const py=2;
|
const py = 2;
|
||||||
if(commit.type !== commitType.MERGE) {
|
// Draw the commit label
|
||||||
const labelBkg = gLabels.insert('rect')
|
if (commit.type !== commitType.MERGE && gitGraphConfig.showCommitLabel) {
|
||||||
.attr('class', 'commit-label-bkg');
|
const labelBkg = gLabels.insert('rect').attr('class', 'commit-label-bkg');
|
||||||
|
|
||||||
const text = gLabels.append('text')
|
const text = gLabels
|
||||||
|
.append('text')
|
||||||
.attr('x', pos)
|
.attr('x', pos)
|
||||||
.attr('y', y + 25)
|
.attr('y', y + 25)
|
||||||
.attr('class', 'commit-label')
|
.attr('class', 'commit-label')
|
||||||
@ -206,48 +192,52 @@ const drawCommits = (svg, commits, modifyGraph) => {
|
|||||||
.attr('height', bbox.height + 2 * py);
|
.attr('height', bbox.height + 2 * py);
|
||||||
text.attr('x', pos + 10 - bbox.width / 2);
|
text.attr('x', pos + 10 - bbox.width / 2);
|
||||||
}
|
}
|
||||||
if(commit.tag) {
|
if (commit.tag) {
|
||||||
const rect = gLabels.insert('polygon');
|
const rect = gLabels.insert('polygon');
|
||||||
const hole = gLabels.append('circle');
|
const hole = gLabels.append('circle');
|
||||||
const tag = gLabels.append('text')
|
const tag = gLabels
|
||||||
// Note that we are delaying setting the x position until we know the width of the text
|
.append('text')
|
||||||
.attr('y', y - 16)
|
// Note that we are delaying setting the x position until we know the width of the text
|
||||||
.attr('class', 'tag-label')
|
.attr('y', y - 16)
|
||||||
.text(commit.tag);
|
.attr('class', 'tag-label')
|
||||||
|
.text(commit.tag);
|
||||||
let tagBbox = tag.node().getBBox();
|
let tagBbox = tag.node().getBBox();
|
||||||
tag.attr('x', pos + 10 - tagBbox.width / 2);
|
tag.attr('x', pos + 10 - tagBbox.width / 2);
|
||||||
|
|
||||||
const h2 = tagBbox.height/2
|
const h2 = tagBbox.height / 2;
|
||||||
const ly = y - 19.2 ;
|
const ly = y - 19.2;
|
||||||
rect
|
rect.attr('class', 'tag-label-bkg').attr(
|
||||||
.attr('class', 'tag-label-bkg')
|
'points',
|
||||||
.attr('points', `
|
`
|
||||||
${pos - tagBbox.width / 2 - px/2},${ly + py}
|
${pos - tagBbox.width / 2 - px / 2},${ly + py}
|
||||||
${pos - tagBbox.width / 2 - px/2},${ly - py}
|
${pos - tagBbox.width / 2 - px / 2},${ly - py}
|
||||||
${pos + 10 - tagBbox.width / 2 - px},${ly - h2 - py}
|
${pos + 10 - tagBbox.width / 2 - px},${ly - h2 - py}
|
||||||
${pos + 10 + tagBbox.width / 2 + px},${ly - h2 - py}
|
${pos + 10 + tagBbox.width / 2 + px},${ly - h2 - py}
|
||||||
${pos + 10 + tagBbox.width / 2 + px},${ly + h2 + py }
|
${pos + 10 + tagBbox.width / 2 + px},${ly + h2 + py}
|
||||||
${pos + 10 - tagBbox.width / 2 - px},${ly + h2 + py}`);
|
${pos + 10 - tagBbox.width / 2 - px},${ly + h2 + py}`
|
||||||
|
);
|
||||||
|
|
||||||
hole
|
hole
|
||||||
.attr('cx', pos - tagBbox.width / 2 + px/2)
|
.attr('cx', pos - tagBbox.width / 2 + px / 2)
|
||||||
.attr('cy', ly)
|
.attr('cy', ly)
|
||||||
.attr('r', 1.5)
|
.attr('r', 1.5)
|
||||||
.attr('class', 'tag-hole');
|
.attr('class', 'tag-hole');
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pos +=50;
|
pos += 50;
|
||||||
if(pos>maxPos) {
|
if (pos > maxPos) {
|
||||||
maxPos = pos;
|
maxPos = pos;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detect if there are other commits between commit1s x-position and commit2s x-position on the same branch as commit2.
|
* Detect if there are other commits between commit1s x-position and commit2s x-position on the same
|
||||||
* @param {*} commit1
|
* branch as commit2.
|
||||||
* @param {*} commit2
|
*
|
||||||
|
* @param {any} commit1
|
||||||
|
* @param {any} commit2
|
||||||
|
* @param allCommits
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const hasOverlappingCommits = (commit1, commit2, allCommits) => {
|
const hasOverlappingCommits = (commit1, commit2, allCommits) => {
|
||||||
@ -257,43 +247,62 @@ const hasOverlappingCommits = (commit1, commit2, allCommits) => {
|
|||||||
// Find commits on the same branch as commit2
|
// Find commits on the same branch as commit2
|
||||||
const keys = Object.keys(allCommits);
|
const keys = Object.keys(allCommits);
|
||||||
const overlappingComits = keys.filter((key) => {
|
const overlappingComits = keys.filter((key) => {
|
||||||
return allCommits[key].branch === commit2.branch && allCommits[key].seq > commit1.seq && allCommits[key].seq < commit2.seq
|
return (
|
||||||
|
allCommits[key].branch === commit2.branch &&
|
||||||
|
allCommits[key].seq > commit1.seq &&
|
||||||
|
allCommits[key].seq < commit2.seq
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return overlappingComits.length > 0;
|
return overlappingComits.length > 0;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This function find a lane in the y-axis that is not overlapping with any other lanes. This is
|
||||||
|
* used for drawing the lines between commits.
|
||||||
*
|
*
|
||||||
|
* @param {any} y1
|
||||||
|
* @param {any} y2
|
||||||
|
* @param {any} _depth
|
||||||
|
* @returns
|
||||||
*/
|
*/
|
||||||
const findLane = (y1, y2, _depth) => {
|
const findLane = (y1, y2, _depth) => {
|
||||||
const depth = _depth || 0;
|
const depth = _depth || 0;
|
||||||
|
|
||||||
const candidate = y1 + Math.abs(y1 - y2) / 2;
|
const candidate = y1 + Math.abs(y1 - y2) / 2;
|
||||||
if(depth > 5) {
|
if (depth > 5) {
|
||||||
return candidate;
|
return candidate;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ok = true;
|
let ok = true;
|
||||||
for(let i = 0; i < lanes.length; i++) {
|
for (let i = 0; i < lanes.length; i++) {
|
||||||
if(Math.abs(lanes[i] - candidate) < 10) {
|
if (Math.abs(lanes[i] - candidate) < 10) {
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(ok) {
|
if (ok) {
|
||||||
lanes.push(candidate);
|
lanes.push(candidate);
|
||||||
return candidate;
|
return candidate;
|
||||||
}
|
}
|
||||||
const diff = Math.abs(y1 - y2);
|
const diff = Math.abs(y1 - y2);
|
||||||
return findLane(y1, y2-(diff/5), depth);
|
return findLane(y1, y2 - diff / 5, depth);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function draw trhe lines between the commits. They were arrows initially.
|
||||||
|
*
|
||||||
|
* @param {any} svg
|
||||||
|
* @param {any} commit1
|
||||||
|
* @param {any} commit2
|
||||||
|
* @param {any} allCommits
|
||||||
|
*/
|
||||||
const drawArrow = (svg, commit1, commit2, allCommits) => {
|
const drawArrow = (svg, commit1, commit2, allCommits) => {
|
||||||
const conf = getConfig();
|
const conf = getConfig();
|
||||||
|
|
||||||
const p1 = commitPos[commit1.id];
|
const p1 = commitPos[commit1.id];
|
||||||
const p2 = commitPos[commit2.id];
|
const p2 = commitPos[commit2.id];
|
||||||
const overlappingCommits = hasOverlappingCommits(commit1, commit2, allCommits);
|
const overlappingCommits = hasOverlappingCommits(commit1, commit2, allCommits);
|
||||||
log.debug('drawArrow', p1, p2, overlappingCommits, commit1.id, commit2.id);
|
// log.debug('drawArrow', p1, p2, overlappingCommits, commit1.id, commit2.id);
|
||||||
|
|
||||||
let url = '';
|
let url = '';
|
||||||
if (conf.arrowMarkerAbsolute) {
|
if (conf.arrowMarkerAbsolute) {
|
||||||
@ -310,28 +319,30 @@ const drawArrow = (svg, commit1, commit2, allCommits) => {
|
|||||||
let arc = '';
|
let arc = '';
|
||||||
let arc2 = '';
|
let arc2 = '';
|
||||||
let radius = 0;
|
let radius = 0;
|
||||||
let offset = 0
|
let offset = 0;
|
||||||
let colorClassNum = branchPos[commit2.branch].index
|
let colorClassNum = branchPos[commit2.branch].index;
|
||||||
let lineDef;
|
let lineDef;
|
||||||
if(overlappingCommits) {
|
if (overlappingCommits) {
|
||||||
arc = 'A 10 10, 0, 0, 0,';
|
arc = 'A 10 10, 0, 0, 0,';
|
||||||
arc2 = 'A 10 10, 0, 0, 1,';
|
arc2 = 'A 10 10, 0, 0, 1,';
|
||||||
radius = 10;
|
radius = 10;
|
||||||
offset = 10;
|
offset = 10;
|
||||||
// Figure out the color of the arrow,arrows going down take the color from the destination branch
|
// Figure out the color of the arrow,arrows going down take the color from the destination branch
|
||||||
colorClassNum = branchPos[commit2.branch].index;
|
colorClassNum = branchPos[commit2.branch].index;
|
||||||
|
|
||||||
const lineY = p1.y < p2.y ? findLane(p1.y, p2.y):findLane(p2.y, p1.y);
|
const lineY = p1.y < p2.y ? findLane(p1.y, p2.y) : findLane(p2.y, p1.y);
|
||||||
|
|
||||||
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}`;
|
|
||||||
} 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}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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}`;
|
||||||
|
} 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 {
|
} else {
|
||||||
|
if (p1.y < p2.y) {
|
||||||
if(p1.y < p2.y) {
|
|
||||||
arc = 'A 20 20, 0, 0, 0,';
|
arc = 'A 20 20, 0, 0, 0,';
|
||||||
radius = 20;
|
radius = 20;
|
||||||
offset = 20;
|
offset = 20;
|
||||||
@ -339,26 +350,34 @@ const drawArrow = (svg, commit1, commit2, allCommits) => {
|
|||||||
// Figure out the color of the arrow,arrows going down take the color from the destination branch
|
// Figure out the color of the arrow,arrows going down take the color from the destination branch
|
||||||
colorClassNum = branchPos[commit2.branch].index;
|
colorClassNum = branchPos[commit2.branch].index;
|
||||||
|
|
||||||
lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${p2.y-radius} ${arc} ${p1.x + offset} ${p2.y} L ${p2.x} ${p2.y}`;
|
lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${p2.y - radius} ${arc} ${p1.x + offset} ${p2.y} L ${
|
||||||
|
p2.x
|
||||||
|
} ${p2.y}`;
|
||||||
}
|
}
|
||||||
if(p1.y > p2.y) {
|
if (p1.y > p2.y) {
|
||||||
arc = 'A 20 20, 0, 0, 0,';
|
arc = 'A 20 20, 0, 0, 0,';
|
||||||
radius = 20;
|
radius = 20;
|
||||||
offset = 20;
|
offset = 20;
|
||||||
|
|
||||||
// Arrows going up take the color from the source branch
|
// Arrows going up take the color from the source branch
|
||||||
colorClassNum = branchPos[commit1.branch].index;
|
colorClassNum = branchPos[commit1.branch].index;
|
||||||
lineDef = `M ${p1.x} ${p1.y} L ${p2.x-radius} ${p1.y} ${arc} ${p2.x} ${p1.y-offset} L ${p2.x} ${p2.y}`;
|
lineDef = `M ${p1.x} ${p1.y} L ${p2.x - radius} ${p1.y} ${arc} ${p2.x} ${p1.y - offset} L ${
|
||||||
|
p2.x
|
||||||
|
} ${p2.y}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(p1.y === p2.y) {
|
if (p1.y === p2.y) {
|
||||||
colorClassNum = branchPos[commit1.branch].index
|
colorClassNum = branchPos[commit1.branch].index;
|
||||||
lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${p2.y-radius} ${arc} ${p1.x + offset} ${p2.y} L ${p2.x} ${p2.y}`;
|
lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${p2.y - radius} ${arc} ${p1.x + offset} ${p2.y} L ${
|
||||||
|
p2.x
|
||||||
|
} ${p2.y}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const arrow = svg.append('path').attr('d', lineDef)
|
const arrow = svg
|
||||||
.attr('class', 'arrow arrow' + colorClassNum)
|
.append('path')
|
||||||
}
|
.attr('d', lineDef)
|
||||||
|
.attr('class', 'arrow arrow' + colorClassNum);
|
||||||
|
};
|
||||||
|
|
||||||
const drawArrows = (svg, commits) => {
|
const drawArrows = (svg, commits) => {
|
||||||
const gArrows = svg.append('g').attr('class', 'commit-arrows');
|
const gArrows = svg.append('g').attr('class', 'commit-arrows');
|
||||||
@ -367,123 +386,114 @@ const drawArrows = (svg, commits) => {
|
|||||||
const k = Object.keys(commits);
|
const k = Object.keys(commits);
|
||||||
k.forEach((key, index) => {
|
k.forEach((key, index) => {
|
||||||
const commit = commits[key];
|
const commit = commits[key];
|
||||||
if(commit.parents && commit.parents.length>0) {
|
if (commit.parents && commit.parents.length > 0) {
|
||||||
commit.parents.forEach((parent) => {
|
commit.parents.forEach((parent) => {
|
||||||
drawArrow(gArrows, commits[parent], commit, commits);
|
drawArrow(gArrows, commits[parent], commit, commits);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This function adds the branches and the branches' labels to the svg.
|
||||||
|
*
|
||||||
* @param svg
|
* @param svg
|
||||||
* @param commitid
|
* @param commitid
|
||||||
* @param branches
|
* @param branches
|
||||||
* @param direction
|
* @param direction
|
||||||
*/
|
*/
|
||||||
const drawBranches = (svg, branches) => {
|
const drawBranches = (svg, branches) => {
|
||||||
const g = svg.append('g')
|
const gitGraphConfig = getConfig().gitGraph;
|
||||||
branches.forEach((branch, index) => {
|
const g = svg.append('g');
|
||||||
const pos = branchPos[branch.name].pos;
|
branches.forEach((branch, index) => {
|
||||||
const line = g.append('line');
|
const pos = branchPos[branch.name].pos;
|
||||||
line.attr('x1', 0);
|
const line = g.append('line');
|
||||||
line.attr('y1', pos);
|
line.attr('x1', 0);
|
||||||
line.attr('x2', maxPos);
|
line.attr('y1', pos);
|
||||||
line.attr('y2', pos);
|
line.attr('x2', maxPos);
|
||||||
line.attr('class', 'branch branch'+index)
|
line.attr('y2', pos);
|
||||||
|
line.attr('class', 'branch branch' + index);
|
||||||
|
|
||||||
lanes.push(pos);
|
lanes.push(pos);
|
||||||
|
|
||||||
// Create the actual text element
|
let name = index === 0 ? gitGraphConfig.mainBranchName : branch.name;
|
||||||
const labelElement = drawText(branch.name);
|
|
||||||
// Create outer g, edgeLabel, this will be positioned after graph layout
|
|
||||||
const bkg = g.insert('rect');
|
|
||||||
const branchLabel = g.insert('g').attr('class', 'branchLabel');
|
|
||||||
|
|
||||||
// Create inner g, label, this will be positioned now for centering the text
|
// Create the actual text element
|
||||||
const label = branchLabel.insert('g').attr('class', 'label branch-label'+index);
|
const labelElement = drawText(name);
|
||||||
label.node().appendChild(labelElement);
|
// Create outer g, edgeLabel, this will be positioned after graph layout
|
||||||
let bbox = labelElement.getBBox();
|
const bkg = g.insert('rect');
|
||||||
bkg.attr('class', 'branchLabelBkg label' + index)
|
const branchLabel = g.insert('g').attr('class', 'branchLabel');
|
||||||
.attr('rx', 4)
|
|
||||||
.attr('ry', 4)
|
|
||||||
.attr('x', -bbox.width -4)
|
|
||||||
.attr('y', -bbox.height / 2 +8 )
|
|
||||||
.attr('width', bbox.width + 18)
|
|
||||||
.attr('height', bbox.height + 4);
|
|
||||||
|
|
||||||
label.attr('transform', 'translate(' + (-bbox.width -14) + ', ' + (pos - bbox.height/2-1) + ')');
|
// Create inner g, label, this will be positioned now for centering the text
|
||||||
bkg.attr('transform', 'translate(' + -19 + ', ' + (pos - bbox.height/2) + ')');
|
const label = branchLabel.insert('g').attr('class', 'label branch-label' + index);
|
||||||
})
|
label.node().appendChild(labelElement);
|
||||||
|
let bbox = labelElement.getBBox();
|
||||||
|
bkg
|
||||||
|
.attr('class', 'branchLabelBkg label' + index)
|
||||||
|
.attr('rx', 4)
|
||||||
|
.attr('ry', 4)
|
||||||
|
.attr('x', -bbox.width - 4)
|
||||||
|
.attr('y', -bbox.height / 2 + 8)
|
||||||
|
.attr('width', bbox.width + 18)
|
||||||
|
.attr('height', bbox.height + 4);
|
||||||
|
|
||||||
}
|
label.attr(
|
||||||
|
'transform',
|
||||||
|
'translate(' + (-bbox.width - 14) + ', ' + (pos - bbox.height / 2 - 1) + ')'
|
||||||
|
);
|
||||||
|
bkg.attr('transform', 'translate(' + -19 + ', ' + (pos - bbox.height / 2) + ')');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param svg
|
* @param svg
|
||||||
* @param commit
|
* @param commit
|
||||||
* @param direction
|
* @param direction
|
||||||
* @param branchColor
|
* @param branchColor
|
||||||
|
* @param txt
|
||||||
|
* @param id
|
||||||
|
* @param ver
|
||||||
*/
|
*/
|
||||||
export const draw = function (txt, id, ver) {
|
export const draw = function (txt, id, ver) {
|
||||||
clear();
|
clear();
|
||||||
const conf = getConfig();
|
const conf = getConfig();
|
||||||
const config = conf.gitGraph;
|
const gitGraphConfig = getConfig().gitGraph;
|
||||||
// try {
|
// try {
|
||||||
const parser = gitGraphParser.parser;
|
const parser = gitGraphParser.parser;
|
||||||
parser.yy = db;
|
parser.yy = db;
|
||||||
parser.yy.clear();
|
parser.yy.clear();
|
||||||
|
|
||||||
log.debug('in gitgraph renderer', txt + '\n', 'id:', id, ver);
|
log.debug('in gitgraph renderer', txt + '\n', 'id:', id, ver);
|
||||||
// // Parse the graph definition
|
// // Parse the graph definition
|
||||||
parser.parse(txt + '\n');
|
parser.parse(txt + '\n');
|
||||||
|
|
||||||
// config = Object.assign(config, apiConfig, db.getOptions());
|
|
||||||
const direction = db.getDirection();
|
const direction = db.getDirection();
|
||||||
allCommitsDict = db.getCommits();
|
allCommitsDict = db.getCommits();
|
||||||
const branches = db.getBranchesAsObjArray();
|
const branches = db.getBranchesAsObjArray();
|
||||||
|
|
||||||
// Position branches vertically
|
// Position branches vertically
|
||||||
let pos=0;
|
let pos = 0;
|
||||||
branches.forEach((branch, index) => {
|
branches.forEach((branch, index) => {
|
||||||
branchPos[branch.name] = {pos, index};
|
branchPos[branch.name] = { pos, index };
|
||||||
pos+=50;
|
pos += 50;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
log.debug('brach pos ', branchPos);
|
|
||||||
log.debug('effective options', config, branches);
|
|
||||||
log.debug('commits', allCommitsDict);
|
|
||||||
|
|
||||||
const diagram = select(`[id="${id}"]`);
|
const diagram = select(`[id="${id}"]`);
|
||||||
svgCreateDefs(diagram);
|
|
||||||
|
|
||||||
diagram
|
|
||||||
.append('defs')
|
|
||||||
.append('marker')
|
|
||||||
.attr('id', 'arrowhead')
|
|
||||||
.attr('refX',24)
|
|
||||||
.attr('refY', 10)
|
|
||||||
.attr('markerUnits', 'userSpaceOnUse')
|
|
||||||
.attr('markerWidth', 24)
|
|
||||||
.attr('markerHeight', 24)
|
|
||||||
.attr('orient', 'auto')
|
|
||||||
.append('path')
|
|
||||||
.attr('d', 'M 0 0 L 20 10 L 0 20 z'); // this is actual shape for arrowhead
|
|
||||||
|
|
||||||
drawCommits(diagram, allCommitsDict, false);
|
drawCommits(diagram, allCommitsDict, false);
|
||||||
drawBranches(diagram, branches);
|
if (gitGraphConfig.showBranches) {
|
||||||
|
drawBranches(diagram, branches);
|
||||||
|
}
|
||||||
drawArrows(diagram, allCommitsDict);
|
drawArrows(diagram, allCommitsDict);
|
||||||
drawCommits(diagram, allCommitsDict, true);
|
drawCommits(diagram, allCommitsDict, true);
|
||||||
|
|
||||||
const padding = config.diagramPadding;
|
const padding = gitGraphConfig.diagramPadding;
|
||||||
const svgBounds = diagram.node().getBBox();
|
const svgBounds = diagram.node().getBBox();
|
||||||
const width = svgBounds.width + padding * 2;
|
const width = svgBounds.width + padding * 2;
|
||||||
const height = svgBounds.height + padding * 2;
|
const height = svgBounds.height + padding * 2;
|
||||||
|
|
||||||
configureSvgSize(diagram, height, width, conf.useMaxWidth);
|
configureSvgSize(diagram, height, width, conf.useMaxWidth);
|
||||||
const vBox = `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`;
|
const vBox = `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`;
|
||||||
// logger.debug(`viewBox ${vBox}`);
|
|
||||||
diagram.attr('viewBox', vBox);
|
diagram.attr('viewBox', vBox);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,14 +72,14 @@ function parse(text) {
|
|||||||
const graphInit = utils.detectInit(text, cnf);
|
const graphInit = utils.detectInit(text, cnf);
|
||||||
if (graphInit) {
|
if (graphInit) {
|
||||||
reinitialize(graphInit);
|
reinitialize(graphInit);
|
||||||
log.debug('reinit ', graphInit);
|
log.info('reinit ', graphInit);
|
||||||
}
|
}
|
||||||
const graphType = utils.detectType(text, cnf);
|
const graphType = utils.detectType(text, cnf);
|
||||||
let parser;
|
let parser;
|
||||||
|
|
||||||
log.debug('Type ' + graphType);
|
log.debug('Type ' + graphType);
|
||||||
switch (graphType) {
|
switch (graphType) {
|
||||||
case 'git':
|
case 'gitGraph':
|
||||||
parser = gitGraphParser;
|
parser = gitGraphParser;
|
||||||
parser.parser.yy = gitGraphAst;
|
parser.parser.yy = gitGraphAst;
|
||||||
break;
|
break;
|
||||||
@ -229,6 +229,9 @@ const render = function (id, _txt, cb, container) {
|
|||||||
configApi.addDirective(graphInit);
|
configApi.addDirective(graphInit);
|
||||||
}
|
}
|
||||||
let cnf = configApi.getConfig();
|
let cnf = configApi.getConfig();
|
||||||
|
|
||||||
|
log.debug(cnf);
|
||||||
|
|
||||||
// Check the maximum allowed text size
|
// Check the maximum allowed text size
|
||||||
if (_txt.length > cnf.maxTextSize) {
|
if (_txt.length > cnf.maxTextSize) {
|
||||||
txt = 'graph TB;a[Maximum text size in diagram exceeded];style a fill:#faa';
|
txt = 'graph TB;a[Maximum text size in diagram exceeded];style a fill:#faa';
|
||||||
@ -422,7 +425,7 @@ const render = function (id, _txt, cb, container) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
switch (graphType) {
|
switch (graphType) {
|
||||||
case 'git':
|
case 'gitGraph':
|
||||||
// cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
// cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||||
//gitGraphRenderer.setConf(cnf.git);
|
//gitGraphRenderer.setConf(cnf.git);
|
||||||
gitGraphRenderer.draw(txt, id, false);
|
gitGraphRenderer.draw(txt, id, false);
|
||||||
|
@ -2,7 +2,7 @@ import classDiagram from './diagrams/class/styles';
|
|||||||
import er from './diagrams/er/styles';
|
import er from './diagrams/er/styles';
|
||||||
import flowchart from './diagrams/flowchart/styles';
|
import flowchart from './diagrams/flowchart/styles';
|
||||||
import gantt from './diagrams/gantt/styles';
|
import gantt from './diagrams/gantt/styles';
|
||||||
import git from './diagrams/git/styles';
|
import gitGraph from './diagrams/git/styles';
|
||||||
import info from './diagrams/info/styles';
|
import info from './diagrams/info/styles';
|
||||||
import pie from './diagrams/pie/styles';
|
import pie from './diagrams/pie/styles';
|
||||||
import requirement from './diagrams/requirement/styles';
|
import requirement from './diagrams/requirement/styles';
|
||||||
@ -20,7 +20,7 @@ const themes = {
|
|||||||
class: classDiagram,
|
class: classDiagram,
|
||||||
stateDiagram,
|
stateDiagram,
|
||||||
state: stateDiagram,
|
state: stateDiagram,
|
||||||
git,
|
gitGraph,
|
||||||
info,
|
info,
|
||||||
pie,
|
pie,
|
||||||
er,
|
er,
|
||||||
|
@ -210,7 +210,7 @@ export const detectType = function (text, cnf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (text.match(/^\s*gitGraph/)) {
|
if (text.match(/^\s*gitGraph/)) {
|
||||||
return 'git';
|
return 'gitGraph';
|
||||||
}
|
}
|
||||||
if (text.match(/^\s*flowchart/)) {
|
if (text.match(/^\s*flowchart/)) {
|
||||||
return 'flowchart-v2';
|
return 'flowchart-v2';
|
||||||
|
@ -214,7 +214,7 @@ Alice->Bob: hi`;
|
|||||||
it('should handle a graph definition for gitGraph', function () {
|
it('should handle a graph definition for gitGraph', function () {
|
||||||
const str = ' \n gitGraph TB:\nbfs1:queue';
|
const str = ' \n gitGraph TB:\nbfs1:queue';
|
||||||
const type = utils.detectType(str);
|
const type = utils.detectType(str);
|
||||||
expect(type).toBe('git');
|
expect(type).toBe('gitGraph');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('when finding substring in array ', function () {
|
describe('when finding substring in array ', function () {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user