Skip to content

Commit

Permalink
Merge pull request #2832 from gwincr11/cg-accessibility
Browse files Browse the repository at this point in the history
ER and Sequence Chart Accessibility
  • Loading branch information
knsv committed Mar 31, 2022
2 parents 9123757 + 50f522a commit 4487754
Show file tree
Hide file tree
Showing 14 changed files with 242 additions and 14 deletions.
45 changes: 45 additions & 0 deletions demos/er.html
@@ -0,0 +1,45 @@
<!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: 'trebuchet ms', verdana, arial; */
font-family: 'Courier New', Courier, monospace !important;
}
</style>
</head>

<body>


<div class="mermaid">
erDiagram
title This is a title
accDescription Test a description
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
</div>

<script src="./mermaid.js"></script>
<script>
mermaid.initialize({
theme: 'forest',
// themeCSS: '.node rect { fill: red; }',
logLevel: 3,
securityLevel: 'loose',
flowchart: { curve: 'basis' },
gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50 },
// sequenceDiagram: { actorMargin: 300 } // deprecated
});
</script>

</body>

</html>
2 changes: 2 additions & 0 deletions demos/flowchart.html
Expand Up @@ -230,6 +230,8 @@ <h3>graph</h3>
<h3>flowchart</h3>
<div class="mermaid">
flowchart TD
title Christmas
accDescription Get money
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me thinksssssx<br/>sssssssssssssssssssuuu<br />tttsssssssssssssssssssssss}
C -->|One| D[Laptop]
Expand Down
1 change: 1 addition & 0 deletions demos/index.html
Expand Up @@ -467,6 +467,7 @@

<div class="mermaid">
sequenceDiagram
accDescription Hello friends
participant Alice
participant Bob
participant John as John<br />Second Line
Expand Down
72 changes: 72 additions & 0 deletions demos/sequence.html
@@ -0,0 +1,72 @@
<!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: 'trebuchet ms', verdana, arial; */
font-family: 'Courier New', Courier, monospace !important;
}
</style>
</head>

<body>


<div class="mermaid">
sequenceDiagram
title: FancySequenceDiagram
accDescription Test a description
participant Alice
participant Bob
participant John as John<br />Second Line
rect rgb(200, 220, 100)
rect rgb(200, 255, 200)
Alice ->> Bob: Hello Bob, how are you?
Bob-->>John: How about you John?
end
Bob--x Alice: I am good thanks!
Bob-x John: I am good thanks!
Note right of John: John thinks a long<br />long time, so long<br />that the text does<br />not fit on a row.
Bob-->Alice: Checking with John...
Note over John:wrap: John looks like he's still thinking, so Bob prods him a bit.
Bob-x John: Hey John - we're still waiting to know<br />how you're doing
Note over John:nowrap: John's trying hard not to break his train of thought.
Bob-x John:wrap: John! Are you still debating about how you're doing? How long does it take??
Note over John: After a few more moments, John<br />finally snaps out of it.
end
alt either this
Alice->>John: Yes
else or this
Alice->>John: No
else or this will happen
Alice->John: Maybe
end
par this happens in parallel
Alice -->> Bob: Parallel message 1
and
Alice -->> John: Parallel message 2
end
</div>

<script src="./mermaid.js"></script>
<script>
mermaid.initialize({
theme: 'forest',
// themeCSS: '.node rect { fill: red; }',
logLevel: 3,
securityLevel: 'loose',
flowchart: { curve: 'basis' },
gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50 },
// sequenceDiagram: { actorMargin: 300 } // deprecated
});
</script>

</body>

</html>
11 changes: 11 additions & 0 deletions launch.json
@@ -0,0 +1,11 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "attach",
"name": "Attach",
"port": 9229
}
]
}
5 changes: 3 additions & 2 deletions src/accessibility.js
Expand Up @@ -9,15 +9,16 @@
* @param id
*/
export default function addSVGAccessibilityFields(yy_parser, svg, id) {
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);

svg
.insert('desc', ':first-child')
.attr('id', 'chart-desc-' + id)
.text(description);

svg
.insert('title', ':first-child')
.attr('id', 'chart-title-' + id)
Expand Down
11 changes: 11 additions & 0 deletions src/diagrams/er/erDb.js
Expand Up @@ -5,6 +5,7 @@ import * as configApi from '../../config';
let entities = {};
let relationships = [];
let title = '';
let description = '';

const Cardinality = {
ZERO_OR_ONE: 'ZERO_OR_ONE',
Expand Down Expand Up @@ -75,6 +76,14 @@ const getTitle = function () {
return title;
};

const setAccDescription = function (txt) {
description = txt;
};

const getAccDescription = function () {
return description;
};

const clear = function () {
entities = {};
relationships = [];
Expand All @@ -94,4 +103,6 @@ export default {
clear,
setTitle,
getTitle,
setAccDescription,
getAccDescription,
};
3 changes: 3 additions & 0 deletions src/diagrams/er/erRenderer.js
Expand Up @@ -7,6 +7,7 @@ import { getConfig } from '../../config';
import { log } from '../../logger';
import erMarkers from './erMarkers';
import { configureSvgSize } from '../../utils';
import addSVGAccessibilityFields from '../../accessibility';

const conf = {};

Expand Down Expand Up @@ -637,6 +638,8 @@ export const draw = function (text, id) {
configureSvgSize(svg, height, width, conf.useMaxWidth);

svg.attr('viewBox', `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`);

addSVGAccessibilityFields(parser.yy, svg, id);
}; // draw

export default {
Expand Down
8 changes: 8 additions & 0 deletions src/diagrams/er/parser/erDiagram.jison
Expand Up @@ -2,8 +2,14 @@

%options case-insensitive
%x open_directive type_directive arg_directive block
%x title
%x accDescription

%%
title { this.begin("title");return 'title'; }
<title>(?!\n|;|#)*[^\n]* { this.popState(); return "title_value"; }
accDescription { this.begin("accDescription");return 'accDescription'; }
<accDescription>(?!\n|;|#)*[^\n]* { this.popState(); return "description_value"; }
\%\%\{ { this.begin('open_directive'); return 'open_directive'; }
<open_directive>((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; }
<type_directive>":" { this.popState(); this.begin('arg_directive'); return ':'; }
Expand Down Expand Up @@ -84,6 +90,8 @@ statement
}
| entityName BLOCK_START BLOCK_STOP { yy.addEntity($1); }
| entityName { yy.addEntity($1); }
| title title_value { $$=$2.trim();yy.setTitle($$); }
| accDescription description_value { $$=$2.trim();yy.setAccDescription($$); }
;

entityName
Expand Down
11 changes: 11 additions & 0 deletions src/diagrams/er/parser/erDiagram.spec.js
Expand Up @@ -181,6 +181,17 @@ describe('when parsing ER diagram it...', function () {
expect(Object.keys(erDb.getEntities()).length).toBe(1);
});

it('should allow for a title and acc description', function () {
const teacherRole = 'is teacher of';
const line1 = `TEACHER }o--o{ STUDENT : "${teacherRole}"`;

erDiagram.parser.parse(
`erDiagram\ntitle graph title\n accDescription this graph is about stuff\n${line1}`
);
expect(erDb.getTitle()).toBe('graph title');
expect(erDb.getAccDescription()).toBe('this graph is about stuff');
});

it('should allow more than one relationship between the same two entities', function () {
const line1 = 'CAR ||--o{ PERSON : "insured for"';
const line2 = 'CAR }o--|| PERSON : "owned by"';
Expand Down
10 changes: 7 additions & 3 deletions src/diagrams/sequence/parser/sequenceDiagram.jison
Expand Up @@ -33,7 +33,7 @@
\%%(?!\{)[^\n]* /* skip comments */
[^\}]\%\%[^\n]* /* skip comments */
"participant" { this.begin('ID'); return 'participant'; }
"actor" { this.begin('ID'); return 'participant_actor'; }
"actor" { this.begin('ID'); return 'participant_actor'; }
<ID>[^\->:\n,;]+?(?=((?!\n)\s)+"as"(?!\n)\s|[#\n;]|$) { yytext = yytext.trim(); this.begin('ALIAS'); return 'ACTOR'; }
<ALIAS>"as" { this.popState(); this.popState(); this.begin('LINE'); return 'AS'; }
<ALIAS>(?:) { this.popState(); this.popState(); return 'NEWLINE'; }
Expand All @@ -56,7 +56,9 @@
"note" return 'note';
"activate" { this.begin('ID'); return 'activate'; }
"deactivate" { this.begin('ID'); return 'deactivate'; }
"title" return 'title';
"title"\s[^#\n;]+ return 'title';
"title:"\s[^#\n;]+ return 'legacy_title';
"accDescription"\s[^#\n;]+ return 'accDescription';
"sequenceDiagram" return 'SD';
"autonumber" return 'autonumber';
"," return ',';
Expand Down Expand Up @@ -121,7 +123,9 @@ statement
| link_statement 'NEWLINE'
| properties_statement 'NEWLINE'
| details_statement 'NEWLINE'
| title text2 'NEWLINE' {$$=[{type:'setTitle', text:$2}]}
| title {yy.setTitle($1.substring(6));$$=$1.substring(6);}
| legacy_title {yy.setTitle($1.substring(7));$$=$1.substring(7);}
| accDescription {yy.setAccDescription($1.substring(15));$$=$1.substring(15);}
| 'loop' restOfLine document end
{
$3.unshift({type: 'loopStart', loopText:yy.parseMessage($2), signalType: yy.LINETYPE.LOOP_START});
Expand Down
23 changes: 15 additions & 8 deletions src/diagrams/sequence/sequenceDb.js
Expand Up @@ -8,7 +8,7 @@ let actors = {};
let messages = [];
const notes = [];
let title = '';
let titleWrapped = false;
let description = '';
let sequenceNumbersEnabled = false;
let wrapEnabled = false;

Expand Down Expand Up @@ -122,9 +122,6 @@ export const getActorKeys = function () {
export const getTitle = function () {
return title;
};
export const getTitleWrapped = function () {
return titleWrapped;
};
export const enableSequenceNumbers = function () {
sequenceNumbersEnabled = true;
};
Expand Down Expand Up @@ -324,9 +321,9 @@ export const getActorProperty = function (actor, key) {
return undefined;
};

export const setTitle = function (titleWrap) {
title = titleWrap.text;
titleWrapped = (titleWrap.wrap === undefined && autoWrap()) || !!titleWrap.wrap;
export const setTitle = function (txt) {
let sanitizedText = sanitizeText(txt, configApi.getConfig());
title = sanitizedText;
};

export const apply = function (param) {
Expand Down Expand Up @@ -409,6 +406,15 @@ export const apply = function (param) {
}
};

const setAccDescription = function (description_lex) {
let sanitizedText = sanitizeText(description_lex, configApi.getConfig());
description = sanitizedText;
};

const getAccDescription = function () {
return description;
};

export default {
addActor,
addMessage,
Expand All @@ -428,7 +434,6 @@ export default {
getTitle,
parseDirective,
getConfig: () => configApi.getConfig().sequence,
getTitleWrapped,
clear,
parseMessage,
LINETYPE,
Expand All @@ -437,4 +442,6 @@ export default {
addNote,
setTitle,
apply,
setAccDescription,
getAccDescription,
};

0 comments on commit 4487754

Please sign in to comment.