Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/feat-6270-gantt-multi-line-excludes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'mermaid': minor
---

feat(gantt): support multiple `excludes` / `includes` lines so long exclusion lists can be split into commented groups (#6270)
17 changes: 17 additions & 0 deletions cypress/integration/rendering/gantt/gantt.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -947,4 +947,21 @@ describe('Gantt diagram', () => {
{ theme: 'dark' }
);
});
it('should render multi-line excludes (issue #6270)', () => {
imgSnapshotTest(
`
gantt
dateFormat YYYY-MM-DD
title Multi-line excludes
excludes weekends
%% mid-January closures
excludes 2014-01-15 2014-01-16
%% one-off holiday
excludes 2014-01-20

section A section
Task across closures :a1, 2014-01-13, 14d
`
);
});
});
12 changes: 12 additions & 0 deletions docs/syntax/gantt.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,18 @@ The `title` is an _optional_ string to be displayed at the top of the Gantt char
The `excludes` is an _optional_ attribute that accepts specific dates in YYYY-MM-DD format, days of the week ("sunday") or "weekends", but not the word "weekdays".
These date will be marked on the graph, and be excluded from the duration calculation of tasks. Meaning that if there are excluded dates during a task interval, the number of 'skipped' days will be added to the end of the task to ensure the duration is as specified in the code.

Multiple `excludes` lines are supported and their tokens are concatenated, so long exclusion lists can be split across grouped lines with comments:

```
gantt
dateFormat DD-MM-YYYY
excludes weekends
%% week 7 is winter break
excludes 10-02-2025 11-02-2025 12-02-2025 13-02-2025 14-02-2025
%% workers holiday 1 maj
excludes 01-05-2025
```

#### Weekend (v\11.0.0+)

When excluding weekends, it is possible to configure the weekends to be either Friday and Saturday or Saturday and Sunday. By default weekends are Saturday and Sunday.
Expand Down
12 changes: 10 additions & 2 deletions packages/mermaid/src/diagrams/gantt/ganttDb.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,23 @@ export const getDateFormat = function () {
return dateFormat;
};

const mergeTokens = (existing, txt) => {
const tokens = txt
.toLowerCase()
.split(/[\s,]+/)
.filter((t) => t !== '');
return [...new Set([...existing, ...tokens])];
};

export const setIncludes = function (txt) {
includes = txt.toLowerCase().split(/[\s,]+/);
includes = mergeTokens(includes, txt);
};

export const getIncludes = function () {
return includes;
};
export const setExcludes = function (txt) {
excludes = txt.toLowerCase().split(/[\s,]+/);
excludes = mergeTokens(excludes, txt);
};

export const getExcludes = function () {
Expand Down
24 changes: 24 additions & 0 deletions packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,10 +292,34 @@ describe('when using the ganttDb', function () {
expect(() => ganttDb.getTasks()).toThrowError('Failed to find a valid date');

// Fridays are now allowed, so it should not throw an error
ganttDb.clear();
ganttDb.setDateFormat('YYYY-MM-DD');
ganttDb.setExcludes('weekends,monday,tuesday,wednesday,thursday');
ganttDb.setWeekend('saturday');
ganttDb.addSection('weekends skip test');
ganttDb.addTask('test1', 'id1,2019-02-01,7d');
expect(() => ganttDb.getTasks()).not.toThrow();
});

it('should merge tokens across multiple setExcludes calls (issue #6270)', function () {
ganttDb.setExcludes('weekends');
ganttDb.setExcludes('2019-02-06');
ganttDb.setExcludes('friday, monday');
expect(ganttDb.getExcludes()).toEqual(['weekends', '2019-02-06', 'friday', 'monday']);
});

it('should dedupe tokens across multiple setExcludes calls (issue #6270)', function () {
ganttDb.setExcludes('weekends,2019-02-06');
ganttDb.setExcludes('weekends 2019-02-07');
expect(ganttDb.getExcludes()).toEqual(['weekends', '2019-02-06', '2019-02-07']);
});

it('should merge tokens across multiple setIncludes calls (issue #6270)', function () {
ganttDb.setIncludes('2019-02-06');
ganttDb.setIncludes('2019-02-07,2019-02-08');
expect(ganttDb.getIncludes()).toEqual(['2019-02-06', '2019-02-07', '2019-02-08']);
});

it('should maintain the order in which tasks are created', function () {
ganttDb.setAccTitle('Project Execution');
ganttDb.setDateFormat('YYYY-MM-DD');
Expand Down
20 changes: 20 additions & 0 deletions packages/mermaid/src/diagrams/gantt/parser/gantt.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,26 @@ describe('when parsing a gantt diagram it', function () {

expect(parserFnConstructor(str)).not.toThrow();
});
it('should concatenate tokens across multiple excludes lines (issue #6270)', function () {
const str = [
'gantt',
'dateFormat DD-MM-YYYY',
'excludes weekends',
'%% week 7 is winter break',
'excludes 10-02-2025 11-02-2025 12-02-2025',
'%% workers holiday 1 maj',
'excludes 01-05-2025',
].join('\n');

expect(parserFnConstructor(str)).not.toThrow();
expect(ganttDb.getExcludes()).toEqual([
'weekends',
'10-02-2025',
'11-02-2025',
'12-02-2025',
'01-05-2025',
]);
});
it('should handle a todayMarker definition', function () {
spyOn(ganttDb, 'setTodayMarker');
const str =
Expand Down
12 changes: 12 additions & 0 deletions packages/mermaid/src/docs/syntax/gantt.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,18 @@ The `title` is an _optional_ string to be displayed at the top of the Gantt char
The `excludes` is an _optional_ attribute that accepts specific dates in YYYY-MM-DD format, days of the week ("sunday") or "weekends", but not the word "weekdays".
These date will be marked on the graph, and be excluded from the duration calculation of tasks. Meaning that if there are excluded dates during a task interval, the number of 'skipped' days will be added to the end of the task to ensure the duration is as specified in the code.

Multiple `excludes` lines are supported and their tokens are concatenated, so long exclusion lists can be split across grouped lines with comments:

```
gantt
dateFormat DD-MM-YYYY
excludes weekends
%% week 7 is winter break
excludes 10-02-2025 11-02-2025 12-02-2025 13-02-2025 14-02-2025
%% workers holiday 1 maj
excludes 01-05-2025
```

#### Weekend (v\11.0.0+)

When excluding weekends, it is possible to configure the weekends to be either Friday and Saturday or Saturday and Sunday. By default weekends are Saturday and Sunday.
Expand Down
Loading