README (GitHub)
This page is automatically copied from the repository root README.md file.
The original file is maintained for GitHub and does not contain Docusaurus-specific markup.
Edit the root README.md to update this page.
remark-kroki-a11y
A Remark plugin that adds accessible source code details and natural language descriptions to Kroki diagrams.
Note: This plugin has only been tested with Docusaurus. It should work with other unified/remark-based systems, but this has not been verified.
Features
- Expandable source code - Adds a collapsible
<details>block with the diagram source code below each diagram - Natural language descriptions - Generates human-readable descriptions for screen readers (currently supports PlantUML state diagrams)
- Tabs interface - Always uses tabs when source and (generated or fallback) description are available
- Keyboard accessible - Uses native
<details>element that works with Enter/Space - Localization - Supports Dutch (nl) and English (en)
- Per-diagram control - Use
hideSourceorhideA11yflags to control visibility
Supported Diagram Types
Works with any diagram type supported by Kroki, including:
- PlantUML
- Mermaid
- C4 (via PlantUML)
- GraphViz
- And many more...
Current A11y Description Support
| Diagram Type | PlantUML | Mermaid | Status |
|---|---|---|---|
| Class diagrams | ✅ Full | ⚠️ To test | Partial |
| State diagrams | ✅ Full | ❌ | Partial |
| Sequence diagrams | ⚠️ Beta | ⚠️ Beta | Partial |
| Activity diagrams | ⚠️ Beta | ❌ | Partial |
| C4 diagrams | ⚠️ Beta | N/A | Partial |
| ER diagrams | ❌ | ❌ | Planned |
| Gantt charts | ❌ | ❌ | Future |
| Pie charts | N/A | ❌ | Planned |
Complete Diagram Type Reference (PlantUML vs Mermaid)
UML Diagrams
| Diagram Type | PlantUML | Mermaid | A11y Support |
|---|---|---|---|
| Class Diagram | ✅ | ✅ | ✅ PlantUML, ⚠️ Mermaid |
| Sequence Diagram | ✅ | ✅ | ⚠️ Beta |
| Activity Diagram | ✅ | ❌ 1 | ⚠️ Beta |
| State Diagram | ✅ | ✅ | ✅ PlantUML |
| Use Case Diagram | ✅ | ❌ | ❌ |
| Object Diagram | ✅ | ❌ | ❌ |
| Component Diagram | ✅ | ❌ | ❌ |
| Deployment Diagram | ✅ | ❌ | ❌ |
Data & Flow Diagrams
| Diagram Type | PlantUML | Mermaid | A11y Support |
|---|---|---|---|
| ER Diagram | ✅ | ✅ | ❌ Planned |
| Flowchart | ❌ | ✅ | ❌ |
| Pie Chart | ❌ | ✅ | ❌ Planned |
| Gantt Chart | ✅ | ✅ | ❌ |
| Mind Map | ✅ | ✅ | ❌ |
| Timeline | ❌ | ✅ | ❌ |
| XY Chart | ❌ | ✅ | ❌ |
| Quadrant Chart | ❌ | ✅ | ❌ |
Architecture & Specialized Diagrams
| Diagram Type | PlantUML | Mermaid | A11y Support |
|---|---|---|---|
| C4 Diagram | ✅ 2 | ✅ (beta) | ⚠️ Beta |
| Git Graph | ❌ | ✅ | ❌ |
| User Journey | ❌ | ✅ | ❌ |
| Sankey Diagram | ❌ | ✅ (beta) | ❌ |
| Block Diagram | ✅ | ✅ (beta) | ❌ |
| BPMN | ✅ | ❌ | ❌ |
| Archimate | ✅ | ❌ | ❌ |
| Network Diagram | ✅ | ❌ | ❌ |
| Wireframe (Salt) | ✅ | ❌ | ❌ |
| WBS | ✅ | ❌ | ❌ |
| JSON/YAML | ✅ | ❌ | ❌ |
| Requirement Diagram | ❌ | ✅ | ❌ |
| Packet Diagram | ❌ | ✅ (beta) | ❌ |
Legend: ✅ = Full support | ⚠️ = Beta/partial | ❌ = Not supported | N/A = Not applicable
Roadmap
Diagram-as-Code Formats
We support multiple diagram-as-text formats through Kroki:
| Format | UML Support | C4 | Other |
|---|---|---|---|
| PlantUML | All 14 UML types | ✅ via C4-PlantUML | Mindmaps, Gantt, etc. |
| Mermaid | Class, Sequence, State, ER | ✅ (beta) | Flowchart, Pie, etc. |
Future Diagram Types (Student Projects Welcome!)
These diagram types don't have good diagram-as-text standards yet:
- Domain Stories (egon.io) - Visual storytelling for domain modeling
- User Story Maps - Story mapping for agile planning
- Event Storming - Domain event visualization
Architecture
We use PlantUML's data structure as internal representation (IR) with adapters for each input format. See ADR-0006 for details.
The official @mermaid-js/parser npm package provides AST parsing for Mermaid diagrams, enabling conversion to our IR.
For comprehensive architecture documentation following Simon Brown's Software Guidebook structure, see the Software Guidebook (includes C4 diagrams, use cases, and component views).
For all architecture decisions, see the Architecture Decision Records (ADRs).
Installation
npm install remark-kroki-a11y
# or
yarn add remark-kroki-a11y
Usage with Docusaurus
In your docusaurus.config.js:
const rehypeRaw = require('rehype-raw').default;
// MDX node types to pass through (not processed by rehype-raw)
const passThrough = [
'mdxFlowExpression',
'mdxJsxFlowElement',
'mdxJsxTextElement',
'mdxTextExpression',
'mdxjsEsm',
];
module.exports = {
presets: [
[
'classic',
{
docs: {
remarkPlugins: [
// This plugin MUST come BEFORE remark-kroki-plugin
[require('remark-kroki-a11y'), {
showSource: true,
showA11yDescription: true,
defaultExpanded: false,
summaryText: '{type} source code for "{title}"',
a11ySummaryText: 'Natural language description for "{title}"',
tabSourceLabel: 'Source',
tabA11yLabel: 'Description',
cssClass: 'diagram-expandable-source',
languages: ['kroki'],
locale: 'en',
}],
[require('remark-kroki-plugin'), {
krokiBase: 'https://kroki.io',
lang: 'kroki',
imgRefDir: '/img/kroki',
imgDir: 'static/img/kroki',
}],
],
rehypePlugins: [
// Enable raw HTML in MDX (needed for remark plugin HTML output)
[rehypeRaw, { passThrough }],
// Fix Kroki image accessibility: alt text and aria-describedby
// Must come AFTER rehype-raw so raw HTML is parsed into AST
require('remark-kroki-a11y/rehype-kroki-a11y-img'),
],
},
},
],
],
};
Local Kroki via Docker (recommended for stable local builds)
If kroki.io is unavailable or blocked, run a local Kroki server:
docker compose -f docker-compose.kroki.yml up -d
Verify the server is reachable:
curl http://localhost:8000/health
The compose file also mounts a local include folder and sets
KROKI_PLANTUML_INCLUDE_PATH, so PlantUML can resolve:
!include domainStory.puml
Use the local server in docusaurus.config.js:
[require('remark-kroki-plugin'), {
krokiBase: 'http://localhost:8000',
lang: 'kroki',
imgRefDir: '/img/kroki',
imgDir: 'static/img/kroki',
}]
Or without editing config, set:
export KROKI_BASE_URL=http://localhost:8000
Stop it when done:
docker compose -f docker-compose.kroki.yml down
Required: Client Module and CSS
The plugin requires a client-side module for tab switching and CSS styling. These are included in the package:
// In docusaurus.config.js
module.exports = {
clientModules: [
require.resolve('remark-kroki-a11y/src/diagramTabs.js'),
],
// ...
};
For CSS, import the provided stylesheet or copy it to your project:
// In your custom.css or via import
@import 'remark-kroki-a11y/src/diagram-tabs.css';
Custom CSS and Client Module (optional)
If you want to customize the styling or tab behavior, you can copy these files to your project instead:
Client Module (src/clientModules/diagramTabs.js):
export function onRouteDidUpdate() {
const tabContainers = document.querySelectorAll('.diagram-expandable-source-tabs');
tabContainers.forEach((container) => {
const buttons = container.querySelectorAll('.diagram-expandable-source-tab-btn');
const contents = container.querySelectorAll('.diagram-expandable-source-tab-content');
buttons.forEach((button) => {
if (button.dataset.tabListener) return;
button.dataset.tabListener = 'true';
button.addEventListener('click', () => {
const tabId = button.dataset.tab;
buttons.forEach((btn) => btn.classList.remove('active'));
button.classList.add('active');
contents.forEach((content) => {
content.classList.toggle('active', content.dataset.tab === tabId);
});
});
});
});
}
CSS Styling:
/* Expandable source code block for diagrams */
.diagram-expandable-source summary {
cursor: pointer;
font-weight: 500;
padding: 0.25rem 0;
user-select: none;
font-size: 0.9em;
}
.diagram-expandable-source summary:hover {
color: var(--ifm-color-primary);
}
.diagram-expandable-source pre {
background: var(--prism-background-color, #1e1e1e);
color: var(--prism-color, #d4d4d4);
padding: 1rem;
border-radius: 4px;
overflow-x: auto;
margin: 0.5rem 0;
}
/* Tabs styling */
.diagram-expandable-source-tab-buttons {
display: flex;
border-bottom: 1px solid var(--ifm-color-emphasis-300);
}
.diagram-expandable-source-tab-btn {
padding: 0.5rem 1rem;
border: none;
background: transparent;
cursor: pointer;
border-bottom: 2px solid transparent;
}
.diagram-expandable-source-tab-btn.active {
color: var(--ifm-color-primary);
border-bottom-color: var(--ifm-color-primary);
}
.diagram-expandable-source-tab-content {
display: none;
}
.diagram-expandable-source-tab-content.active {
display: block;
}
Options
| Option | Type | Default | Description |
|---|---|---|---|
showSource | boolean | true | Show source code tab |
showA11yDescription | boolean | true | Show natural language description tab |
defaultExpanded | boolean | false | Expand details by default |
summaryText | string | '{type} source code for "{title}"' | Summary text template |
a11ySummaryText | string | 'Natural language description for "{title}"' | A11y summary text template |
tabSourceLabel | string | 'Source' | Label for source tab |
tabA11yLabel | string | 'Description' | Label for description tab |
cssClass | string | 'diagram-expandable-source' | CSS class for the details element |
languages | string[] | ['kroki'] | Code block languages to process |
locale | string | 'en' | Locale for generated descriptions ('en' or 'nl') |
fallbackA11yText | object | { en: '...', nl: '...' } | Override fallback text per locale |
Markdown Flags
Control per-diagram behavior using flags in the code block meta:
<!-- Hide source code for this diagram -->
```kroki hideSource imgType="plantuml"
@startuml
...
@enduml
```
<!-- Hide natural language description for this diagram -->
```kroki hideA11y imgType="plantuml"
@startuml
...
@enduml
```
<!-- Override automatic description with custom text -->
```kroki a11yDescriptionOverride="Zie toelichting in tekst voor beschrijving van dit diagram" imgType="plantuml"
@startuml
...
@enduml
```
The a11yDescriptionOverride attribute is useful when:
- The diagram type is not yet supported for automatic description generation
- You want to provide a more context-specific description
- The automatic description doesn't capture the intended meaning
Accessibility
This plugin improves diagram accessibility by:
- Providing source code - Screen readers can read the diagram syntax (PlantUML, Mermaid, etc.) which describes the structure
- Generating natural language descriptions - For supported diagram types, creates human-readable text descriptions
- Keyboard navigation - Uses native
<details>elements accessible via keyboard - Proper alt text - The
rehype-kroki-a11y-imgplugin replaces hash-based alt text with meaningful titles - ARIA linkage - Adds
aria-describedbyto images pointing to the natural language description section
Documentation Site
This plugin includes a live documentation site built with Docusaurus that besides documenting the plugin also demonstrates all features with working examples.
Running Locally
# From the repository root:
./start-docs.sh
# Or manually:
cd test-docusaurus-site
npm install # first time only
npm start
The documentation site will be available at http://localhost:3001/remark-kroki-a11y/.
Online Documentation
📖 Live documentation: bartvanderwal.github.io/remark-kroki-a11y
CI/CD Pipeline
The documentation site is automatically built and deployed to GitHub Pages on every push to main.
The pipeline:
- Copies hybrid documentation (README, CONTRIBUTING, ADRs) with Docusaurus front-matter
- Builds the Docusaurus site with the remark-kroki-a11y plugin
- Deploys to GitHub Pages
Single Source of Truth
The README.md and CONTRIBUTING.md files are maintained in the repository root for GitHub visibility. These files are automatically copied to the Docusaurus docs folder by start-docs.sh (with added front-matter for Docusaurus).
Important: Do NOT add Docusaurus-specific front-matter (the --- YAML block) to these root files, as they need to render correctly on GitHub. The start-docs.sh script adds the necessary front-matter when copying.
Meta: Eating Our Own Dog Food
This project has a delightful meta aspect: we build an accessibility plugin for "diagrams-as-code" in Docusaurus, and we use Docusaurus with those same diagrams to document the plugin itself.
The technical domain: The plugin operates in the landscape of Markdown, HTML generation, and diagram-as-code syntaxes (PlantUML, Mermaid). We use these same tools to document the plugin's architecture with C4 diagrams, class diagrams, and sequence diagrams.
The problem domain: We address accessibility (a11y) for visual diagrams - a challenge driven by both the continuous documentation movement in software engineering and broader societal/legal requirements like WCAG and the European Accessibility Act.
To see a more concrete example check the Docusaurus page with diagrams and documentation for this plugin itself. We also use that to test/validate our own plugin.
In short: A plugin that makes software diagrams accessible, and uses diagrams to explain how we do that (and these then test/validate if we are succeeding).
Acknowledgments
This plugin was originally conceived by Remco Veurink, lecturer at HAN University of Applied Sciences.
Related Work
The Mermaid project is also exploring accessibility for diagram-as-code. As noted in their accessibility discussion:
While I recognize that this is not going to be easy, I also believe that Mermaid is uniquely situated to solve this problem. The entire concept of Mermaid is that we can represent this visual content as plain structured text. Mermaid diagrams aren't just static images generated in Photoshop; they are rendered dynamically from structured data.
This insight applies equally to PlantUML and other diagram-as-code formats - the structured source text is inherently accessible, we just need to present it properly.
Contributing
Want to help? Or update and run this plugin itself? See Contributing for local development setup and publishing tips.
For quality standards and acceptance criteria, see the Definition of Done.
License
MIT