From 65b0b8362569f03964fb708230b74f3ae5f4350c Mon Sep 17 00:00:00 2001 From: Adam B Date: Thu, 7 Apr 2022 13:20:58 +0000 Subject: [PATCH] Adds accDescription, draws tags to svg --- cypress/integration/rendering/gantt.spec.js | 32 ++++++++++++++ demos/gantt.html | 43 +++++++++++++++++++ src/accessibility.js | 10 +++-- src/diagrams/gantt/ganttDb.js | 11 +++++ src/diagrams/gantt/ganttDb.spec.js | 1 + src/diagrams/gantt/ganttRenderer.js | 3 ++ src/diagrams/gantt/parser/gantt.jison | 34 ++++++++------- src/diagrams/gantt/parser/gantt.spec.js | 17 ++++++++ src/diagrams/sequence/sequenceDiagram.spec.js | 2 +- 9 files changed, 133 insertions(+), 20 deletions(-) create mode 100644 demos/gantt.html diff --git a/cypress/integration/rendering/gantt.spec.js b/cypress/integration/rendering/gantt.spec.js index dd521f779..c77c26109 100644 --- a/cypress/integration/rendering/gantt.spec.js +++ b/cypress/integration/rendering/gantt.spec.js @@ -291,4 +291,36 @@ describe('Gantt diagram', () => { { gantt: { topAxis: true } } ); }); + + it('should render accessibility tags', function () { + const expectedTitle = 'Gantt Diagram'; + const expectedAccDescription = 'Tasks for Q4'; + renderGraph( + ` + gantt + title ${expectedTitle} + accDescription ${expectedAccDescription} + dateFormat YYYY-MM-DD + section Section + A task :a1, 2014-01-01, 30d + `, + {} + ); + cy.get('svg').should((svg) => { + const el = svg.get(0); + const children = Array.from(el.children); + + const titleEl = children.find(function (node) { + return node.tagName === 'title'; + }); + const descriptionEl = children.find(function (node) { + return node.tagName === 'desc'; + }); + + expect(titleEl).to.exist; + expect(titleEl.textContent).to.equal(expectedTitle); + expect(descriptionEl).to.exist; + expect(descriptionEl.textContent).to.equal(expectedAccDescription); + }); + }); }); diff --git a/demos/gantt.html b/demos/gantt.html new file mode 100644 index 000000000..68bf4a961 --- /dev/null +++ b/demos/gantt.html @@ -0,0 +1,43 @@ + + + + + + +Mermaid Quick Test Page + + + + + + + +
+gantt + title A Gantt Diagram + + dateFormat YYYY-MM-DD + section Section + A task :a1, 2014-01-01, 30d + Another task :after a1 , 20d + section Another + Task in sec :2014-01-12 , 12d + another task : 24d +
+ + + + + + + diff --git a/src/accessibility.js b/src/accessibility.js index 046fea6ad..05720500b 100644 --- a/src/accessibility.js +++ b/src/accessibility.js @@ -1,17 +1,21 @@ /** * This method will add a basic title and description element to a chart. The yy parser will need to * respond to getTitle and getAccDescription, where the title is the title element on the chart, - * which is not displayed and the accDescription is the description element on the chart, which is - * also not displayed. + * which is generally not displayed and the accDescription is the description element on the chart, + * which is never displayed. + * + * The following charts display their title as a visual and accessibility element: + * gantt * * @param yy_parser * @param svg * @param id */ export default function addSVGAccessibilityFields(yy_parser, svg, id) { - if (typeof svg.insert == 'undefined') { + if (typeof svg.insert === 'undefined') { return; } + let title_string = yy_parser.getTitle(); let description = yy_parser.getAccDescription(); svg.attr('role', 'img').attr('aria-labelledby', 'chart-title-' + id + ' chart-desc-' + id); diff --git a/src/diagrams/gantt/ganttDb.js b/src/diagrams/gantt/ganttDb.js index 88c591520..0d4bd594d 100644 --- a/src/diagrams/gantt/ganttDb.js +++ b/src/diagrams/gantt/ganttDb.js @@ -12,6 +12,7 @@ let includes = []; let excludes = []; let links = {}; let title = ''; +let accDescription = ''; let sections = []; let tasks = []; let currentSection = ''; @@ -115,6 +116,14 @@ export const getTitle = function () { return title; }; +export const setAccDescription = function (txt) { + accDescription = txt; +}; + +export const getAccDescription = function () { + return accDescription; +}; + export const addSection = function (txt) { currentSection = txt; sections.push(txt); @@ -637,6 +646,8 @@ export default { getTodayMarker, setTitle, getTitle, + setAccDescription, + getAccDescription, addSection, getSections, getTasks, diff --git a/src/diagrams/gantt/ganttDb.spec.js b/src/diagrams/gantt/ganttDb.spec.js index b94ba9617..a6960aaf2 100644 --- a/src/diagrams/gantt/ganttDb.spec.js +++ b/src/diagrams/gantt/ganttDb.spec.js @@ -32,6 +32,7 @@ describe('when using the ganttDb', function () { fn | expected ${'getTasks'} | ${[]} ${'getTitle'} | ${''} + ${'getAccDescription'} | ${''} ${'getDateFormat'} | ${''} ${'getAxisFormat'} | ${''} ${'getTodayMarker'} | ${''} diff --git a/src/diagrams/gantt/ganttRenderer.js b/src/diagrams/gantt/ganttRenderer.js index 899c61e02..b9a253ae1 100644 --- a/src/diagrams/gantt/ganttRenderer.js +++ b/src/diagrams/gantt/ganttRenderer.js @@ -15,6 +15,7 @@ import common from '../common/common'; import ganttDb from './ganttDb'; import { getConfig } from '../../config'; import { configureSvgSize } from '../../utils'; +import addSVGAccessibilityFields from '../../accessibility' parser.yy = ganttDb; export const setConf = function () { @@ -114,6 +115,8 @@ export const draw = function (text, id) { .attr('y', conf.titleTopMargin) .attr('class', 'titleText'); + addSVGAccessibilityFields(parser.yy, svg, id); + /** * @param tasks * @param pageWidth diff --git a/src/diagrams/gantt/parser/gantt.jison b/src/diagrams/gantt/parser/gantt.jison index a206da0b1..e6390c250 100644 --- a/src/diagrams/gantt/parser/gantt.jison +++ b/src/diagrams/gantt/parser/gantt.jison @@ -65,22 +65,23 @@ that id. [\s\n] this.popState(); [^\s\n]* return 'click'; -"gantt" return 'gantt'; -"dateFormat"\s[^#\n;]+ return 'dateFormat'; -"inclusiveEndDates" return 'inclusiveEndDates'; -"topAxis" return 'topAxis'; -"axisFormat"\s[^#\n;]+ return 'axisFormat'; -"includes"\s[^#\n;]+ return 'includes'; -"excludes"\s[^#\n;]+ return 'excludes'; -"todayMarker"\s[^\n;]+ return 'todayMarker'; -\d\d\d\d"-"\d\d"-"\d\d return 'date'; -"title"\s[^#\n;]+ return 'title'; -"section"\s[^#:\n;]+ return 'section'; -[^#:\n;]+ return 'taskTxt'; -":"[^#\n;]+ return 'taskData'; -":" return ':'; -<> return 'EOF'; -. return 'INVALID'; +"gantt" return 'gantt'; +"dateFormat"\s[^#\n;]+ return 'dateFormat'; +"inclusiveEndDates" return 'inclusiveEndDates'; +"topAxis" return 'topAxis'; +"axisFormat"\s[^#\n;]+ return 'axisFormat'; +"includes"\s[^#\n;]+ return 'includes'; +"excludes"\s[^#\n;]+ return 'excludes'; +"todayMarker"\s[^\n;]+ return 'todayMarker'; +\d\d\d\d"-"\d\d"-"\d\d return 'date'; +"title"\s[^#\n;]+ return 'title'; +"accDescription"\s[^#\n;]+ return 'accDescription' +"section"\s[^#:\n;]+ return 'section'; +[^#:\n;]+ return 'taskTxt'; +":"[^#\n;]+ return 'taskData'; +":" return ':'; +<> return 'EOF'; +. return 'INVALID'; /lex @@ -116,6 +117,7 @@ statement | includes {yy.setIncludes($1.substr(9));$$=$1.substr(9);} | todayMarker {yy.setTodayMarker($1.substr(12));$$=$1.substr(12);} | title {yy.setTitle($1.substr(6));$$=$1.substr(6);} + | accDescription {yy.setAccDescription($1.substr(15));$$=$1.substr(15);} | section {yy.addSection($1.substr(8));$$=$1.substr(8);} | clickStatement | taskTxt taskData {yy.addTask($1,$2);$$='task';} diff --git a/src/diagrams/gantt/parser/gantt.spec.js b/src/diagrams/gantt/parser/gantt.spec.js index bb2a3a540..ca535ebb8 100644 --- a/src/diagrams/gantt/parser/gantt.spec.js +++ b/src/diagrams/gantt/parser/gantt.spec.js @@ -156,4 +156,21 @@ describe('when parsing a gantt diagram it', function () { '"test0", test1, test2' ); }); + + it('should allow for a title and accDescription', function () { + const expectedTitle = 'Gantt Diagram'; + const expectedAccDescription = 'Tasks for Q4'; + const ganttString = + 'gantt\n' + + `title ${expectedTitle}\n` + + `accDescription ${expectedAccDescription}\n` + + 'dateFormat YYYY-MM-DD\n' + + 'section Section\n' + + 'A task :a1, 2014-01-01, 30d\n'; + + const output = parser.parse(ganttString); + + expect(ganttDb.getTitle()).toBe(expectedTitle); + expect(ganttDb.getAccDescription()).toBe(expectedAccDescription); + }); }); diff --git a/src/diagrams/sequence/sequenceDiagram.spec.js b/src/diagrams/sequence/sequenceDiagram.spec.js index aa73bf28a..06662c8be 100644 --- a/src/diagrams/sequence/sequenceDiagram.spec.js +++ b/src/diagrams/sequence/sequenceDiagram.spec.js @@ -21,7 +21,7 @@ describe('when parsing a sequenceDiagram', function () { parser.yy = sequenceDb; parser.yy.clear(); }); - it('it should handle a sequenceDiagram definition', function () { + it('should handle a sequenceDiagram definition', function () { const str = ` sequenceDiagram Alice->Bob:Hello Bob, how are you?