Skip to main content

README (GitHub)

Single Source of Truth

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

npm version license Node.js BDD Tests

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 hideSource or hideA11y flags 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 TypePlantUMLMermaidStatus
Class diagrams✅ Full⚠️ To testPartial
State diagrams✅ FullPartial
Sequence diagrams⚠️ Beta⚠️ BetaPartial
Activity diagrams⚠️ BetaPartial
C4 diagrams⚠️ BetaN/APartial
ER diagramsPlanned
Gantt chartsFuture
Pie chartsN/APlanned
Complete Diagram Type Reference (PlantUML vs Mermaid)

UML Diagrams

Diagram TypePlantUMLMermaidA11y Support
Class Diagram✅ PlantUML, ⚠️ Mermaid
Sequence Diagram⚠️ Beta
Activity Diagram1⚠️ Beta
State Diagram✅ PlantUML
Use Case Diagram
Object Diagram
Component Diagram
Deployment Diagram

Data & Flow Diagrams

Diagram TypePlantUMLMermaidA11y Support
ER Diagram❌ Planned
Flowchart
Pie Chart❌ Planned
Gantt Chart
Mind Map
Timeline
XY Chart
Quadrant Chart

Architecture & Specialized Diagrams

Diagram TypePlantUMLMermaidA11y Support
C4 Diagram2✅ (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:

FormatUML SupportC4Other
PlantUMLAll 14 UML types✅ via C4-PlantUMLMindmaps, Gantt, etc.
MermaidClass, 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'),
],
},
},
],
],
};

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

OptionTypeDefaultDescription
showSourcebooleantrueShow source code tab
showA11yDescriptionbooleantrueShow natural language description tab
defaultExpandedbooleanfalseExpand details by default
summaryTextstring'{type} source code for "{title}"'Summary text template
a11ySummaryTextstring'Natural language description for "{title}"'A11y summary text template
tabSourceLabelstring'Source'Label for source tab
tabA11yLabelstring'Description'Label for description tab
cssClassstring'diagram-expandable-source'CSS class for the details element
languagesstring[]['kroki']Code block languages to process
localestring'en'Locale for generated descriptions ('en' or 'nl')
fallbackA11yTextobject{ 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:

  1. Providing source code - Screen readers can read the diagram syntax (PlantUML, Mermaid, etc.) which describes the structure
  2. Generating natural language descriptions - For supported diagram types, creates human-readable text descriptions
  3. Keyboard navigation - Uses native <details> elements accessible via keyboard
  4. Proper alt text - The rehype-kroki-a11y-img plugin replaces hash-based alt text with meaningful titles
  5. ARIA linkage - Adds aria-describedby to 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:

  1. Copies hybrid documentation (README, CONTRIBUTING, ADRs) with Docusaurus front-matter
  2. Builds the Docusaurus site with the remark-kroki-a11y plugin
  3. 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.

Strategy Pattern class diagram example

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.

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

Footnotes

  1. Mermaid has no Activity Diagram; use Flowchart instead.

  2. PlantUML C4 support via the C4-PlantUML extension.