Skip to content

Commit 0cbbabb

Browse files
Add configurable and disableable Kroki diagram rendering (#1410)
* Add configurable and disableable Kroki diagram rendering * Update README.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update src/Markdown-it.ts Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update src/Markdown-it.ts Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent b78fb0a commit 0cbbabb

File tree

6 files changed

+93
-5
lines changed

6 files changed

+93
-5
lines changed

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,21 @@ highlightTheme : "other theme"
114114

115115
Get the theme list here https://highlightjs.org/
116116

117+
## <a id="diagramserver"></a> Diagram server (Kroki)
118+
119+
Diagram languages supported by Kroki (for example `mermaid`, `plantuml`, `graphviz`, etc.) can be rendered remotely.
120+
121+
- `revealjs.diagramServerEnabled` (default: `true`) keeps current behavior and renders diagrams as images.
122+
- `revealjs.diagramServerUrl` (default: `https://kroki.io`) lets you target your own Kroki-compatible endpoint.
123+
124+
For a fully local/offline mode, set:
125+
126+
```
127+
diagramServerEnabled: false
128+
```
129+
130+
In this mode, diagram code blocks are kept as plain code blocks and no remote diagram request is made.
131+
117132
## <a id="options"></a> Reveal.js Options
118133

119134

@@ -130,6 +145,8 @@ You can customize many setting on for your reveal.js presentation.
130145
)$</code></td></tr>
131146
<tr><td><code>revealjs.theme</code></td><td>Revealjs Theme (black, white, league, beige, sky, night, serif, simple, solarized</td><td><code>black</code></td></tr>
132147
<tr><td><code>revealjs.highlightTheme</code></td><td>Highlight Theme</td><td><code>Zenburn</code></td></tr>
148+
<tr><td><code>revealjs.diagramServerEnabled</code></td><td>Enable remote diagram rendering through a Kroki-compatible server</td><td><code>true</code></td></tr>
149+
<tr><td><code>revealjs.diagramServerUrl</code></td><td>Base URL of the Kroki-compatible diagram server</td><td><code>https://kroki.io</code></td></tr>
133150
<tr><td><code>revealjs.controls</code></td><td>Display controls in the bottom right corner</td><td><code>true</code></td></tr><tr><td><code>revealjs.progress</code></td><td>Display a presentation progress bar</td><td><code>true</code></td></tr><tr><td><code>revealjs.slideNumber</code></td><td>Display the page number of the current slide</td><td><code></code></td></tr><tr><td><code>revealjs.history</code></td><td>Push each slide change to the browser history</td><td><code></code></td></tr><tr><td><code>revealjs.keyboard</code></td><td>Enable keyboard shortcuts for navigation</td><td><code>true</code></td></tr><tr><td><code>revealjs.overview</code></td><td>Enable the slide overview mode</td><td><code>true</code></td></tr><tr><td><code>revealjs.center</code></td><td>Vertical centering of slides</td><td><code>true</code></td></tr><tr><td><code>revealjs.touch</code></td><td>Enables touch navigation on devices with touch input</td><td><code>true</code></td></tr><tr><td><code>revealjs.loop</code></td><td>Loop the presentation</td><td><code></code></td></tr><tr><td><code>revealjs.rtl</code></td><td>Change the presentation direction to be RTL</td><td><code></code></td></tr><tr><td><code>revealjs.shuffle</code></td><td>Randomizes the order of slides each time the presentation loads</td><td><code></code></td></tr><tr><td><code>revealjs.fragments</code></td><td>Turns fragments on and off globally</td><td><code>true</code></td></tr><tr><td><code>revealjs.embedded</code></td><td>Flags if the presentation is running in an embedded mode, i.e. contained within a limited portion of the screen</td><td><code></code></td></tr><tr><td><code>revealjs.help</code></td><td>Flags if we should show a help overlay when the questionmark key is pressed</td><td><code>true</code></td></tr><tr><td><code>revealjs.showNotes</code></td><td>Flags if speaker notes should be visible to all viewers</td><td><code></code></td></tr><tr><td><code>revealjs.autoSlide</code></td><td>Number of milliseconds between automatically proceeding to the next slide, disabled when set to 0, this value can be overwritten by using a data-autoslide attribute on your slides</td><td><code></code></td></tr><tr><td><code>revealjs.autoSlideMethod</code></td><td>The direction in which the slides will move whilst autoslide is activet</td><td><code>Reveal.navigateNext</code></td></tr><tr><td><code>revealjs.autoSlideStoppable</code></td><td>Stop auto-sliding after user input</td><td><code>true</code></td></tr><tr><td><code>revealjs.mouseWheel</code></td><td>Enable slide navigation via mouse wheel</td><td><code></code></td></tr><tr><td><code>revealjs.hideAddressBar</code></td><td>Hides the address bar on mobile devices</td><td><code>true</code></td></tr><tr><td><code>revealjs.previewLinks</code></td><td>Opens links in an iframe preview overlay</td><td><code></code></td></tr><tr><td><code>revealjs.transition</code></td><td>Transition style (none/fade/slide/convex/concave/zoom)</td><td><code>default</code></td></tr><tr><td><code>revealjs.transitionSpeed</code></td><td>Transition speed (default/fast/slow)</td><td><code>default</code></td></tr><tr><td><code>revealjs.backgroundTransition</code></td><td>Transition style for full page slide backgrounds (none/fade/slide/convex/concave/zoom)</td><td><code>default</code></td></tr><tr><td><code>revealjs.viewDistance</code></td><td>Number of slides away from the current that are visible</td><td><code>3</code></td></tr><tr><td><code>revealjs.parallaxBackgroundImage</code></td><td>Parallax background image</td><td><code></code></td></tr><tr><td><code>revealjs.parallaxBackgroundSize</code></td><td>Parallax background size (CSS syntax, e.g. 2100px 900px)</td><td><code></code></td></tr><tr><td><code>revealjs.parallaxBackgroundHorizontal</code></td><td>Number of pixels to move the parallax background per slide</td><td><code></code></td></tr><tr><td><code>revealjs.parallaxBackgroundVertical</code></td><td>Number of pixels to move the parallax background per slide</td><td><code></code></td></tr></table>
134151

135152

package.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,16 @@
242242
"default": "monokai",
243243
"description": "highlight.js Theme"
244244
},
245+
"revealjs.diagramServerEnabled": {
246+
"type": "boolean",
247+
"default": true,
248+
"description": "Enable remote diagram rendering for supported diagram languages via a Kroki-compatible server"
249+
},
250+
"revealjs.diagramServerUrl": {
251+
"type": "string",
252+
"default": "https://kroki.io",
253+
"description": "Base URL for the Kroki-compatible diagram server used to render supported diagram languages"
254+
},
245255
"revealjs.controls": {
246256
"type": "boolean",
247257
"default": true,

src/Configuration.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ export interface IRevealOptions {
8585

8686
css: string[]
8787
cssvariables: object | null
88+
89+
diagramServerEnabled: boolean
90+
diagramServerUrl: string
8891
}
8992
export interface IExtensionOptions {
9093
slideExplorerEnabled: boolean
@@ -169,7 +172,10 @@ export const defaultConfiguration: Configuration = {
169172
enableSearch: true,
170173

171174
css: [],
172-
cssvariables: null
175+
cssvariables: null,
176+
177+
diagramServerEnabled: true,
178+
diagramServerUrl: 'https://kroki.io'
173179
}
174180

175181

src/Markdown-it.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,29 @@ import {notesSeparator} from './utils'
1919

2020
import pako from 'pako'
2121

22+
const DEFAULT_DIAGRAM_SERVER = 'https://kroki.io'
23+
24+
interface IDiagramRenderingConfig {
25+
enabled: boolean
26+
serverBaseUrl: string
27+
}
28+
29+
const diagramRenderingConfig: IDiagramRenderingConfig = {
30+
enabled: true,
31+
serverBaseUrl: DEFAULT_DIAGRAM_SERVER,
32+
}
33+
34+
export const setDiagramRenderingConfig = (config: Partial<IDiagramRenderingConfig>) => {
35+
if (typeof config.enabled === 'boolean') {
36+
diagramRenderingConfig.enabled = config.enabled
37+
}
38+
39+
if (typeof config.serverBaseUrl === 'string') {
40+
const trimmedServerBaseUrl = config.serverBaseUrl.trim().replace(/\/$/, '')
41+
diagramRenderingConfig.serverBaseUrl = trimmedServerBaseUrl || DEFAULT_DIAGRAM_SERVER
42+
}
43+
}
44+
2245
const note = (markdown, config) => {
2346
const notesSeparator = config.notesSeparator
2447
const notesClass = 'notes'
@@ -107,13 +130,15 @@ const markdown = md({
107130
// add kroki
108131
const highlight = markdown.options.highlight
109132
markdown.options.highlight = (code, lang, attr) => {
110-
const server = 'https://kroki.io' //TODO config.serverPath || '//www.plantuml.com/plantuml/svg/';
111-
112133
if (lang && diagramTypes.indexOf(lang.toLowerCase()) >= 0) {
134+
if (!diagramRenderingConfig.enabled) {
135+
return `<pre><code class="language-${lang.toLowerCase()}">${markdown.utils.escapeHtml(code)}</code></pre>`
136+
}
137+
113138
const data = Buffer.from(code, 'utf8')
114139
const compressed = pako.deflate(data, { level: 9 })
115140
const result = Buffer.from(compressed).toString('base64').replace(/\+/g, '-').replace(/\//g, '_')
116-
return `<pre style="all:unset;"><div><img class="${lang}" src="${server}/${lang}/svg/${result}" /></div></pre>`
141+
return `<pre style="all:unset;"><div><img class="${lang.toLowerCase()}" src="${diagramRenderingConfig.serverBaseUrl}/${lang.toLowerCase()}/svg/${result}" /></div></pre>`
117142
}
118143
if (highlight !== null && highlight !== undefined) {
119144
return highlight(code, lang, attr)

src/RevealServer.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import * as ejs from 'ejs'
55
import cors from 'cors'
66
import morgan from 'morgan'
77
import * as path from 'path'
8-
import markdownit from './Markdown-it'
8+
import markdownit, { setDiagramRenderingConfig } from './Markdown-it'
99
import { exportHTML, IExportOptions } from './ExportHTML'
1010
import { Disposable } from './dispose'
1111
import { RevealContext } from './RevealContext'
@@ -114,6 +114,11 @@ export class RevealServer extends Disposable {
114114
}
115115
}
116116

117+
setDiagramRenderingConfig({
118+
enabled: context.configuration.diagramServerEnabled,
119+
serverBaseUrl: context.configuration.diagramServerUrl,
120+
})
121+
117122
const htmlSlides = context.slides.map((s) => ({
118123
...s,
119124
html: markdownit.render(s.text),
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import markdownit, { setDiagramRenderingConfig } from '../../Markdown-it'
2+
3+
describe('Markdown-it diagram server configuration', () => {
4+
afterEach(() => {
5+
setDiagramRenderingConfig({ enabled: true, serverBaseUrl: 'https://kroki.io' })
6+
})
7+
8+
test('uses the configured diagram server base URL', () => {
9+
setDiagramRenderingConfig({ serverBaseUrl: 'http://localhost:8000/' })
10+
11+
const html = markdownit.render('```mermaid\nflowchart LR\nA-->B\n```')
12+
13+
expect(html).toContain('src="http://localhost:8000/mermaid/svg/')
14+
})
15+
16+
test('falls back to a local code block when diagram rendering is disabled', () => {
17+
setDiagramRenderingConfig({ enabled: false })
18+
19+
const html = markdownit.render('```plantuml\nAlice -> Bob: hello\n```')
20+
21+
expect(html).toContain('<pre><code class="language-plantuml">')
22+
expect(html).toContain('Alice -&gt; Bob: hello')
23+
expect(html).not.toContain('<img class="plantuml"')
24+
})
25+
})

0 commit comments

Comments
 (0)