From 3d7cb212c06f15e0d2da76c3830670620e8e3adf Mon Sep 17 00:00:00 2001 From: Cory Gwin Date: Thu, 7 Apr 2022 18:01:44 +0000 Subject: [PATCH 1/2] feat: Add accessibility fields to requirements diagram --- .../integration/rendering/requirement.spec.js | 65 +++++++++++ demos/requirements.html | 106 ++++++++++++++++++ src/diagrams/class/parser/classDiagram.jison | 1 + .../parser/requirementDiagram.jison | 8 +- .../parser/requirementDiagram.spec.js | 23 ++++ src/diagrams/requirement/requirementDb.js | 27 +++++ .../requirement/requirementRenderer.js | 3 + 7 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 demos/requirements.html diff --git a/cypress/integration/rendering/requirement.spec.js b/cypress/integration/rendering/requirement.spec.js index 0bf9014bf9..aca990c42a 100644 --- a/cypress/integration/rendering/requirement.spec.js +++ b/cypress/integration/rendering/requirement.spec.js @@ -46,4 +46,69 @@ describe('Requirement diagram', () => { ); cy.get('svg'); }); + + it('should render accessibility tags', function () { + const expectedTitle = 'Gantt Diagram'; + const expectedAccDescription = 'Tasks for Q4'; + renderGraph( + ` + requirementDiagram + title: ${expectedTitle} + accDescription: ${expectedAccDescription} + + requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + functionalRequirement test_req2 { + id: 1.1 + text: the second test text. + risk: low + verifymethod: inspection + } + + performanceRequirement test_req3 { + id: 1.2 + text: the third test text. + risk: medium + verifymethod: demonstration + } + + element test_entity { + type: simulation + } + + element test_entity2 { + type: word doc + docRef: reqs/test_entity + } + + + test_entity - satisfies -> test_req2 + test_req - traces -> test_req2 + test_req - contains -> test_req3 + test_req <- copies - test_entity2 + `, + {} + ); + 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/requirements.html b/demos/requirements.html new file mode 100644 index 0000000000..e2dfd738a7 --- /dev/null +++ b/demos/requirements.html @@ -0,0 +1,106 @@ + + + + + + + Mermaid Quick Test Page + + + + + + + +
+ requirementDiagram + title This is a title + requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + functionalRequirement test_req2 { + id: 1.1 + text: the second test text. + risk: low + verifymethod: inspection + } + + performanceRequirement test_req3 { + id: 1.2 + text: the third test text. + risk: medium + verifymethod: demonstration + } + + interfaceRequirement test_req4 { + id: 1.2.1 + text: the fourth test text. + risk: medium + verifymethod: analysis + } + + physicalRequirement test_req5 { + id: 1.2.2 + text: the fifth test text. + risk: medium + verifymethod: analysis + } + + designConstraint test_req6 { + id: 1.2.3 + text: the sixth test text. + risk: medium + verifymethod: analysis + } + + element test_entity { + type: simulation + } + + element test_entity2 { + type: word doc + docRef: reqs/test_entity + } + + element test_entity3 { + type: "test suite" + docRef: github.com/all_the_tests + } + + + test_entity - satisfies -> test_req2 + test_req - traces -> test_req2 + test_req - contains -> test_req3 + test_req3 - contains -> test_req4 + test_req4 - derives -> test_req5 + test_req5 - refines -> test_req6 + test_entity3 - verifies -> test_req5 + test_req <- copies - test_entity2 +
+ + + + + + + \ No newline at end of file diff --git a/src/diagrams/class/parser/classDiagram.jison b/src/diagrams/class/parser/classDiagram.jison index cd4ff75a29..80b53dd2e4 100644 --- a/src/diagrams/class/parser/classDiagram.jison +++ b/src/diagrams/class/parser/classDiagram.jison @@ -185,6 +185,7 @@ Function arguments are optional: 'call ()' simply executes 'callb start : mermaidDoc + | statments | direction | directive start ; diff --git a/src/diagrams/requirement/parser/requirementDiagram.jison b/src/diagrams/requirement/parser/requirementDiagram.jison index b8c14dfc10..b7d3089e17 100644 --- a/src/diagrams/requirement/parser/requirementDiagram.jison +++ b/src/diagrams/requirement/parser/requirementDiagram.jison @@ -21,6 +21,9 @@ \}\%\% { this.popState(); this.popState(); return 'close_directive'; } ((?:(?!\}\%\%).|\n)*) return 'arg_directive'; +"title"\s[^#\n;]+ return 'title'; +"accDescription"\s[^#\n;]+ return 'accDescription'; + (\r?\n)+ return 'NEWLINE'; \s+ /* skip all whitespace */ \#[^\n]* /* skip comments */ @@ -90,7 +93,9 @@ start directive : openDirective typeDirective closeDirective - | openDirective typeDirective ':' argDirective closeDirective; + | openDirective typeDirective ':' argDirective closeDirective + | title {yy.setTitle($1.substring(6));$$=$1.substring(6);} + | accDescription {yy.setAccDescription($1.substring(15));$$=$1.substring(15);}; openDirective : open_directive { yy.parseDirective('%%{', 'open_directive'); }; @@ -191,6 +196,7 @@ relationship | TRACES { $$=yy.Relationships.TRACES;}; + requirementName: unqString | qString; id : unqString | qString; text : unqString | qString; diff --git a/src/diagrams/requirement/parser/requirementDiagram.spec.js b/src/diagrams/requirement/parser/requirementDiagram.spec.js index 715c35bb77..9b651b6903 100644 --- a/src/diagrams/requirement/parser/requirementDiagram.spec.js +++ b/src/diagrams/requirement/parser/requirementDiagram.spec.js @@ -72,6 +72,29 @@ describe('when parsing requirement diagram it...', function () { expect(Object.keys(requirementDb.getRelationships()).length).toBe(0); }); + it('will use a title and accDescription', function () { + const expectedTitle = 'test title'; + const expectedAccDescription = 'my chart description'; + const expectedDocRef = 'test_ref'; + + let lines = [ + `requirementDiagram`, + ``, + `title ${expectedTitle}`, + `accDescription ${expectedAccDescription}`, + `element test_name {`, + `type: test_type`, + `docref: test_ref`, + `}`, + ]; + let doc = lines.join('\n'); + + reqDiagram.parser.parse(doc); + + expect(requirementDb.getTitle()).toBe(expectedTitle); + expect(requirementDb.getAccDescription()).toBe(expectedAccDescription); + }); + it('will accept full relationship definition', function () { const expectedSrc = 'a'; const expectedDest = 'b'; diff --git a/src/diagrams/requirement/requirementDb.js b/src/diagrams/requirement/requirementDb.js index a1ae6aae01..2141c24007 100644 --- a/src/diagrams/requirement/requirementDb.js +++ b/src/diagrams/requirement/requirementDb.js @@ -1,12 +1,17 @@ import * as configApi from '../../config'; import { log } from '../../logger'; import mermaidAPI from '../../mermaidAPI'; +import common from '../common/common'; let relations = []; let latestRequirement = {}; let requirements = {}; let latestElement = {}; let elements = {}; +let title = ''; +let accDescription = ''; + +const sanitizeText = (txt) => common.sanitizeText(txt, configApi.getConfig()); const RequirementType = { REQUIREMENT: 'Requirement', @@ -134,6 +139,24 @@ const clear = () => { elements = {}; }; +export const setTitle = function (txt) { + let sanitizedText = sanitizeText(txt, configApi.getConfig()); + title = sanitizedText; +}; + +export const getTitle = function () { + return title; +}; + +export const setAccDescription = function (txt) { + let sanitizedText = sanitizeText(txt, configApi.getConfig()); + accDescription = sanitizedText; +}; + +export const getAccDescription = function () { + return accDescription; +}; + export default { RequirementType, RiskLevel, @@ -149,6 +172,10 @@ export default { setNewReqText, setNewReqRisk, setNewReqVerifyMethod, + setTitle, + getTitle, + setAccDescription, + getAccDescription, addElement, getElements, diff --git a/src/diagrams/requirement/requirementRenderer.js b/src/diagrams/requirement/requirementRenderer.js index 0814b00883..96b2e0ab4d 100644 --- a/src/diagrams/requirement/requirementRenderer.js +++ b/src/diagrams/requirement/requirementRenderer.js @@ -9,6 +9,7 @@ import { parser } from './parser/requirementDiagram'; import requirementDb from './requirementDb'; import markers from './requirementMarkers'; import { getConfig } from '../../config'; +import addSVGAccessibilityFields from '../../accessibility'; const conf = {}; let relCnt = 0; @@ -377,6 +378,8 @@ export const draw = (text, id) => { configureSvgSize(svg, height, width, conf.useMaxWidth); svg.attr('viewBox', `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`); + // Adds title and description to the flow chart + addSVGAccessibilityFields(parser.yy, svg, id); }; export default { From 1d269f07e32765ec2f057702a0a347eda39c17e7 Mon Sep 17 00:00:00 2001 From: Cory Gwin Date: Thu, 7 Apr 2022 14:22:47 -0400 Subject: [PATCH 2/2] Update src/diagrams/requirement/requirementRenderer.js Co-authored-by: Lindsey Wild <35239154+lindseywild@users.noreply.github.com> --- src/diagrams/requirement/requirementRenderer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/diagrams/requirement/requirementRenderer.js b/src/diagrams/requirement/requirementRenderer.js index 96b2e0ab4d..ee26565298 100644 --- a/src/diagrams/requirement/requirementRenderer.js +++ b/src/diagrams/requirement/requirementRenderer.js @@ -378,7 +378,7 @@ export const draw = (text, id) => { configureSvgSize(svg, height, width, conf.useMaxWidth); svg.attr('viewBox', `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`); - // Adds title and description to the flow chart + // Adds title and description to the requirements diagram addSVGAccessibilityFields(parser.yy, svg, id); };