mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-14 06:43:25 +08:00
Merge pull request #2912 from el-mapache/feat/gantt-diagram-accessibility
Adds accDescription to Gantt, draws tags to svg
This commit is contained in:
commit
266bce45f2
@ -291,4 +291,36 @@ describe('Gantt diagram', () => {
|
|||||||
{ gantt: { topAxis: true } }
|
{ 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);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
43
demos/gantt.html
Normal file
43
demos/gantt.html
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<title>Mermaid Quick Test Page</title>
|
||||||
|
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=">
|
||||||
|
<style>
|
||||||
|
div.mermaid {
|
||||||
|
font-family: 'Courier New', Courier, monospace !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<!-- accDescription Tasks for Q4 -->
|
||||||
|
<div class="mermaid">
|
||||||
|
gantt
|
||||||
|
title A Gantt Diagram
|
||||||
|
accDescription Remaining Q4 Tasks
|
||||||
|
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
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="./mermaid.js"></script>
|
||||||
|
<script>
|
||||||
|
mermaid.initialize({
|
||||||
|
logLevel: 3,
|
||||||
|
securityLevel: 'loose',
|
||||||
|
gantt: { axisFormat: '%m/%d/%Y' },
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
@ -1,17 +1,21 @@
|
|||||||
/**
|
/**
|
||||||
* This method will add a basic title and description element to a chart. The yy parser will need to
|
* 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,
|
* 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
|
* which is generally not displayed and the accDescription is the description element on the chart,
|
||||||
* also not displayed.
|
* which is never displayed.
|
||||||
|
*
|
||||||
|
* The following charts display their title as a visual and accessibility element:
|
||||||
|
* gantt
|
||||||
*
|
*
|
||||||
* @param yy_parser
|
* @param yy_parser
|
||||||
* @param svg
|
* @param svg
|
||||||
* @param id
|
* @param id
|
||||||
*/
|
*/
|
||||||
export default function addSVGAccessibilityFields(yy_parser, svg, id) {
|
export default function addSVGAccessibilityFields(yy_parser, svg, id) {
|
||||||
if (typeof svg.insert == 'undefined') {
|
if (typeof svg.insert === 'undefined') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let title_string = yy_parser.getTitle();
|
let title_string = yy_parser.getTitle();
|
||||||
let description = yy_parser.getAccDescription();
|
let description = yy_parser.getAccDescription();
|
||||||
svg.attr('role', 'img').attr('aria-labelledby', 'chart-title-' + id + ' chart-desc-' + id);
|
svg.attr('role', 'img').attr('aria-labelledby', 'chart-title-' + id + ' chart-desc-' + id);
|
||||||
|
@ -4,6 +4,7 @@ import { log } from '../../logger';
|
|||||||
import * as configApi from '../../config';
|
import * as configApi from '../../config';
|
||||||
import utils from '../../utils';
|
import utils from '../../utils';
|
||||||
import mermaidAPI from '../../mermaidAPI';
|
import mermaidAPI from '../../mermaidAPI';
|
||||||
|
import common from '../common/common';
|
||||||
|
|
||||||
let dateFormat = '';
|
let dateFormat = '';
|
||||||
let axisFormat = '';
|
let axisFormat = '';
|
||||||
@ -12,6 +13,7 @@ let includes = [];
|
|||||||
let excludes = [];
|
let excludes = [];
|
||||||
let links = {};
|
let links = {};
|
||||||
let title = '';
|
let title = '';
|
||||||
|
let accDescription = '';
|
||||||
let sections = [];
|
let sections = [];
|
||||||
let tasks = [];
|
let tasks = [];
|
||||||
let currentSection = '';
|
let currentSection = '';
|
||||||
@ -23,6 +25,10 @@ let topAxis = false;
|
|||||||
// The serial order of the task in the script
|
// The serial order of the task in the script
|
||||||
let lastOrder = 0;
|
let lastOrder = 0;
|
||||||
|
|
||||||
|
const sanitizeText = function (txt) {
|
||||||
|
return common.sanitizeText(txt, configApi.getConfig());
|
||||||
|
};
|
||||||
|
|
||||||
export const parseDirective = function (statement, context, type) {
|
export const parseDirective = function (statement, context, type) {
|
||||||
mermaidAPI.parseDirective(this, statement, context, type);
|
mermaidAPI.parseDirective(this, statement, context, type);
|
||||||
};
|
};
|
||||||
@ -108,13 +114,21 @@ export const getLinks = function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const setTitle = function (txt) {
|
export const setTitle = function (txt) {
|
||||||
title = txt;
|
title = sanitizeText(txt);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getTitle = function () {
|
export const getTitle = function () {
|
||||||
return title;
|
return title;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const setAccDescription = function (txt) {
|
||||||
|
accDescription = sanitizeText(txt);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getAccDescription = function () {
|
||||||
|
return accDescription;
|
||||||
|
};
|
||||||
|
|
||||||
export const addSection = function (txt) {
|
export const addSection = function (txt) {
|
||||||
currentSection = txt;
|
currentSection = txt;
|
||||||
sections.push(txt);
|
sections.push(txt);
|
||||||
@ -637,6 +651,8 @@ export default {
|
|||||||
getTodayMarker,
|
getTodayMarker,
|
||||||
setTitle,
|
setTitle,
|
||||||
getTitle,
|
getTitle,
|
||||||
|
setAccDescription,
|
||||||
|
getAccDescription,
|
||||||
addSection,
|
addSection,
|
||||||
getSections,
|
getSections,
|
||||||
getTasks,
|
getTasks,
|
||||||
|
@ -32,6 +32,7 @@ describe('when using the ganttDb', function () {
|
|||||||
fn | expected
|
fn | expected
|
||||||
${'getTasks'} | ${[]}
|
${'getTasks'} | ${[]}
|
||||||
${'getTitle'} | ${''}
|
${'getTitle'} | ${''}
|
||||||
|
${'getAccDescription'} | ${''}
|
||||||
${'getDateFormat'} | ${''}
|
${'getDateFormat'} | ${''}
|
||||||
${'getAxisFormat'} | ${''}
|
${'getAxisFormat'} | ${''}
|
||||||
${'getTodayMarker'} | ${''}
|
${'getTodayMarker'} | ${''}
|
||||||
|
@ -15,6 +15,7 @@ import common from '../common/common';
|
|||||||
import ganttDb from './ganttDb';
|
import ganttDb from './ganttDb';
|
||||||
import { getConfig } from '../../config';
|
import { getConfig } from '../../config';
|
||||||
import { configureSvgSize } from '../../utils';
|
import { configureSvgSize } from '../../utils';
|
||||||
|
import addSVGAccessibilityFields from '../../accessibility'
|
||||||
|
|
||||||
parser.yy = ganttDb;
|
parser.yy = ganttDb;
|
||||||
export const setConf = function () {
|
export const setConf = function () {
|
||||||
@ -114,6 +115,8 @@ export const draw = function (text, id) {
|
|||||||
.attr('y', conf.titleTopMargin)
|
.attr('y', conf.titleTopMargin)
|
||||||
.attr('class', 'titleText');
|
.attr('class', 'titleText');
|
||||||
|
|
||||||
|
addSVGAccessibilityFields(parser.yy, svg, id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param tasks
|
* @param tasks
|
||||||
* @param pageWidth
|
* @param pageWidth
|
||||||
|
@ -75,6 +75,7 @@ that id.
|
|||||||
"todayMarker"\s[^\n;]+ return 'todayMarker';
|
"todayMarker"\s[^\n;]+ return 'todayMarker';
|
||||||
\d\d\d\d"-"\d\d"-"\d\d return 'date';
|
\d\d\d\d"-"\d\d"-"\d\d return 'date';
|
||||||
"title"\s[^#\n;]+ return 'title';
|
"title"\s[^#\n;]+ return 'title';
|
||||||
|
"accDescription"\s[^#\n;]+ return 'accDescription'
|
||||||
"section"\s[^#:\n;]+ return 'section';
|
"section"\s[^#:\n;]+ return 'section';
|
||||||
[^#:\n;]+ return 'taskTxt';
|
[^#:\n;]+ return 'taskTxt';
|
||||||
":"[^#\n;]+ return 'taskData';
|
":"[^#\n;]+ return 'taskData';
|
||||||
@ -116,6 +117,7 @@ statement
|
|||||||
| includes {yy.setIncludes($1.substr(9));$$=$1.substr(9);}
|
| includes {yy.setIncludes($1.substr(9));$$=$1.substr(9);}
|
||||||
| todayMarker {yy.setTodayMarker($1.substr(12));$$=$1.substr(12);}
|
| todayMarker {yy.setTodayMarker($1.substr(12));$$=$1.substr(12);}
|
||||||
| title {yy.setTitle($1.substr(6));$$=$1.substr(6);}
|
| 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);}
|
| section {yy.addSection($1.substr(8));$$=$1.substr(8);}
|
||||||
| clickStatement
|
| clickStatement
|
||||||
| taskTxt taskData {yy.addTask($1,$2);$$='task';}
|
| taskTxt taskData {yy.addTask($1,$2);$$='task';}
|
||||||
|
@ -156,4 +156,21 @@ describe('when parsing a gantt diagram it', function () {
|
|||||||
'"test0", test1, test2'
|
'"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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -21,7 +21,7 @@ describe('when parsing a sequenceDiagram', function () {
|
|||||||
parser.yy = sequenceDb;
|
parser.yy = sequenceDb;
|
||||||
parser.yy.clear();
|
parser.yy.clear();
|
||||||
});
|
});
|
||||||
it('it should handle a sequenceDiagram definition', function () {
|
it('should handle a sequenceDiagram definition', function () {
|
||||||
const str = `
|
const str = `
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
Alice->Bob:Hello Bob, how are you?
|
Alice->Bob:Hello Bob, how are you?
|
||||||
|
Loading…
x
Reference in New Issue
Block a user