Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using diagram api to add gitGraph #3240

Merged
merged 2 commits into from Jul 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion cypress/platform/knsv.html
Expand Up @@ -64,7 +64,7 @@
commit
commit
</div>
<div class="mermaid2" style="width: 50%;">
<div class="mermaid" style="width: 50%;">
sequenceDiagram
title: My Sequence Diagram Title
accTitle: My Acc Sequence Diagram
Expand Down Expand Up @@ -283,6 +283,9 @@
class: {
// defaultRenderer: 'dagre-d3',
htmlLabels: true,
},
sequence: {
mirrorActors: false,
},
// gantt: { axisFormat: '%m/%d/%Y' },
// sequence: {
Expand Down
11 changes: 9 additions & 2 deletions docs/Setup.md
Expand Up @@ -1401,6 +1401,15 @@ This sets the auto-wrap padding for the diagram (sides only)

**Notes:** Default value: 0.

## parse

### Parameters

- `text`
- `dia`

Returns **any**

## setSiteConfig

## setSiteConfig
Expand Down Expand Up @@ -1524,8 +1533,6 @@ Pushes in a directive to the configuration

## reset

## reset

| Function | Description | Type | Required | Values |
| -------- | ---------------------------- | ----------- | -------- | ------ |
| reset | Resets currentConfig to conf | Put Request | Required | None |
Expand Down
218 changes: 43 additions & 175 deletions src/Diagram.js
@@ -1,198 +1,66 @@
import c4Db from './diagrams/c4/c4Db';
import c4Renderer from './diagrams/c4/c4Renderer';
import c4Parser from './diagrams/c4/parser/c4Diagram';
import classDb from './diagrams/class/classDb';
import classRenderer from './diagrams/class/classRenderer';
import classRendererV2 from './diagrams/class/classRenderer-v2';
import classParser from './diagrams/class/parser/classDiagram';
import erDb from './diagrams/er/erDb';
import erRenderer from './diagrams/er/erRenderer';
import erParser from './diagrams/er/parser/erDiagram';
import flowDb from './diagrams/flowchart/flowDb';
import flowRenderer from './diagrams/flowchart/flowRenderer';
import flowRendererV2 from './diagrams/flowchart/flowRenderer-v2';
import flowParser from './diagrams/flowchart/parser/flow';
import ganttDb from './diagrams/gantt/ganttDb';
import ganttRenderer from './diagrams/gantt/ganttRenderer';
import ganttParser from './diagrams/gantt/parser/gantt';
import gitGraphAst from './diagrams/git/gitGraphAst';
import gitGraphRenderer from './diagrams/git/gitGraphRenderer';
import gitGraphParser from './diagrams/git/parser/gitGraph';
import infoDb from './diagrams/info/infoDb';
import infoRenderer from './diagrams/info/infoRenderer';
import infoParser from './diagrams/info/parser/info';
import pieParser from './diagrams/pie/parser/pie';
import pieDb from './diagrams/pie/pieDb';
import pieRenderer from './diagrams/pie/pieRenderer';
import requirementParser from './diagrams/requirement/parser/requirementDiagram';
import requirementDb from './diagrams/requirement/requirementDb';
import requirementRenderer from './diagrams/requirement/requirementRenderer';
import sequenceParser from './diagrams/sequence/parser/sequenceDiagram';
import sequenceDb from './diagrams/sequence/sequenceDb';
import sequenceRenderer from './diagrams/sequence/sequenceRenderer';
import stateParser from './diagrams/state/parser/stateDiagram';
import stateDb from './diagrams/state/stateDb';
import stateRenderer from './diagrams/state/stateRenderer';
import stateRendererV2 from './diagrams/state/stateRenderer-v2';
import journeyDb from './diagrams/user-journey/journeyDb';
import journeyRenderer from './diagrams/user-journey/journeyRenderer';
import journeyParser from './diagrams/user-journey/parser/journey';
import utils from './utils';
import * as configApi from './config';
import { log } from './logger';

import { getDiagrams } from './diagram-api/diagramAPI';
import detectType from './diagram-api/detectType';
class Diagram {
type = 'graph';
parser;
renderer;
db;
constructor(txt) {
const diagrams = getDiagrams();
const cnf = configApi.getConfig();
this.txt = txt;
this.type = utils.detectType(txt, cnf);
this.type = detectType(txt, cnf);
log.debug('Type ' + this.type);
switch (this.type) {
case 'c4':
this.parser = c4Parser;
this.parser.parser.yy = c4Db;
this.db = c4Db;
this.renderer = c4Renderer;
this.renderer.setConf(cnf.c4);
break;
case 'gitGraph':
this.parser = gitGraphParser;
this.parser.parser.yy = gitGraphAst;
this.db = gitGraphAst;
this.renderer = gitGraphRenderer;
this.txt = this.txt + '\n';
break;
case 'flowchart':
flowRenderer.setConf(cnf.flowchart);
cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
flowDb.clear();
flowDb.setGen('gen-1');
this.parser = flowParser;
this.parser.parser.yy = flowDb;
this.db = flowDb;
this.renderer = flowRenderer;
break;
case 'flowchart-v2':
flowRendererV2.setConf(cnf.flowchart);
cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
flowDb.clear();
flowDb.setGen('gen-2');
this.parser = flowParser;
this.parser.parser.yy = flowDb;
this.db = flowDb;
this.renderer = flowRendererV2;
break;
case 'sequenceDiagram':
case 'sequence':
cnf.sequence.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
if (cnf.sequenceDiagram) {
// backwards compatibility
sequenceRenderer.setConf(Object.assign(cnf.sequence, cnf.sequenceDiagram));
console.error(
'`mermaid config.sequenceDiagram` has been renamed to `config.sequence`. Please update your mermaid config.'
);
}
this.parser = sequenceParser;
this.parser.parser.yy = sequenceDb;
this.db = sequenceDb;
this.db.setWrap(cnf.wrap);
this.renderer = sequenceRenderer;
this.renderer.setConf(cnf.sequence);
this.txt = this.txt + '\n';
break;
case 'gantt':
cnf.gantt.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
this.parser = ganttParser;
this.parser.parser.yy = ganttDb;
this.db = ganttDb;
this.renderer = ganttRenderer;
ganttRenderer.setConf(cnf.gantt);
break;
case 'class':
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
this.parser = classParser;
this.parser.parser.yy = classDb;
this.db = classDb;
this.db.clear();
this.renderer = classRenderer;
break;
case 'classDiagram':
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
this.parser = classParser;
this.parser.parser.yy = classDb;
this.db = classDb;
this.db.clear();
this.renderer = classRendererV2;
break;
case 'state':
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
this.parser = stateParser;
this.parser.parser.yy = stateDb;
this.db = stateDb;
this.db.clear();
this.renderer = stateRenderer;
break;
case 'stateDiagram':
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
this.parser = stateParser;
this.parser.parser.yy = stateDb;
this.db = stateDb;
this.db.clear();
this.renderer = stateRendererV2;
break;
case 'info':
log.debug('info info info');
this.parser = infoParser;
this.parser.parser.yy = infoDb;
this.db = infoDb;
this.renderer = infoRenderer;
break;
case 'pie':
log.debug('pie');
this.parser = pieParser;
this.parser.parser.yy = pieDb;
this.db = pieDb;
this.renderer = pieRenderer;
break;
case 'er':
log.debug('er');
this.parser = erParser;
this.parser.parser.yy = erDb;
this.db = erDb;
this.renderer = erRenderer;
break;
case 'journey':
log.debug('Journey');
journeyRenderer.setConf(cnf.journey);
this.parser = journeyParser;
this.parser.parser.yy = journeyDb;
this.db = journeyDb;
this.db.clear();
this.renderer = journeyRenderer;
break;
case 'requirement':
case 'requirementDiagram':
log.debug('RequirementDiagram');
this.parser = requirementParser;
this.parser.parser.yy = requirementDb;
this.db = requirementDb;
this.renderer = requirementRenderer;
break;
default:
log.error('Unkown graphtype');
throw new Error('Unkown graphtype');

// console.log('this.type', this.type, diagrams[this.type]);
// Setup diagram
this.db = diagrams[this.type].db;
this.renderer = diagrams[this.type].renderer;
this.parser = diagrams[this.type].parser;
this.parser.parser.yy = this.db;
if (typeof diagrams[this.type].init === 'function') {
diagrams[this.type].init(cnf);
log.debug('Initialized diagram ' + this.type, cnf);
}
this.txt = this.txt + '\n';

this.parser.parser.yy.graphType = this.type;
this.parser.parser.yy.parseError = (str, hash) => {
const error = { str, hash };
throw error;
};
this.parser.parse(this.txt);
}
parse(text) {
var parseEncounteredException = false;
try {
text = text + '\n';
this.db.clear();

this.parser.parse(text);
} catch (error) {
parseEncounteredException = true;
// Is this the correct way to access mermiad's parseError()
// method ? (or global.mermaid.parseError()) ?
if (global.mermaid.parseError) {
if (error.str != undefined) {
// handle case where error string and hash were
// wrapped in object like`const error = { str, hash };`
global.mermaid.parseError(error.str, error.hash);
} else {
// assume it is just error string and pass it on
global.mermaid.parseError(error);
}
} else {
// No mermaid.parseError() handler defined, so re-throw it
throw error;
}
}
return !parseEncounteredException;
}
getParser() {
return this.parser;
}
Expand Down
74 changes: 74 additions & 0 deletions src/assignWithDepth.js
@@ -0,0 +1,74 @@
/**
* @function assignWithDepth Extends the functionality of {@link ObjectConstructor.assign} with the
* ability to merge arbitrary-depth objects For each key in src with path `k` (recursively)
* performs an Object.assign(dst[`k`], src[`k`]) with a slight change from the typical handling of
* undefined for dst[`k`]: instead of raising an error, dst[`k`] is auto-initialized to {} and
* effectively merged with src[`k`]<p> Additionally, dissimilar types will not clobber unless the
* config.clobber parameter === true. Example:
*
* ```js
* let config_0 = { foo: { bar: 'bar' }, bar: 'foo' };
* let config_1 = { foo: 'foo', bar: 'bar' };
* let result = assignWithDepth(config_0, config_1);
* console.log(result);
* //-> result: { foo: { bar: 'bar' }, bar: 'bar' }
* ```
*
* Traditional Object.assign would have clobbered foo in config_0 with foo in config_1. If src is a
* destructured array of objects and dst is not an array, assignWithDepth will apply each element
* of src to dst in order.
* @param dst
* @param src
* @param config
* @param dst
* @param src
* @param config
* @param dst
* @param src
* @param config
* @param {any} dst - The destination of the merge
* @param {any} src - The source object(s) to merge into destination
* @param {{ depth: number; clobber: boolean }} [config={ depth: 2, clobber: false }] - Depth: depth
* to traverse within src and dst for merging - clobber: should dissimilar types clobber (default:
* { depth: 2, clobber: false }). Default is `{ depth: 2, clobber: false }`
* @returns {any}
*/
const assignWithDepth = function (dst, src, config) {
const { depth, clobber } = Object.assign({ depth: 2, clobber: false }, config);
if (Array.isArray(src) && !Array.isArray(dst)) {
src.forEach((s) => assignWithDepth(dst, s, config));
return dst;
} else if (Array.isArray(src) && Array.isArray(dst)) {
src.forEach((s) => {
if (dst.indexOf(s) === -1) {
dst.push(s);
}
});
return dst;
}
if (typeof dst === 'undefined' || depth <= 0) {
if (dst !== undefined && dst !== null && typeof dst === 'object' && typeof src === 'object') {
return Object.assign(dst, src);
} else {
return src;
}
}
if (typeof src !== 'undefined' && typeof dst === 'object' && typeof src === 'object') {
Object.keys(src).forEach((key) => {
if (
typeof src[key] === 'object' &&
(dst[key] === undefined || typeof dst[key] === 'object')
) {
if (dst[key] === undefined) {
dst[key] = Array.isArray(src[key]) ? [] : {};
}
dst[key] = assignWithDepth(dst[key], src[key], { depth: depth - 1, clobber });
} else if (clobber || (typeof dst[key] !== 'object' && typeof src[key] !== 'object')) {
dst[key] = src[key];
}
});
}
return dst;
};

export default assignWithDepth;
2 changes: 1 addition & 1 deletion src/config.js
@@ -1,4 +1,4 @@
import { assignWithDepth } from './utils';
import assignWithDepth from './assignWithDepth';
import { log } from './logger';
import theme from './themes';
import config from './defaultConfig';
Expand Down