diff --git a/.changeset/graphviz-diagrams.md b/.changeset/graphviz-diagrams.md
new file mode 100644
index 00000000..6fa8d856
--- /dev/null
+++ b/.changeset/graphviz-diagrams.md
@@ -0,0 +1,5 @@
+---
+'@doc-kit/generator-react': minor
+---
+
+Render ` ```dot ` code blocks as Graphviz diagrams when the optional `@hpcc-js/wasm-graphviz` dependency is installed, with `${light|dark}` colors rendering a diagram per color scheme.
diff --git a/packages/react/package.json b/packages/react/package.json
index 843b1f89..48e2b01e 100644
--- a/packages/react/package.json
+++ b/packages/react/package.json
@@ -59,6 +59,15 @@
"vite": "~8.3.1"
},
"devDependencies": {
+ "@hpcc-js/wasm-graphviz": "^1.22.0",
"dedent": "^1.7.2"
+ },
+ "peerDependencies": {
+ "@hpcc-js/wasm-graphviz": "^1.22.0"
+ },
+ "peerDependenciesMeta": {
+ "@hpcc-js/wasm-graphviz": {
+ "optional": true
+ }
}
}
diff --git a/packages/react/src/html/ui/index.css b/packages/react/src/html/ui/index.css
index 6653b39e..09f595e6 100644
--- a/packages/react/src/html/ui/index.css
+++ b/packages/react/src/html/ui/index.css
@@ -204,4 +204,18 @@ main {
}
}
}
+
+ /* Graphviz diagrams; with colors for each color scheme, there is one per
+ scheme, and the one of the current scheme shows */
+ .diagram svg {
+ display: block;
+ max-width: 100%;
+ height: auto;
+ margin: 1rem auto;
+ }
+
+ :where([data-theme='dark']) & .diagram-light,
+ :where(:root:not([data-theme='dark'])) & .diagram-dark {
+ display: none;
+ }
}
diff --git a/packages/react/src/jsx-ast/utils/plugins/__tests__/diagrams.test.mjs b/packages/react/src/jsx-ast/utils/plugins/__tests__/diagrams.test.mjs
new file mode 100644
index 00000000..4b7754d7
--- /dev/null
+++ b/packages/react/src/jsx-ast/utils/plugins/__tests__/diagrams.test.mjs
@@ -0,0 +1,44 @@
+import assert from 'node:assert/strict';
+import { describe, it } from 'node:test';
+
+import { u } from 'unist-builder';
+
+import transformDiagrams, { renderDiagram } from '../diagrams.mjs';
+
+const transform = transformDiagrams();
+
+describe('transformDiagrams', () => {
+ it('renders ```dot code blocks as inline SVG', () => {
+ const tree = u('root', [u('code', { lang: 'dot' }, 'digraph { a -> b }')]);
+
+ transform(tree);
+
+ const [node] = tree.children;
+ assert.equal(node.type, 'html');
+ assert.match(
+ node.value,
+ /^
[\s\S]*