拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Mermaid 无障碍实践:用 accTitle / accDescr 与 ARIA 属性生成可被读屏软件理解的 SVG 图表

Mermaid 无障碍实践用 accTitle / accDescr 与 ARIA 属性生成可被读屏软件理解的 SVG 图表【免费下载链接】mermaidGeneration of diagrams like flowcharts or sequence diagrams from text in a similar manner as markdown项目地址: https://gitcode.com/GitHub_Trending/me/mermaidMermaid 渲染出的图表本质是一张只有图像、没有文字的 SVG对依赖辅助技术屏幕阅读器的用户和搜索引擎而言信息几乎为零。本篇基于仓库文档 accessibility.md 与配套源码系统讲解 Mermaid 的无障碍Accessibility/a11y机制自动写入role与aria-roledescription的底层逻辑、accTitle/accDescr的完整语法与生成的 HTML 结构以及从 Langium 词法终端到渲染层addSVGa11yTitleDescription的完整实现链路帮助你在编写图表时正确标注可访问标题与描述并理解其源码级处理细节。为什么要为图表添加无障碍信息Mermaid 的使用范围不断扩大后官方开始基于社区反馈推进更完善的无障碍特性。添加无障碍信息的意义在于把视觉图表所承载的丰富信息转交给使用辅助技术的用户自然也包括搜索引擎。这背后依托的是 W3C 的 ARIAAccessible Rich Internet Applications标准与 SVG 无障碍映射SVG-AAM规范。Mermaid 的无障碍支持分两层自动层无论作者是否提供文字Mermaid 都会自动为渲染出的svg元素插入aria-roledescription作者层图表作者可以在图源码中通过accTitle可访问标题与accDescr可访问描述关键字显式提供标题与描述该能力适用于所有图表类型。官方刻意保持了各图表类型关键字与格式的一致性便于理解与维护。自动插入的 ARIA 属性role 与 aria-roledescriptionaria-roledescription会被设置为图表类型键diagram type key。注意它与图源码中使用的关键字可能略有差异例如状态图的关键字是stateDiagram-v2但类型键是stateDiagram流程图的关键字是graph/flowchart类型键则是flowchart-v2。一段自动插入aria-roledescriptionstateDiagram的 SVG 标签示例省略了部分 SVG 属性与内容svg aria-roledescriptionstateDiagram classstatediagram xmlnshttp://www.w3.org/2000/svg width100% idmermaid-1668720491568 /svg从源码看这一行为由 accessibility.ts 中的setA11yDiagramInfo完成const SVG_ROLE graphics-document document; export function setA11yDiagramInfo(svg: D3Element, diagramType: string) { svg.attr(role, SVG_ROLE); if (diagramType ! ) { svg.attr(aria-roledescription, diagramType); } }两个值得注意的实现细节role被设置为graphics-document document。源码注释解释按 SVG 标准role应当是graphics-documentARIA Graphics 1.0但实践中部分浏览器并未做到位注释中给出的时点是 2022-12-08因此追加了 ARIA 1.0 的兜底角色document以兼容仅支持 ARIA 1.0 的环境diagramType为空字符串时不会写入aria-roledescription属性。对应测试见 accessibility.spec.ts其中分别验证了role为graphics-document document、aria-roledescription等于传入的图表类型、以及空类型时该属性为null三种情况。渲染入口侧的调用链在 mermaidAPI.tsfunction addA11yInfo( diagramType: string, svgNode: D3SelectionSVGSVGElement, a11yTitle?: string, a11yDescr?: string ): void { setA11yDiagramInfo(svgNode, diagramType); addSVGa11yTitleDescription(svgNode, a11yTitle, a11yDescr, svgNode.attr(id)); }可以看到addSVGa11yTitleDescription的第四个参数baseId直接取自当前 SVG 元素的id即mermaid_xxx这正是后文 HTML 中chart-title-mermaid_xxx/chart-desc-mermaid_xxx两个 id 的来源。可访问标题与描述的 HTML 结构accTitle和accDescr会在 SVG 元素内部插入title与desc两个子元素并在svg标签上添加aria-labelledby与aria-describedby属性。下面是一段生成的 HTMLSVG 元素通过aria-labelledby指向可访问标题id chart-title-mermaid-1668725057758通过aria-describedby指向可访问描述id chart-desc-mermaid-1668725057758标题元素文本为 This is the accessible title描述元素文本为 This is an accessible description省略了部分 SVG 属性与内容svg aria-labelledbychart-title-mermaid-1668725057758 aria-describedbychart-desc-mermaid-1668725057758 xmlnshttp://www.w3.org/2000/svg width100% idmermaid-1668725057758 title idchart-title-mermaid-1668725057758This is the accessible title/title desc idchart-desc-mermaid-1668725057758This is an accessible description/desc /svg插入逻辑在 accessibility.ts 的addSVGa11yTitleDescription中export function addSVGa11yTitleDescription( svg: D3Element, a11yTitle: string | undefined, a11yDesc: string | undefined, baseId: string ): void { if (svg.insert undefined) { return; } if (a11yDesc) { const descId chart-desc-${baseId}; svg.attr(aria-describedby, descId); svg.insert(desc, :first-child).attr(id, descId).text(a11yDesc); } if (a11yTitle) { const titleId chart-title-${baseId}; svg.attr(aria-labelledby, titleId); svg.insert(title, :first-child).attr(id, titleId).text(a11yTitle); } }由此可确认几条边界行为均有 accessibility.spec.ts 中对应断言支撑标题与描述可以只写其一仅有标题时设置aria-labelledby并插入title不设置aria-describedby、不插入desc反之亦然两者均为undefined或空字符串时不设置任何 aria 属性、不插入任何子元素id的构造规则固定为chart-title-${baseId}与chart-desc-${baseId}baseId即 SVG 根元素的id源码注释同时提醒可访问标题通常不会被可视化显示、描述则从不显示例外是 Gantt 图——它会把title同时作为视觉元素与无障碍元素显示。accTitle 语法可访问标题accTitle关键字 冒号: 标题字符串字符串值到行尾结束只能占一行。accTitle: This is a single line title在词法层面accTitle由 Langium 公共语法定义。common.langium 中fragment TitleAndAccessibilities: ((accDescrACC_DESCR | accTitleACC_TITLE | titleTITLE) EOL) ; terminal ACC_TITLE: /[\t ]*accTitle[\t ]*:(?:[^\n\r]*?(?%%)|[^\n\r]*)/;从该正则可以确认文档中的两个约定关键字前允许 tab/空格缩进[\t ]*行首缩进不影响识别取值一直持续到行尾[^\n\r]*且遇到行内注释起始符%%时截断[^\n\r]*?(?%%)——即%%之后的内容不会进入标题文本。accDescr 语法可访问描述accDescr支持单行与多行两种写法。单行描述accDescr关键字 冒号: 描述字符串。accDescr: This is a single line description.多行描述accDescr关键字后不带冒号内容用花括号{}包围accDescr { This is a multiple line accessible description. It does not have a colon and is surrounded by curly brackets. }对应的词法终端在 common.langium 中terminal ACC_DESCR: /[\t ]*accDescr(?:[\t ]*:([^\n\r]*?(?%%)|[^\n\r]*)|\s*{([^}]*)})/;这是一个分支正则:后捕获组 1 对应单行写法{...}捕获组 2 对应多行写法两种写法互斥。解析后的文本清洗在 valueConverter.ts 中完成// single line title, accTitle, accDescr if (match[1] ! undefined) { return match[1].trim().replace(/[\t ]{2,}/gm, ); } // multi line accDescr if (match[2] ! undefined) { return match[2] .replace(/^\s*/gm, ) .replace(/\s$/gm, ) .replace(/[\t ]{2,}/gm, ) .replace(/[\n\r]{2,}/gm, \n); }也就是说单行值会trim并把连续空白压成单个空格多行值会逐行去除行首缩进与行尾空白、压缩行内连续空白、把连续空行压成单个换行。这就是为什么文档示例中多行描述里每行的前导缩进不会出现在最终的desc文本里。此外仓库还提供了一组独立的正则工具matcher.ts供各图表解析器自行匹配无障碍指令export const accessibilityDescrRegex /accDescr(?:[\t ]*:([^\n\r]*)|\s*{([^}]*)})/; export const accessibilityTitleRegex /accTitle[\t ]*:([^\n\r]*)/; export const titleRegex /title([\t ][^\n\r]*|)/;accTitle / accDescr 使用示例及生成的 HTML下面完整继承文档给出的两组流程图示例。示例 1单行标题 单行描述流程图的可访问标题为 Big Decisions单行可访问描述为 Bobs Burgers process for making big decisions生成的 SVG 元素 HTML省略部分属性与内容svg aria-labelledbychart-title-mermaid_382ee221 aria-describedbychart-desc-mermaid_382ee221 aria-roledescriptionflowchart-v2 xmlnshttp://www.w3.org/2000/svg width100% idmermaid_382ee221 title idchart-title-mermaid_382ee221Big decisions/title desc idchart-desc-mermaid_382ee221Bobs Burgers process for making big decisions/desc /svg示例 2单行标题 多行描述流程图的可访问标题为 Bobs Burgers Making Big Decisions多行可访问描述为 The official Bobs Burgers corporate processes that are used for making very, very big decisions. This is actually a very simple flow: identify the big decision and then make the big decision.生成的 SVG 元素 HTMLsvg aria-labelledbychart-title-mermaid_382ee221 aria-describedbychart-desc-mermaid_382ee221 aria-roledescriptionflowchart-v2 xmlnshttp://www.w3.org/2000/svg width100% idmermaid_382ee221 title idchart-title-mermaid_382ee221Big decisions/title desc idchart-desc-mermaid_382ee221 The official Bobs Burgers corporate processes that are used for making very, very big decisions. This is actually a very simple flow: identify the big decision and then make the big decision. /desc /svg其他图表类型的示例以下各图表类型的accTitle/accDescr用法完全一致直接放在图表声明之后即可。Class DiagramEntity Relationship DiagramGantt ChartGitGraphPie ChartRequirement DiagramSequence DiagramState DiagramUser Journey Diagram实现链路从图源码文本到 ARIA 属性把前面的词法定义与渲染函数串起来accTitle/accDescr的完整处理链路是Langium 词法 → 公共 AST → 图表数据库DB→ 渲染后处理。1. 解析层。各图表语法的公共片段TitleAndAccessibilities允许在图表开头连续书写accDescr/accTitle/title指令每行一条见 common.langium解析结果进入统一的DiagramAST字段accTitle/accDescr/title。2. 入库层。populateCommonDb.ts 负责把 AST 写入图表数据库export function populateCommonDb(ast: DiagramAST, db: DiagramDB) { if (ast.accDescr) { db.setAccDescription?.(ast.accDescr); } if (ast.accTitle) { db.setAccTitle?.(ast.accTitle); } if (ast.title) { db.setDiagramTitle?.(ast.title); } }这里使用可选调用?.意味着并非每个图表类型都实现了这些 setter——未实现时静默跳过。3. 存储层。各图表 DB 普遍组合了 commonDb.ts 提供的通用存取函数。值得注意其写入时会做二次清洗let accTitle ; let diagramTitle ; let accDescription ; export const setAccTitle (txt: string): void { accTitle sanitizeText(txt).replace(/^\s/g, ); }; export const setAccDescription (txt: string): void { accDescription sanitizeText(txt).replace(/\n\s/g, \n); };写入值先经过sanitizeText基于当前配置的文本清洗即仓库安全相关的文本净化逻辑因此accTitle/accDescr内容同样受安全配置约束标题会去除前导空白描述会把换行 后续空白规范化为纯换行与词法层的行级清洗相互呼应保证多行描述最终是干净的换行文本。4. 渲染层。图表渲染完成后mermaidAPI.ts 的addA11yInfo统一收尾先setA11yDiagramInfo(svgNode, diagramType)写入role与aria-roledescription再addSVGa11yTitleDescription(svgNode, a11yTitle, a11yDescr, svgNode.attr(id))按 SVG 自身 id 构造chart-title-*/chart-desc-*并插入子元素。由于 baseId 来自实际生成的唯一 SVG id同一页面渲染多张图表时各图表的 aria 引用不会互相冲突。验证依据与延伸阅读上文的关键行为均可在仓库中复核单元测试 accessibility.spec.ts覆盖role/aria-roledescription设置、空类型不设置、title/desc 四种组合都有/只有标题/只有描述/都没有下的属性与子元素断言集成测试 mermaidAPI.spec.ts以真实图源码渲染后验证aria-roledescription被设为图表类型且addSVGa11yTitleDescription链路生效端到端样例图architecture 图含 title 与无障碍指令、Cynefin 图无障碍指令样例可用于直接查看渲染结果中 title/desc 的实际输出。适用前提小结accTitle仅支持单行accDescr单行写法必须带冒号、多行写法必须用花括号且不带冒号title视觉标题与accTitle可访问标题是两个独立指令仅 Gantt 图等少数类型会把title同时显示出来。按此规范为每张关键图表补上accTitle/accDescr即可让 Mermaid 图表在辅助技术与搜索引擎侧输出确定性的、可引用的文本信息。【免费下载链接】mermaidGeneration of diagrams like flowcharts or sequence diagrams from text in a similar manner as markdown项目地址: https://gitcode.com/GitHub_Trending/me/mermaid创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门