diff --git a/packages/mermaid/src/diagrams/git/gitGraph.spec.ts b/packages/mermaid/src/diagrams/git/gitGraph.spec.ts index 9b3236f907..0a5235ab63 100644 --- a/packages/mermaid/src/diagrams/git/gitGraph.spec.ts +++ b/packages/mermaid/src/diagrams/git/gitGraph.spec.ts @@ -306,6 +306,96 @@ describe('when parsing a gitGraph', function () { expect(commits.get(key)?.type).toBe(2); }); + it('should handle a gitGraph commit with custom commit color RED only', async () => { + const str = `gitGraph: + commit color: RED + `; + + await parser.parse(str); + const commits = db.getCommits(); + expect(commits.size).toBe(1); + expect(db.getCurrentBranch()).toBe('main'); + expect(db.getDirection()).toBe('LR'); + expect(db.getBranches().size).toBe(1); + const key = commits.keys().next().value; + expect(commits.get(key)?.message).toBe(''); + expect(commits.get(key)?.id).not.toBeNull(); + expect(commits.get(key)?.tags).toStrictEqual([]); + expect(commits.get(key)?.color).toBe(1); + }); + + it('should handle a gitGraph commit with custom commit color BLUE only', async () => { + const str = `gitGraph: + commit color: BLUE + `; + + await parser.parse(str); + const commits = db.getCommits(); + expect(commits.size).toBe(1); + expect(db.getCurrentBranch()).toBe('main'); + expect(db.getDirection()).toBe('LR'); + expect(db.getBranches().size).toBe(1); + const key = commits.keys().next().value; + expect(commits.get(key)?.message).toBe(''); + expect(commits.get(key)?.id).not.toBeNull(); + expect(commits.get(key)?.tags).toStrictEqual([]); + expect(commits.get(key)?.color).toBe(2); + }); + + it('should handle a gitGraph commit with custom commit color GREEN only', async () => { + const str = `gitGraph: + commit color: GREEN + `; + + await parser.parse(str); + const commits = db.getCommits(); + expect(commits.size).toBe(1); + expect(db.getCurrentBranch()).toBe('main'); + expect(db.getDirection()).toBe('LR'); + expect(db.getBranches().size).toBe(1); + const key = commits.keys().next().value; + expect(commits.get(key)?.message).toBe(''); + expect(commits.get(key)?.id).not.toBeNull(); + expect(commits.get(key)?.tags).toStrictEqual([]); + expect(commits.get(key)?.color).toBe(3); + }); + + it('should handle a gitGraph commit with custom commit color BLACK only', async () => { + const str = `gitGraph: + commit color: BLACK + `; + + await parser.parse(str); + const commits = db.getCommits(); + expect(commits.size).toBe(1); + expect(db.getCurrentBranch()).toBe('main'); + expect(db.getDirection()).toBe('LR'); + expect(db.getBranches().size).toBe(1); + const key = commits.keys().next().value; + expect(commits.get(key)?.message).toBe(''); + expect(commits.get(key)?.id).not.toBeNull(); + expect(commits.get(key)?.tags).toStrictEqual([]); + expect(commits.get(key)?.color).toBe(0); + }); + + it('should handle a gitGraph commit with default commit color BLACK', async () => { + const str = `gitGraph: + commit + `; + + await parser.parse(str); + const commits = db.getCommits(); + expect(commits.size).toBe(1); + expect(db.getCurrentBranch()).toBe('main'); + expect(db.getDirection()).toBe('LR'); + expect(db.getBranches().size).toBe(1); + const key = commits.keys().next().value; + expect(commits.get(key)?.message).toBe(''); + expect(commits.get(key)?.id).not.toBeNull(); + expect(commits.get(key)?.tags).toStrictEqual([]); + expect(commits.get(key)?.color).toBe(0); + }); + it('should handle a gitGraph commit with custom commit type REVERSE only', async () => { const str = `gitGraph: commit type: REVERSE @@ -471,7 +561,7 @@ describe('when parsing a gitGraph', function () { it('should handle a gitGraph commit with custom type,tag, msg, commit id,', async () => { const str = `gitGraph: commit type:REVERSE tag: "test tag" msg: "test msg" id: "1111" - + `; await parser.parse(str); @@ -1255,7 +1345,7 @@ describe('when parsing a gitGraph', function () { it('should throw error when trying to merge branch which has no commits', async () => { const str = `gitGraph branch test1 - + checkout main commit merge test1 diff --git a/packages/mermaid/src/diagrams/git/gitGraphAst.ts b/packages/mermaid/src/diagrams/git/gitGraphAst.ts index 44597e9d78..3f0ec0ed45 100644 --- a/packages/mermaid/src/diagrams/git/gitGraphAst.ts +++ b/packages/mermaid/src/diagrams/git/gitGraphAst.ts @@ -20,7 +20,7 @@ import type { BranchDB, CherryPickDB, } from './gitGraphTypes.js'; -import { commitType } from './gitGraphTypes.js'; +import { commitColor, commitType } from './gitGraphTypes.js'; import { ImperativeState } from '../../utils/imperativeState.js'; import DEFAULT_CONFIG from '../../defaultConfig.js'; @@ -107,6 +107,7 @@ export const commit = function (commitDB: CommitDB) { let id = commitDB.id; const type = commitDB.type; let tags = commitDB.tags; + const color = commitDB.color; log.info('commit', msg, id, type, tags); log.debug('Entering commit:', msg, id, type, tags); @@ -119,6 +120,7 @@ export const commit = function (commitDB: CommitDB) { message: msg, seq: state.records.seq++, type: type ?? commitType.NORMAL, + color: color ?? commitColor.BLACK, tags: tags ?? [], parents: state.records.head == null ? [] : [state.records.head.id], branch: state.records.currBranch, @@ -244,6 +246,7 @@ export const merge = (mergeDB: MergeDB): void => { parents: state.records.head == null ? [] : [state.records.head.id, verifiedBranch], branch: state.records.currBranch, type: commitType.MERGE, + color: commitColor.BLACK, customType: overrideType, customId: customId ? true : false, tags: customTags ?? [], @@ -347,6 +350,7 @@ export const cherryPick = function (cherryPickDB: CherryPickDB) { parents: state.records.head == null ? [] : [state.records.head.id, sourceCommit.id], branch: state.records.currBranch, type: commitType.CHERRY_PICK, + color: commitColor.BLACK, tags: tags ? tags.filter(Boolean) : [ @@ -494,6 +498,7 @@ export const getHead = function () { export const db: GitGraphDB = { commitType, + commitColor, getConfig, setDirection, setOptions, diff --git a/packages/mermaid/src/diagrams/git/gitGraphParser.ts b/packages/mermaid/src/diagrams/git/gitGraphParser.ts index c56bc6f449..50f7b7a05b 100644 --- a/packages/mermaid/src/diagrams/git/gitGraphParser.ts +++ b/packages/mermaid/src/diagrams/git/gitGraphParser.ts @@ -4,7 +4,7 @@ import type { ParserDefinition } from '../../diagram-api/types.js'; import { log } from '../../logger.js'; import { populateCommonDb } from '../common/populateCommonDb.js'; import { db } from './gitGraphAst.js'; -import { commitType } from './gitGraphTypes.js'; +import { commitColor, commitType } from './gitGraphTypes.js'; import type { CheckoutAst, CherryPickingAst, @@ -53,6 +53,7 @@ const parseCommit = (commit: CommitAst): CommitDB => { msg: commit.message ?? '', type: commit.type !== undefined ? commitType[commit.type] : commitType.NORMAL, tags: commit.tags ?? undefined, + color: commit.color !== undefined ? commitColor[commit.color] : commitColor.BLACK, }; return commitDB; }; @@ -103,6 +104,7 @@ if (import.meta.vitest) { const mockDB: GitGraphDBParseProvider = { commitType: commitType, + commitColor: commitColor, setDirection: vi.fn(), commit: vi.fn(), branch: vi.fn(), diff --git a/packages/mermaid/src/diagrams/git/gitGraphRenderer.ts b/packages/mermaid/src/diagrams/git/gitGraphRenderer.ts index 39a64a623b..dd6c27ed63 100644 --- a/packages/mermaid/src/diagrams/git/gitGraphRenderer.ts +++ b/packages/mermaid/src/diagrams/git/gitGraphRenderer.ts @@ -283,6 +283,18 @@ const drawCommitBullet = ( } }; +const commitLabelColorClass = (color: number) => { + if (color == 1) { + return 'commit-label-color-red'; + } else if (color == 2) { + return 'commit-label-color-blue'; + } else if (color == 3) { + return 'commit-label-color-green'; + } else { + return 'commit-label'; + } +}; + const drawCommitLabel = ( gLabels: d3.Selection, commit: Commit, @@ -300,7 +312,7 @@ const drawCommitLabel = ( .append('text') .attr('x', pos) .attr('y', commitPosition.y + 25) - .attr('class', 'commit-label') + .attr('class', commitLabelColorClass(commit.color)) .text(commit.id); const bbox = text.node()?.getBBox(); @@ -1013,6 +1025,7 @@ if (import.meta.vitest) { tags: [], parents: [], branch: 'main', + color: 0, }, ], [ @@ -1025,6 +1038,7 @@ if (import.meta.vitest) { tags: [], parents: ['ZERO'], branch: 'feature', + color: 0, }, ], [ @@ -1037,6 +1051,7 @@ if (import.meta.vitest) { tags: [], parents: ['A'], branch: 'feature', + color: 0, }, ], [ @@ -1050,6 +1065,7 @@ if (import.meta.vitest) { parents: ['ZERO', 'B'], branch: 'main', customId: true, + color: 0, }, ], [ @@ -1062,6 +1078,7 @@ if (import.meta.vitest) { tags: [], parents: ['ZERO'], branch: 'release', + color: 0, }, ], [ @@ -1074,6 +1091,7 @@ if (import.meta.vitest) { tags: [], parents: ['C', 'M'], branch: 'release', + color: 0, }, ], [ @@ -1086,6 +1104,7 @@ if (import.meta.vitest) { tags: [], parents: ['5-8928ea0'], branch: 'release', + color: 0, }, ], [ @@ -1098,6 +1117,7 @@ if (import.meta.vitest) { tags: [], parents: ['D', 'M'], branch: 'release', + color: 0, }, ], ]); @@ -1179,6 +1199,7 @@ if (import.meta.vitest) { tags: [], parents: [], branch: 'main', + color: 0, }, ], [ @@ -1191,6 +1212,7 @@ if (import.meta.vitest) { tags: [], parents: ['1-abcdefg'], branch: 'main', + color: 0, }, ], [ @@ -1203,6 +1225,7 @@ if (import.meta.vitest) { tags: [], parents: ['2-abcdefg'], branch: 'develop', + color: 0, }, ], [ @@ -1215,6 +1238,7 @@ if (import.meta.vitest) { tags: [], parents: ['3-abcdefg'], branch: 'develop', + color: 0, }, ], [ @@ -1227,6 +1251,7 @@ if (import.meta.vitest) { tags: [], parents: ['2-abcdefg'], branch: 'feature', + color: 0, }, ], [ @@ -1239,6 +1264,7 @@ if (import.meta.vitest) { tags: [], parents: ['5-abcdefg'], branch: 'feature', + color: 0, }, ], [ @@ -1251,6 +1277,7 @@ if (import.meta.vitest) { tags: [], parents: ['2-abcdefg'], branch: 'main', + color: 0, }, ], [ @@ -1263,6 +1290,7 @@ if (import.meta.vitest) { tags: [], parents: ['7-abcdefg'], branch: 'main', + color: 0, }, ], ]); diff --git a/packages/mermaid/src/diagrams/git/gitGraphTypes.ts b/packages/mermaid/src/diagrams/git/gitGraphTypes.ts index 32b951bcc4..3ba4c5e590 100644 --- a/packages/mermaid/src/diagrams/git/gitGraphTypes.ts +++ b/packages/mermaid/src/diagrams/git/gitGraphTypes.ts @@ -1,6 +1,13 @@ import type { GitGraphDiagramConfig } from '../../config.type.js'; import type { DiagramDBBase } from '../../diagram-api/types.js'; +export const commitColor = { + BLACK: 0, + RED: 1, + BLUE: 2, + GREEN: 3, +} as const; + export const commitType = { NORMAL: 0, REVERSE: 1, @@ -13,6 +20,7 @@ export interface CommitDB { msg: string; id: string; type: number; + color: number; tags?: string[]; } @@ -40,6 +48,7 @@ export interface Commit { message: string; seq: number; type: number; + color: number; tags: string[]; parents: string[]; branch: string; @@ -59,6 +68,7 @@ export interface CommitAst { message?: string; tags?: string[]; type?: 'NORMAL' | 'REVERSE' | 'HIGHLIGHT'; + color?: 'BLACK' | 'RED' | 'GREEN' | 'BLUE'; } export interface BranchAst { @@ -89,6 +99,7 @@ export interface CherryPickingAst { export interface GitGraphDB extends DiagramDBBase { commitType: typeof commitType; + commitColor: typeof commitColor; setDirection: (dir: DiagramOrientation) => void; setOptions: (rawOptString: string) => void; getOptions: () => any; @@ -110,6 +121,7 @@ export interface GitGraphDB extends DiagramDBBase { export interface GitGraphDBParseProvider extends Partial { commitType: typeof commitType; + commitColor: typeof commitColor; setDirection: (dir: DiagramOrientation) => void; commit: (commitDB: CommitDB) => void; branch: (branchDB: BranchDB) => void; diff --git a/packages/mermaid/src/diagrams/git/styles.js b/packages/mermaid/src/diagrams/git/styles.js index 1836e9dff6..3ecdf51259 100644 --- a/packages/mermaid/src/diagrams/git/styles.js +++ b/packages/mermaid/src/diagrams/git/styles.js @@ -27,6 +27,9 @@ const getStyles = (options) => stroke-dasharray: 2; } .commit-label { font-size: ${options.commitLabelFontSize}; fill: ${options.commitLabelColor};} + .commit-label-color-red { font-size: ${options.commitLabelFontSize}; fill: red;} + .commit-label-color-blue { font-size: ${options.commitLabelFontSize}; fill: blue;} + .commit-label-color-green { font-size: ${options.commitLabelFontSize}; fill: green;} .commit-label-bkg { font-size: ${options.commitLabelFontSize}; fill: ${ options.commitLabelBackground }; opacity: 0.5; } diff --git a/packages/parser/src/language/gitGraph/gitGraph.langium b/packages/parser/src/language/gitGraph/gitGraph.langium index 1571ebba8a..699d061d01 100644 --- a/packages/parser/src/language/gitGraph/gitGraph.langium +++ b/packages/parser/src/language/gitGraph/gitGraph.langium @@ -39,8 +39,8 @@ entry GitGraph: Statement : Commit | Branch -| Merge -| Checkout +| Merge +| Checkout | CherryPicking ; @@ -48,12 +48,13 @@ Direction: dir=('LR' | 'TB' | 'BT'); Commit: - 'commit' + 'commit' ( - 'id:' id=STRING + 'id:' id=STRING |'msg:'? message=STRING |'tag:' tags+=STRING |'type:' type=('NORMAL' | 'REVERSE' | 'HIGHLIGHT') + |'color:' color=('RED' | 'GREEN' | 'BLUE' | 'BLACK') )* EOL; Branch: 'branch' name=(ID|STRING) @@ -72,7 +73,7 @@ Checkout: ('checkout'|'switch') branch=(ID|STRING) EOL; CherryPicking: - 'cherry-pick' + 'cherry-pick' ( 'id:' id=STRING |'tag:' tags+=STRING