diff --git a/cypress/integration/rendering/gitGraph.spec.js b/cypress/integration/rendering/gitGraph.spec.js index b0d65d0cc..afb39b62e 100644 --- a/cypress/integration/rendering/gitGraph.spec.js +++ b/cypress/integration/rendering/gitGraph.spec.js @@ -180,7 +180,48 @@ describe('Git Graph diagram', () => { {} ); }); - + it('11: should render a gitgraph with cherry pick commit with custom tag', () => { + imgSnapshotTest( + ` + gitGraph + 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('11: should render a gitgraph with cherry pick commit with no tag', () => { + imgSnapshotTest( + ` + gitGraph + 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('11: should render a simple gitgraph with two cherry pick commit', () => { imgSnapshotTest( ` @@ -207,7 +248,6 @@ describe('Git Graph diagram', () => { {} ); }); - it('12: should render commits for more than 8 branches', () => { imgSnapshotTest( ` diff --git a/cypress/platform/gitgraph.html b/cypress/platform/gitgraph.html index da81427f8..0186d6209 100644 --- a/cypress/platform/gitgraph.html +++ b/cypress/platform/gitgraph.html @@ -30,7 +30,31 @@

info below

+
+  %%{init: { "logLevel": "debug", "theme": "default" , "gitGraph" : {"showBranches":"false","rotateCommitLabel":"true"},"themeVariables": {
+              "gitBranchLabel0": "#ff0000",
+              "gitBranchLabel1": "#00ff00",
+              "gitBranchLabel2": "#0000ff",
+              "git0": "#550055"
+       } } }%%
+    gitGraph
+      commit
+       branch develop
+       commit
+       commit
+       branch release/1.0.0
+       checkout release/1.0.0
+       commit tag:"1.0.0-beta1"
+       checkout develop
+       commit
+       commit
+       commit
+       commit
+       checkout release/1.0.0
+       merge develop tag: "1.0.0-beta2"
+    
+
     %%{init: { "logLevel": "debug", "theme": "default" , "gitGraph" : {"showBranches":"false"},"themeVariables": {
               "gitBranchLabel0": "#ff0000",
               "gitBranchLabel1": "#00ff00",
@@ -131,6 +155,7 @@
         // arrowMarkerAbsolute: true,
         // themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
         logLevel: 1,
+        gitGraph: { rotateCommitLabel: false },
         flowchart: { curve: 'linear', htmlLabels: true },
         // gantt: { axisFormat: '%m/%d/%Y' },
         sequence: { actorMargin: 50, showSequenceNumbers: true },
diff --git a/docs/classDiagram.md b/docs/classDiagram.md
index 6c9ae96fe..3f12dddf8 100644
--- a/docs/classDiagram.md
+++ b/docs/classDiagram.md
@@ -660,14 +660,27 @@ It is also possible to attach a class to a list of nodes in one statement:
 
 A shorter form of adding a class is to attach the classname to the node using the `:::` operator:
 
-```mmd
+```mermaid-example
+classDiagram
+    class Animal:::cssClass
+```
+
+```mermaid
 classDiagram
     class Animal:::cssClass
 ```
 
 Or:
 
-```mmd
+```mermaid-example
+classDiagram
+    class Animal:::cssClass {
+        -int sizeInFeet
+        -canEat()
+    }
+```
+
+```mermaid
 classDiagram
     class Animal:::cssClass {
         -int sizeInFeet
diff --git a/src/diagrams/git/gitGraphAst.js b/src/diagrams/git/gitGraphAst.js
index fb9bb100d..41130c780 100644
--- a/src/diagrams/git/gitGraphAst.js
+++ b/src/diagrams/git/gitGraphAst.js
@@ -258,9 +258,11 @@ export const merge = function (otherBranch, custom_id, override_type, custom_tag
   log.debug('in mergeBranch');
 };
 
-export const cherryPick = function (sourceId, targetId) {
+export const cherryPick = function (sourceId, targetId, tag) {
+  log.debug('Entering cherryPick:', sourceId, targetId, tag);
   sourceId = common.sanitizeText(sourceId, configApi.getConfig());
   targetId = common.sanitizeText(targetId, configApi.getConfig());
+  tag = common.sanitizeText(tag, configApi.getConfig());
 
   if (!sourceId || typeof commits[sourceId] === 'undefined') {
     let error = new Error(
@@ -328,13 +330,13 @@ export const cherryPick = function (sourceId, targetId) {
       parents: [head == null ? null : head.id, sourceCommit.id],
       branch: curBranch,
       type: commitType.CHERRY_PICK,
-      tag: 'cherry-pick:' + sourceCommit.id,
+      tag: tag ?? 'cherry-pick:' + sourceCommit.id,
     };
     head = commit;
     commits[commit.id] = commit;
     branches[curBranch] = commit.id;
     log.debug(branches);
-    log.debug('in cheeryPick');
+    log.debug('in cherryPick');
   }
 };
 export const checkout = function (branch) {
diff --git a/src/diagrams/git/gitGraphParserV2.spec.js b/src/diagrams/git/gitGraphParserV2.spec.js
index b6c9c2459..7aab8fc7c 100644
--- a/src/diagrams/git/gitGraphParserV2.spec.js
+++ b/src/diagrams/git/gitGraphParserV2.spec.js
@@ -611,6 +611,54 @@ describe('when parsing a gitGraph', function () {
     ]);
   });
 
+  it('should support cherry-picking commits', function () {
+    const str = `gitGraph
+    commit id: "ZERO"
+    branch develop
+    commit id:"A"
+    checkout main
+    cherry-pick id:"A"
+    `;
+
+    parser.parse(str);
+    const commits = parser.yy.getCommits();
+    const cherryPickCommitID = Object.keys(commits)[2];
+    expect(commits[cherryPickCommitID].tag).toBe('cherry-pick:A');
+    expect(commits[cherryPickCommitID].branch).toBe('main');
+  });
+
+  it('should support cherry-picking commits with custom tag', function () {
+    const str = `gitGraph
+    commit id: "ZERO"
+    branch develop
+    commit id:"A"
+    checkout main
+    cherry-pick id:"A" tag:"MyTag"
+    `;
+
+    parser.parse(str);
+    const commits = parser.yy.getCommits();
+    const cherryPickCommitID = Object.keys(commits)[2];
+    expect(commits[cherryPickCommitID].tag).toBe('MyTag');
+    expect(commits[cherryPickCommitID].branch).toBe('main');
+  });
+
+  it('should support cherry-picking commits with no tag', function () {
+    const str = `gitGraph
+    commit id: "ZERO"
+    branch develop
+    commit id:"A"
+    checkout main
+    cherry-pick id:"A" tag:""
+    `;
+
+    parser.parse(str);
+    const commits = parser.yy.getCommits();
+    const cherryPickCommitID = Object.keys(commits)[2];
+    expect(commits[cherryPickCommitID].tag).toBe('');
+    expect(commits[cherryPickCommitID].branch).toBe('main');
+  });
+
   it('should throw error when try to branch existing branch: main', function () {
     const str = `gitGraph
     commit
diff --git a/src/diagrams/git/gitGraphRenderer.js b/src/diagrams/git/gitGraphRenderer.js
index 68905c0d2..e15e43ac3 100644
--- a/src/diagrams/git/gitGraphRenderer.js
+++ b/src/diagrams/git/gitGraphRenderer.js
@@ -1,7 +1,6 @@
 import { select } from 'd3';
-import { configureSvgSize } from '../../setupGraphViewbox';
+import { getConfig, setupGraphViewbox } from '../../diagram-api/diagramAPI';
 import { log } from '../../logger';
-import { getConfig } from '../../config';
 import addSVGAccessibilityFields from '../../accessibility';
 
 let allCommitsDict = {};
@@ -523,18 +522,8 @@ export const draw = function (txt, id, ver, diagObj) {
   drawArrows(diagram, allCommitsDict);
   drawCommits(diagram, allCommitsDict, true);
 
-  const padding = gitGraphConfig.diagramPadding;
-  const svgBounds = diagram.node().getBBox();
-  const width = svgBounds.width + padding * 2;
-  const height = svgBounds.height + padding * 2;
-
-  configureSvgSize(diagram, height, width, conf.useMaxWidth);
-  const vBox = `${
-    svgBounds.x -
-    padding -
-    (gitGraphConfig.showBranches && gitGraphConfig.rotateCommitLabel === true ? 30 : 0)
-  } ${svgBounds.y - padding} ${width} ${height}`;
-  diagram.attr('viewBox', vBox);
+  // Setup the view box and size of the svg element
+  setupGraphViewbox(undefined, diagram, gitGraphConfig.diagramPadding, conf.useMaxWidth);
 };
 
 export default {
diff --git a/src/diagrams/git/parser/gitGraph.jison b/src/diagrams/git/parser/gitGraph.jison
index f35dbcde3..dbe220e15 100644
--- a/src/diagrams/git/parser/gitGraph.jison
+++ b/src/diagrams/git/parser/gitGraph.jison
@@ -47,7 +47,7 @@ commit(?=\s|$)                          return 'COMMIT';
 branch(?=\s|$)                          return 'BRANCH';
 "order:"                                return 'ORDER';
 merge(?=\s|$)                           return 'MERGE';
-cherry-pick(?=\s|$)                     return 'CHERRY_PICK';
+cherry\-pick(?=\s|$)                    return 'CHERRY_PICK';
 // "reset"                                 return 'RESET';
 checkout(?=\s|$)                        return 'CHECKOUT';
 "LR"                                    return 'DIR';
@@ -57,6 +57,7 @@ checkout(?=\s|$)                        return 'CHECKOUT';
 "options"\r?\n                          this.begin("options"); //
 [ \r\n\t]+"end"                this.popState();       // not used anymore in the renderer, fixed for backward compatibility
 [\s\S]+(?=[ \r\n\t]+"end")     return 'OPT';          //
+["]["]                                  return 'EMPTYSTR';
 ["]                                     this.begin("string");
 ["]                             this.popState();
 [^"]*                           return 'STR';
@@ -117,7 +118,11 @@ branchStatement
     ;
 
 cherryPickStatement
-    : CHERRY_PICK COMMIT_ID STR {yy.cherryPick($3)}
+    : CHERRY_PICK COMMIT_ID STR {yy.cherryPick($3, '', undefined)}
+    | CHERRY_PICK COMMIT_ID STR COMMIT_TAG STR {yy.cherryPick($3, '', $5)}
+    | CHERRY_PICK COMMIT_ID STR COMMIT_TAG EMPTYSTR {yy.cherryPick($3, '', '')}
+    | CHERRY_PICK COMMIT_TAG STR COMMIT_ID STR {yy.cherryPick($5, '', $3)}
+    | CHERRY_PICK COMMIT_TAG EMPTYSTR COMMIT_ID STR {yy.cherryPick($3, '', '')}
     ;
 
 mergeStatement
diff --git a/src/docs/classDiagram.md b/src/docs/classDiagram.md
index 87d76cd37..f46d3689c 100644
--- a/src/docs/classDiagram.md
+++ b/src/docs/classDiagram.md
@@ -493,14 +493,14 @@ It is also possible to attach a class to a list of nodes in one statement:
 
 A shorter form of adding a class is to attach the classname to the node using the `:::` operator:
 
-```mmd
+```mermaid-example
 classDiagram
     class Animal:::cssClass
 ```
 
 Or:
 
-```mmd
+```mermaid-example
 classDiagram
     class Animal:::cssClass {
         -int sizeInFeet
diff --git a/yarn.lock b/yarn.lock
index 55fa0c555..18cbe2958 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3799,15 +3799,10 @@ camelcase@^6.2.0:
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809"
   integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==
 
-caniuse-lite@^1.0.30001359:
-  version "1.0.30001390"
-  resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001390.tgz"
-  integrity sha512-sS4CaUM+/+vqQUlCvCJ2WtDlV81aWtHhqeEVkLokVJJa3ViN4zDxAGfq9R8i1m90uGHxo99cy10Od+lvn3hf0g==
-
-caniuse-lite@^1.0.30001400:
-  version "1.0.30001402"
-  resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001402.tgz#aa29e1f47f5055b0d0c07696a67b8b08023d14c8"
-  integrity sha512-Mx4MlhXO5NwuvXGgVb+hg65HZ+bhUYsz8QtDGDo2QmaJS2GBX47Xfi2koL86lc8K+l+htXeTEB/Aeqvezoo6Ew==
+caniuse-lite@^1.0.30001359, caniuse-lite@^1.0.30001400:
+  version "1.0.30001406"
+  resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001406.tgz"
+  integrity sha512-bWTlaXUy/rq0BBtYShc/jArYfBPjEV95euvZ8JVtO43oQExEN/WquoqpufFjNu4kSpi5cy5kMbNvzztWDfv1Jg==
 
 capture-exit@^2.0.0:
   version "2.0.0"