asciidoctor-kroki 0.10.2 → 1.0.0.beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7347a21da207a19001192e18b271334d6c3c2086ff30b09630766225139f7f9c
4
- data.tar.gz: 6a01add5e4b9b538ce7503d6fc13c96b7212d9e2a2c2329cb3c4e2bb7b1bcc9a
3
+ metadata.gz: f28746df322330460df07cafca210d9705c1bb5f1f6d97d6217ba0948d43f909
4
+ data.tar.gz: 1ee9e56a3c4982c2f2d8cb71fbba4f88d9e3b1e8b04d9b101ada7500d7b2148d
5
5
  SHA512:
6
- metadata.gz: 63c383fb103a3e68fbbdaa752b0f07b0b2796bfa16d2be4c522ecdb66f957e71a3d8f031dfafb0e3b58e454a9830d226a63076a8c19f129fce74616b1de4960e
7
- data.tar.gz: 854dba86ec4ad263b7c20948322e61bcc6d385eef137471555ec362c17161dbf92b7b90fcefbc2be0c70dec71638557200d8d790cb668e4bb80fb83c2718e1a7
6
+ metadata.gz: 4fbba1d5c16f1cb59a6cfe5f3a992e752592bcb123f7fa73c2a63fb62c0f93f773280fc86ed5afab1f819c0392d5fd94bfdfe70c11bb6a7d1d3dd099f629c171
7
+ data.tar.gz: 918ccffc3ef558cd389bf6d4f27724404e59f23c2f995ba11bf7ca25a482222d404b0310efd2c39f0d457e01a0428aa8512c9c71ec5b53848b7b429cfe99e2ec
data/Gemfile.lock CHANGED
@@ -1,13 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- asciidoctor-kroki (0.10.2)
4
+ asciidoctor-kroki (1.0.0.beta.1)
5
5
  asciidoctor (~> 2.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- asciidoctor (2.0.22)
10
+ asciidoctor (2.0.26)
11
11
  ast (2.4.3)
12
12
  diff-lcs (1.6.2)
13
13
  json (2.13.0)
data/README.md CHANGED
@@ -1,456 +1,34 @@
1
- # ✏️ Asciidoctor Kroki Extension
1
+ # Asciidoctor Kroki Extension
2
2
 
3
- [![Build JavaScript](https://github.com/ggrossetie/asciidoctor-kroki/actions/workflows/build-js.yml/badge.svg)](https://github.com/ggrossetie/asciidoctor-kroki/actions/workflows/build-js.yml)
4
- [![Build JavaScript](https://github.com/ggrossetie/asciidoctor-kroki/actions/workflows/build-ruby.yml/badge.svg)](https://github.com/ggrossetie/asciidoctor-kroki/actions/workflows/build-ruby.yml)
3
+ [![Build JavaScript](https://github.com/asciidoctor/asciidoctor-kroki/actions/workflows/build-js.yml/badge.svg)](https://github.com/asciidoctor/asciidoctor-kroki/actions/workflows/build-js.yml)
4
+ [![Build Ruby](https://github.com/asciidoctor/asciidoctor-kroki/actions/workflows/build-ruby.yml/badge.svg)](https://github.com/asciidoctor/asciidoctor-kroki/actions/workflows/build-ruby.yml)
5
5
  [![npm version](http://img.shields.io/npm/v/asciidoctor-kroki.svg)](https://www.npmjs.com/package/asciidoctor-kroki)
6
6
  [![Gem version](https://img.shields.io/gem/v/asciidoctor-kroki)](https://rubygems.org/gems/asciidoctor-kroki)
7
7
  [![Zulip Chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://kroki.zulipchat.com/)
8
8
 
9
- An extension for [Asciidoctor.js](https://github.com/asciidoctor/asciidoctor.js) to convert diagrams to images using [Kroki](https://kroki.io)!
9
+ An extension for [Asciidoctor.js](https://github.com/asciidoctor/asciidoctor.js) and [Asciidoctor](https://github.com/asciidoctor/asciidoctor) to convert diagrams to images using [Kroki](https://kroki.io).
10
10
 
11
- ## Install
11
+ ## Documentation
12
12
 
13
- ### Node.js
13
+ Full documentation is available at **https://docs.asciidoctor.org/kroki-extension/latest**.
14
14
 
15
- Install the dependencies:
16
-
17
- npm i asciidoctor asciidoctor-kroki
18
-
19
- Create a file named `kroki.js` with following content and run it:
20
-
21
- ```javascript
22
- const asciidoctor = require('@asciidoctor/core')()
23
- const kroki = require('asciidoctor-kroki')
24
-
25
- const input = 'plantuml::hello.puml[svg,role=sequence]'
26
-
27
- kroki.register(asciidoctor.Extensions) // 1️⃣
28
- console.log(asciidoctor.convert(input, { safe: 'safe' }))
29
-
30
- const registry = asciidoctor.Extensions.create()
31
- kroki.register(registry) // 2️⃣
32
- console.log(asciidoctor.convert(input, { safe: 'safe', extension_registry: registry }))
33
- ```
34
- 1️⃣ Register the extension in the global registry <br/>
35
- 2️⃣ Register the extension in a dedicated registry
36
-
37
- ### Browser
15
+ ## Quick start
38
16
 
39
17
  Install the dependencies:
40
18
 
41
19
  npm i asciidoctor asciidoctor-kroki
42
20
 
43
- Create a file named `kroki.html` with the following content and open it in your browser:
44
-
45
- ```html
46
- <html lang="en">
47
- <head>
48
- <title>Asciidoctor x Kroki</title>
49
- <meta charset="utf-8">
50
- <script src="node_modules/@asciidoctor/core/dist/browser/asciidoctor.js"></script>
51
- <script src="node_modules/asciidoctor-kroki/dist/browser/asciidoctor-kroki.js"></script>
52
- </head>
53
- <body>
54
- <div id="content"></div>
55
- <script>
56
- const input = `Let's take an example with a _GraphViz_ "Hello World":
57
-
58
- [graphviz]
59
- ....
60
- digraph G {
61
- Hello->World
62
- }
63
- ....`
64
-
65
- const asciidoctor = Asciidoctor()
66
-
67
- const registry = asciidoctor.Extensions.create()
68
- AsciidoctorKroki.register(registry) // 1️⃣
69
- const result = asciidoctor.convert(input, { safe: 'safe', extension_registry: registry })
70
- document.getElementById('content').innerHTML = result
71
- </script>
72
- </body>
73
- </html>
74
- ```
75
- 1️⃣ Register the extension in a dedicated registry
76
-
77
- > [!IMPORTANT]
78
- > If you want to reference a diagram file in a browser environment, you will need to define the base directory using the `base_dir` option.
79
- > In addition, you will also need to provide an implementation to read a binary file **synchronously** for a given path.
80
- > You can find an implementation based on `XMLHttpRequest` in the source code: https://github.com/ggrossetie/asciidoctor-kroki/blob/9585b969014a1894d0c9fb76df10e1e8c66ce2b2/test/browser/test.js#L2-L34.
81
- > Once `httpGet` is defined, here's how we should configure the extension:
21
+ Register and use the extension:
82
22
 
83
23
  ```js
84
- const registry = asciidoctor.Extensions.create()
85
- AsciidoctorKroki.register(registry, {
86
- vfs: {
87
- read: (path, encoding = 'utf8') => httpGet(path, encoding),
88
- exists: (_) => false,
89
- add: (_) => { /* no-op */ },
90
- parse: (path) => ({
91
- dir: path.substring(0, path.lastIndexOf('/') - 1),
92
- path
93
- })
94
- }
95
- })
96
- const input = 'plantuml::hello.puml[svg,role=sequence]'
97
- asciidoctor.convert(input, { safe: 'safe', base_dir: window.location.origin, extension_registry: registry })
98
- ```
99
-
100
- ### Ruby
24
+ import { convert, Extensions } from '@asciidoctor/core'
25
+ import asciidoctorKroki from 'asciidoctor-kroki'
101
26
 
102
- Install the dependency:
103
-
104
- gem install asciidoctor-kroki
105
-
106
- Require the library using the `--require` (or `-r`) option from the Asciidoctor CLI:
107
-
108
- asciidoctor -r asciidoctor-kroki doc.adoc
109
-
110
- ### Antora Integration
111
-
112
- If you are using [Antora](https://antora.org/), you can integrate Kroki in your documentation site.
113
-
114
- 1. Install the extension in your playbook project:
115
-
116
- npm i asciidoctor-kroki
117
-
118
- 2. Register the extension in your playbook file:
119
-
120
- ```yaml
121
- asciidoc:
122
- extensions:
123
- - asciidoctor-kroki
124
- ```
125
-
126
- https://docs.antora.org/antora/latest/playbook/asciidoc-extensions/
127
-
128
- 3. Enjoy!
129
-
130
- > [!TIP]
131
- > You can use the `kroki-fetch-diagram` option to download the images from Kroki at build time.
132
- > In other words, while viewing pages you won't rely on Kroki anymore.
133
-
134
- ```yaml
135
- asciidoc:
136
- attributes:
137
- kroki-fetch-diagram: true
27
+ asciidoctorKroki.register(Extensions)
28
+ console.log(await convert('[graphviz]\n....\ndigraph G { Hello->World }\n....'))
138
29
  ```
139
30
 
140
- ## Usage
141
-
142
- In your AsciiDoc document, you can either write your diagram inline or, alternatively, you can make a reference to the diagram file using macro form or with the `include` directive.
143
-
144
- Here's an example where we declare a GraphViz diagram directly in our AsciiDoc document using the block syntax:
145
-
146
- ```adoc
147
- [graphviz]
148
- ....
149
- digraph foo {
150
- node [style=rounded]
151
- node1 [shape=box]
152
- node2 [fillcolor=yellow, style="rounded,filled", shape=diamond]
153
- node3 [shape=record, label="{ a | b | c }"]
154
-
155
- node1 -> node2 -> node3
156
- }
157
- ....
158
- ```
159
-
160
- ![GraphViz diagram](https://kroki.io/graphviz/png/eNo9jjEOwjAMRfee4itzGKBzuEjVIaldWsnEVQBBVXp3AqQdLFlP_32bxkvy04BeFUsFRCVGc7vPwi7pIxJTW_Ax88FP7IK-NnZC048inYomN7OIPi3-tim6_QaYTOY_m0Z_1bi31ltr4k4TWYgPLM4s8Hgj5Omwmrbanzicy-Wy1NX6AUS2QVQ=)
161
-
162
- In the example below, we are using the `vegalite` macro to reference a file named *chart.vlite*:
163
-
164
- ```
165
- vegalite::chart.vlite[svg,role=chart,opts=interactive]
166
- ```
167
-
168
- ![Vega-Lite chart diagram](https://kroki.io/vegalite/png/eNrtVktz2yAQvvtXMEyOqt9pnNz6To-d6c3jA5ZWEg0CF7Ba26P_3gVb2JJSN8mhTWdyMIb92CffCnY9QuiFiXMoGL0hNLd2ZW4GgxIy1s-4zdfLPleD_QYvfSW4hUE57X8zStLI6SdgYs1XlqMAbdwqzbdKWibEhsRKxsyCxF9C4pxpa4jNmSUmVz9IwtMUNEhL7GYFhqgURWgMLN9ymRETMwGmf3DDrItxh3NclUysweB67teE7KjP4A2NCF3ibDyroib0toYuL9vQuxqaTtrQ-xq6HrWhDzU060Afg6-OwU81NLpuQ7fB4FUb-hwMjiuPLHD0m2i-L3Koxe6gSQum75xuzHUsgNYWKchYJVjfUE0v3TSWKEg5iMTpL4Oql7uzcmKpCi6ZaIJGaReJXAvRkLOf3LQcOFM8vnPilAkDURNLVMG4_A1ouRVw8HOCVGFeHRWo4Vt4bHLf10yiE2Z5Ca0MHSnvSaWhiA7_GFashNJ_P65WJbegFeJWr-E04oZpARnI5L7j258C_XI-6d7p_8H0C0v_PUtFhw2aycxtmM-GERm9xmE8xWEyxmE6HC6eJam7afgLy-8oWIZX26OZnSpd-E8qTWh0lvTihfT_C-ltrgHfHaJzpCGf-QR5fjVcnOuK8XDfEM-tF56c3bFZSq45PsDo0y-CryGIhzQFjj4YikpKlMfkOrmGWlIuE1hhEPhqPLbNgUYNMLioelXvF-H7eDo=)
169
-
170
-
171
- Finally, we can use the `include` directive to reference a diagram file:
172
-
173
- ```
174
- [plantuml,alice-bob,svg,role=sequence]
175
- ....
176
- include::alice-bob.puml[]
177
- ....
178
- ```
179
-
180
- ![PlantUML diagram](https://kroki.io/plantuml/png/eNpzKC5JLCopzc3hSszJTE5V0LVTSMpP4nJIzUsBCgIApPUKcg==)
181
-
182
- ### References and includes with Antora
183
-
184
- If you use this Asciidoctor Kroki Extension in combination with Antora, all references and includes MUST use [Antora Resource IDs](https://docs.antora.org/antora/latest/page/resource-id/). The `.puml`-files are best placed in the [_partials_-directory](https://docs.antora.org/antora/latest/page/partials/) of the modules.
185
-
186
- #### Block macros
187
-
188
- ```adoc
189
- vegalite::partial$chart.vlite[svg,role=chart,opts=interactive]
190
- ```
191
- #### Includes
192
-
193
- ```adoc
194
- [plantuml,alice-bob,svg,role=sequence]
195
- ....
196
- include::partial$alice-bob.puml[]
197
- ....
198
- ```
199
-
200
-
201
- ### Syntax
202
-
203
- You can declare positional and named attributes when using the block or the macro form.
204
-
205
- **Positional attributes**
206
-
207
- When using the block form:
208
-
209
- 1. The first positional attribute specifies the diagram type (see below for a complete list).
210
- 2. The second optional positional attribute assigns a file name (i.e. target) to the generated diagram. *Currently, the value of this attribute is ignored, and an auto-generated hash will be used as file name for caching purposes (see #48)*.
211
- 3. The third optional positional attribute specifies the image format.
212
-
213
- Example:
214
-
215
- ```
216
- [mermaid,abcd-flowchart,svg]
217
- ....
218
- graph TD;
219
- A-->B;
220
- A-->C;
221
- B-->D;
222
- C-->D;
223
- ....
224
- ```
225
-
226
- In the above example,
227
- the diagram type is `mermaid`,
228
- the file name (i.e., target) is `abcd-flowchart`,
229
- and the image format is `svg`.
230
-
231
- When using the macro form:
232
-
233
- 1. The first optional positional attribute specifies the image format.
234
-
235
- Example:
236
-
237
- ```
238
- vegalite::chart.vlite[svg]
239
- ```
240
-
241
- In the above example,
242
- the diagram type is `vegalite`,
243
- the target is `chart.vlite`,
244
- and the image format is `svg`.
245
-
246
- **Named attributes**
247
-
248
- You can also use both positional and named attributes. Here's an example:
249
-
250
- ```adoc
251
- .PlantUML example
252
- [plantuml#diagAliceBob,alice-and-bob,svg,role=sequence]
253
- ....
254
- alice -> bob
255
- ....
256
- ```
257
-
258
- As you can see, we specified an id using the syntax `#diagAliceBob` just after the diagram type, and we are also using a named attribute to assign a role using `role=sequence`.
259
-
260
- Here's another example using the macro form:
261
-
262
- ```
263
- vegalite::chart.vlite[svg,role=chart,opts=interactive]
264
- ```
265
-
266
- We are using a positional attribute to declare the image format and two named attributes to define the `role` and `options`.
267
-
268
- **Attributes**
269
-
270
- It's important to note that not all attributes are used in all converters.
271
- Here's a list of all attributes used in the built-in HTML 5 converter:
272
-
273
- - `target`
274
- - `width`
275
- - `height`
276
- - `format` (default `svg`)
277
- - `fallback`
278
- - `link`
279
- - `float`
280
- - `align`
281
- - `role`
282
- - `title` (used to define an alternative text description of the diagram)
283
-
284
- **Options**
285
-
286
- In addition, the following options are available when using the SVG format:
287
-
288
- - `inline`
289
- - `interactive`
290
- - `none` (used for cancelling defaults)
291
-
292
- Options can be defined using `options` attribute (or `opts` for short):
293
-
294
- ```adoc
295
- [blockdiag,opts=inline]
296
- ....
297
- blockdiag {
298
- Kroki -> generates -> "Block diagrams";
299
-
300
- Kroki [color = "greenyellow"];
301
- "Block diagrams" [color = "pink"];
302
- }
303
- ....
304
- ```
305
-
306
- ### Supported diagram types
307
-
308
- Kroki currently supports the following diagram libraries:
309
-
310
- * [ActDiag](https://github.com/blockdiag/actdiag): `actdiag`
311
- * [BlockDiag](https://github.com/blockdiag/blockdiag): `blockdiag`
312
- * [BPMN](https://github.com/bpmn-io/bpmn-js): `bpmn`
313
- * [Bytefield](https://github.com/Deep-Symmetry/bytefield-svg/): `bytefield`
314
- * [C4 (PlantUML)](https://github.com/RicardoNiepel/C4-PlantUML): `c4plantuml`
315
- * [D2](https://d2lang.com/tour/intro/): `d2`
316
- * [DBML](https://www.dbml.org/home/): `dbml`
317
- * [Ditaa](http://ditaa.sourceforge.net): `ditaa`
318
- * [ERD](https://github.com/BurntSushi/erd): `erd`
319
- * [Excalidraw](https://github.com/excalidraw/excalidraw): `excalidraw`
320
- * [GraphViz](https://www.graphviz.org/): `graphviz`
321
- * [Mermaid](https://github.com/knsv/mermaid): `mermaid`
322
- * [Nomnoml](https://github.com/skanaar/nomnoml): `nomnoml`
323
- * [NwDiag](https://github.com/blockdiag/nwdiag): `nwdiag`
324
- * [PacketDiag](https://github.com/blockdiag/nwdiag): `packetdiag`
325
- * [Pikchr](https://github.com/drhsqlite/pikchr): `pikchr`
326
- * [PlantUML](https://github.com/plantuml/plantuml): `plantuml`
327
- * [RackDiag](https://github.com/blockdiag/nwdiag): `rackdiag`
328
- * [SeqDiag](https://github.com/blockdiag/seqdiag): `seqdiag`
329
- * [SVGBob](https://github.com/ivanceras/svgbob): `svgbob`
330
- * [Symbolator](https://github.com/zebreus/symbolator): `symbolator`
331
- * [UMLet](https://github.com/umlet/umlet): `umlet`
332
- * [Vega](https://github.com/vega/vega): `vega`
333
- * [Vega-Lite](https://github.com/vega/vega-lite): `vegalite`
334
- * [WaveDrom](https://github.com/wavedrom/wavedrom): `wavedrom`
335
- * [Structurizr](https://github.com/structurizr/dsl): `structurizr`
336
- * [Diagrams.net](https://github.com/jgraph/drawio): `diagramsnet` _(only available via [Using Your Own Kroki](#using-your-own-kroki "Using Your Own Kroki"))_
337
-
338
- Each diagram library supports one or more output formats.
339
- Consult the [Kroki documentation](https://kroki.io/#support) to find out which formats are supported.
340
-
341
- ## Configuration
342
-
343
- | Attribute name | Description | Default value |
344
- |--------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|
345
- | `kroki-server-url` | The URL of the Kroki server (see "Using Your Own Kroki") | `https://kroki.io` |
346
- | `kroki-data-uri` | Embed images as data-uri elements in HTML elements so file is completely self-contained. | `false` |
347
- | `kroki-fetch-diagram` | Define if we should download (and save on the disk) the images from the Kroki server.<br/>This feature is not available when running in the browser. | `false` |
348
- | `kroki-http-method` | Define how we should get the image from the Kroki server. Possible values:<br/><ul><li>`get`: always use GET requests</li><li>`post`: always use POST requests</li><li>`adaptive`: use a POST request if the URI length is longer than `kroki-max-uri-length` (default 4000) characters, otherwise use a GET request</li></ul> | `adaptive` |
349
- | `kroki-plantuml-include` | A file that will be included at the top of all PlantUML diagrams as if `!include file` was used. This can be useful when you want to define a common skin for all your diagrams. The value can be a path or a URL. | |
350
- | `kroki-plantuml-include-paths` | Search path(s) that will be used to resolve `!include file` additionally to current diagram directory, similar to PlantUML property [plantuml.include.path](https://plantuml.com/de/preprocessing). Please use directory delimiter `;` (Windows) or `:` (Unix) for multiple paths, e.g.: `"c:/docu/styles;c:/docu/library"` or `"~/docu/styles:~/docu/library"` | |
351
- | `kroki-max-uri-length` | Define the max URI length before using a POST request when using `adaptive` HTTP method (`kroki-http-method`) | `4000` |
352
-
353
- > [!IMPORTANT]
354
- > `kroki-fetch-diagram` and `kroki-plantuml-include` are only available when safe mode is `server` or lower.
355
- > If you want to learn more about Asciidoctor safe modes: https://docs.asciidoctor.org/asciidoctor/latest/safe-modes/
356
-
357
- ### Default configuration
358
-
359
- By default, images are generated as SVG when possible.
360
- To alter this, set the `kroki-default-format` attribute:
361
-
362
- ```adoc
363
- :kroki-default-format: png
364
- ```
365
-
366
- You can unset this with `:kroki-default-format!:` or `:kroki-default-format: svg`.
367
-
368
- > [!NOTE]
369
- > An AsciiDoc attribute can be defined through the CLI or API, in the document’s header or in the document’s body.
370
- > In addition, if you are using Antora, you can define AsciiDoc attributes in your playbook and/or in your component descriptor.
371
-
372
- References:
373
-
374
- - https://asciidoctor.org/docs/user-manual/#setting-attributes-on-a-document
375
- - https://docs.antora.org/antora/2.3/page/attributes/#custom-attributes
376
-
377
- For instance, in an Antora playbook or component descriptor:
378
-
379
- ```yaml
380
- asciidoc:
381
- attributes:
382
- kroki-default-format: png@
383
- ```
384
-
385
- (the `@` allows the attribute value to be reset in documents)
386
-
387
- By default, Asciidoctor Kroki generates a link, to a Kroki server or a local file.
388
- To change the default for SVG diagrams, set the `kroki-default-options` attribute.
389
-
390
- ```adoc
391
- :kroki-default-options: inline
392
- ```
393
-
394
- You can unset this with `:kroki-default-options: none` or `:kroki-default-options!:` or specify `opts=none` in a block or macro.
395
-
396
- ## Preprocessing
397
-
398
- Some diagram libraries allow referencing external entities by URL or accessing resources from the filesystem.
399
- For example, PlantUML allows the `!import` directive to pull fragments from the filesystem or a remote URL or the standard library.
400
- Similarly, Vega-Lite can load data from a URL using the `url` property.
401
-
402
- By default, the Kroki server is running in `SECURE` mode which restrict access to files on the file system and on the network.
403
-
404
- For ease of use and convenience, Asciidoctor Kroki will try to resolve and load external resources before sending a request to the Kroki server.
405
- This feature is only available when Asciidoctor safe mode is `server` or lower.
406
-
407
- ## Troubleshooting
408
-
409
- ### 414 URI Too Long
410
-
411
- By default, the extension retrieves images from the Kroki server using a GET request.
412
- Be aware that the Kroki server will return a 414 (Request-URI Too Long) response if the requested URI exceeds the maximum length the server can process.
413
- The default maximum URI length is 4096 characters.
414
-
415
-
416
- To work around this limitation, you can:
417
- - **Increase the max URI length** if you are using a self-hosted instance of Kroki. For more information, see the Kroki documentation: https://docs.kroki.io/kroki/setup/configuration/#_max_uri_length.
418
- - **Use POST requests** by enabling `kroki-fetch-diagram` and setting `kroki-http-method` to `adaptive` or `post`.
419
-
420
- > [!NOTE]
421
- > If you switch to POST requests, the extension will download the images from the server.
422
- > In fact, it is no longer possible to retrieve images via GET requests, so the images need to be downloaded and displayed using a relative path.
423
-
424
- ## Using Your Own Kroki
425
-
426
- By default, this extension sends information and receives diagrams back from https://kroki.io.
427
-
428
- You may choose to use your own server due to:
429
-
430
- * Network restrictions — if Kroki is not available behind your corporate firewall
431
- * Network latency — you are far from the European public instance
432
- * Privacy — you don't want to send your diagrams to a remote server on the internet
433
-
434
- This is done using the `kroki-server-url` attribute.
435
- Typically, this is at the top of the document (under the title):
436
-
437
- ```adoc
438
- :kroki-server-url: http://my-server-url:port
439
- ```
440
-
441
- For instance, if you have followed [the instructions](https://docs.kroki.io/kroki/setup/install/#_using_docker) to set up a self-managed server using Docker you can use the following:
442
-
443
- ```adoc
444
- :kroki-server-url: http://localhost:8080
445
- ```
446
-
447
- Note that either the `http://` or `https://` prefix _is_ required (the default Docker image only uses `http`).
448
-
449
- You can also set this attribute using the Javascript API, for instance:
450
-
451
- ```js
452
- asciidoctor.convertFile('file.adoc', { safe: 'safe', attributes: { 'kroki-server-url': 'http://my-server-url:port' } })
453
- ```
31
+ For installation instructions for Node.js, Browser, Ruby, and Antora, as well as the full configuration reference, see the [documentation](https://docs.asciidoctor.org/kroki-extension/latest).
454
32
 
455
33
  ## Contributing
456
34
 
@@ -465,11 +43,12 @@ We recommend [`volta`](https://volta.sh/) to manage multiple active Node.js vers
465
43
 
466
44
  npm i
467
45
 
468
- 2. Generate a distribution:
46
+ 2. Build the project:
469
47
 
470
- npm run dist
48
+ npm run build
471
49
 
472
- When working on a new feature or when fixing a bug, make sure to run the linter and the test suite:
50
+ When working on a new feature or when fixing a bug, make sure to run the formatter, the linter and the test suite:
473
51
 
52
+ npm run format
474
53
  npm run lint
475
54
  npm run test
@@ -10,11 +10,11 @@ Gem::Specification.new do |s|
10
10
 
11
11
  s.authors = ['Guillaume Grossetie']
12
12
  s.email = ['ggrossetie@yuzutech.fr']
13
- s.homepage = 'https://github.com/ggrossetie/asciidoctor-kroki'
13
+ s.homepage = 'https://github.com/asciidoctor/asciidoctor-kroki'
14
14
  s.license = 'MIT'
15
15
  s.metadata = {
16
- 'bug_tracker_uri' => 'https://github.com/ggrossetie/asciidoctor-kroki/issues',
17
- 'source_code_uri' => 'https://github.com/ggrossetie/asciidoctor-kroki',
16
+ 'bug_tracker_uri' => 'https://github.com/asciidoctor/asciidoctor-kroki/issues',
17
+ 'source_code_uri' => 'https://github.com/asciidoctor/asciidoctor-kroki',
18
18
  'rubygems_mfa_required' => 'true'
19
19
  }
20
20
  # NOTE: the logic to build the list of files is designed to produce a usable package even when the git command is not available
@@ -124,6 +124,7 @@ module AsciidoctorExtensions
124
124
  ditaa
125
125
  erd
126
126
  excalidraw
127
+ goat
127
128
  graphviz
128
129
  mermaid
129
130
  nomnoml
@@ -155,7 +156,7 @@ module AsciidoctorExtensions
155
156
  BUILTIN_ATTRIBUTES = %w[target width height format fallback link float align role caption title cloaked-context subs].freeze
156
157
 
157
158
  class << self
158
- # rubocop:disable Metrics/AbcSize
159
+ # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
159
160
  def process(processor, parent, attrs, diagram_type, diagram_text, logger)
160
161
  doc = parent.document
161
162
  diagram_text = prepend_plantuml_config(diagram_text, diagram_type, doc, logger)
@@ -165,6 +166,10 @@ module AsciidoctorExtensions
165
166
  diagram_text = parent.apply_subs(diagram_text, parent.resolve_subs(subs))
166
167
  end
167
168
  attrs.delete('opts')
169
+ # Apply the option defined on the block/macro or, as a fallback, the document-wide kroki-default-options.
170
+ if (option = get_option(attrs, doc)) && option != 'none'
171
+ attrs["#{option}-option"] = ''
172
+ end
168
173
  format = get_format(doc, attrs, diagram_type)
169
174
  attrs['role'] = get_role(format, attrs['role'])
170
175
  attrs['format'] = format
@@ -185,14 +190,14 @@ module AsciidoctorExtensions
185
190
  block = processor.create_block(parent, 'literal', text_content, attrs)
186
191
  else
187
192
  attrs['alt'] = alt
188
- attrs['target'] = create_image_src(doc, kroki_diagram, kroki_client)
193
+ attrs['target'] = create_image_src(doc, kroki_diagram, kroki_client, logger)
189
194
  block = processor.create_image_block(parent, attrs)
190
195
  end
191
196
  block.title = title if title
192
197
  block.assign_caption(caption, 'figure')
193
198
  block
194
199
  end
195
- # rubocop:enable Metrics/AbcSize
200
+ # rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity
196
201
 
197
202
  private
198
203
 
@@ -234,26 +239,48 @@ module AsciidoctorExtensions
234
239
  end
235
240
  end
236
241
 
242
+ # Get the option defined on the block or macro.
243
+ #
244
+ # First, check if an option is defined as an attribute (e.g. opts=inline).
245
+ # If there is no match, fall back to the document-wide kroki-default-options attribute.
246
+ #
247
+ # @param attrs [Hash] the block or macro attributes
248
+ # @param doc [Asciidoctor::Document] the Asciidoctor document
249
+ # @return [String, nil] the option name (inline, interactive or none) or nil
250
+ def get_option(attrs, doc)
251
+ available_options = %w[inline interactive none]
252
+ available_options.find { |option| attrs["#{option}-option"] == '' } ||
253
+ available_options.find { |option| doc.attr('kroki-default-options') == option }
254
+ end
255
+
237
256
  def get_format(doc, attrs, diagram_type)
238
257
  format = attrs['format'] || doc.attr('kroki-default-format') || 'svg'
239
258
  if format == 'png'
240
259
  # redirect PNG format to SVG if the diagram library only supports SVG as output format.
241
260
  # this is useful when the default format has been set to PNG
242
- # Currently, nomnoml, svgbob, wavedrom only support SVG as output format.
243
- svg_only_diagram_types = %i[nomnoml svgbob wavedrom]
261
+ # Currently, goat, nomnoml, svgbob, wavedrom only support SVG as output format.
262
+ svg_only_diagram_types = %i[goat nomnoml svgbob wavedrom]
244
263
  format = 'svg' if svg_only_diagram_types.include?(diagram_type)
245
264
  end
246
265
  format
247
266
  end
248
267
 
249
- def create_image_src(doc, kroki_diagram, kroki_client)
268
+ def create_image_src(doc, kroki_diagram, kroki_client, logger)
250
269
  if doc.attr('kroki-fetch-diagram') && doc.safe < ::Asciidoctor::SafeMode::SECURE
251
- kroki_diagram.save(output_dir_path(doc), kroki_client)
270
+ kroki_diagram.save(output_dir_path(doc), kroki_client, generated_files(doc), logger)
252
271
  else
253
272
  kroki_diagram.get_diagram_uri(server_url(doc))
254
273
  end
255
274
  end
256
275
 
276
+ # Returns the per-document registry of generated file names, mapping each name
277
+ # to the diagram URI it was generated from. Used to detect name clashes within
278
+ # a single conversion.
279
+ def generated_files(doc)
280
+ doc.instance_variable_get(:@kroki_generated_files) ||
281
+ doc.instance_variable_set(:@kroki_generated_files, {})
282
+ end
283
+
257
284
  def server_url(doc)
258
285
  doc.attr('kroki-server-url', 'https://kroki.io')
259
286
  end
@@ -306,28 +333,53 @@ module AsciidoctorExtensions
306
333
  ([Zlib::Deflate.deflate(@text, 9)].pack 'm0').tr '+/', '-_'
307
334
  end
308
335
 
309
- def save(output_dir_path, kroki_client)
336
+ def save(output_dir_path, kroki_client, generated_files = nil, logger = nil)
310
337
  diagram_url = get_diagram_uri(kroki_client.server_url)
311
- diagram_name = "#{@target || 'diag'}-#{Digest::SHA256.hexdigest diagram_url}.#{@format}"
338
+ # An explicit name is used verbatim so links stay stable across content changes;
339
+ # otherwise the name is content-addressed so anonymous diagrams don't collide (see #451).
340
+ named = @target.is_a?(::String) && !@target.empty?
341
+ diagram_name = named ? "#{@target}.#{@format}" : "diag-#{Digest::SHA256.hexdigest diagram_url}.#{@format}"
312
342
  file_path = File.join(output_dir_path, diagram_name)
313
- encoding = case @format
314
- when 'txt', 'atxt', 'utxt', 'svg'
315
- 'utf8'
316
- else
317
- 'binary'
318
- end
319
- # file is either (already) on the file system or we should read it from Kroki
320
- unless File.exist?(file_path)
321
- contents = kroki_client.get_image(self, encoding)
322
- FileUtils.mkdir_p(output_dir_path)
323
- File.write(file_path, contents, mode: 'wb')
343
+ if named
344
+ # A stable file may exist from a previous build with stale content, so always
345
+ # re-fetch and overwrite. Warn when the same name is reused for a different diagram.
346
+ warn_on_name_clash(generated_files, diagram_name, diagram_url, logger)
347
+ generated_files[diagram_name] = diagram_url if generated_files
348
+ fetch_and_write(output_dir_path, file_path, kroki_client)
349
+ elsif !File.exist?(file_path)
350
+ # Content-addressed name: an existing file necessarily has identical content.
351
+ fetch_and_write(output_dir_path, file_path, kroki_client)
324
352
  end
325
-
326
353
  diagram_name
327
354
  end
328
355
 
329
356
  private
330
357
 
358
+ def fetch_and_write(output_dir_path, file_path, kroki_client)
359
+ contents = kroki_client.get_image(self, image_encoding)
360
+ FileUtils.mkdir_p(output_dir_path)
361
+ File.write(file_path, contents, mode: 'wb')
362
+ end
363
+
364
+ def warn_on_name_clash(generated_files, diagram_name, diagram_url, logger)
365
+ return unless generated_files && logger
366
+
367
+ previous_url = generated_files[diagram_name]
368
+ return if previous_url.nil? || previous_url == diagram_url
369
+
370
+ logger.warn "kroki: the diagram file name '#{diagram_name}' is generated by more than one diagram with different content; " \
371
+ 'the file will be overwritten. Use unique names to keep stable links.'
372
+ end
373
+
374
+ def image_encoding
375
+ case @format
376
+ when 'txt', 'atxt', 'utxt', 'svg'
377
+ 'utf8'
378
+ else
379
+ 'binary'
380
+ end
381
+ end
382
+
331
383
  def _url_encode(text)
332
384
  CGI.escape(text).gsub('+', '%20')
333
385
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Asciidoctor
4
4
  module AsciidoctorKroki
5
- VERSION = '0.10.2'
5
+ VERSION = '1.0.0.beta.1'
6
6
  end
7
7
  end
@@ -70,7 +70,7 @@ describe AsciidoctorExtensions::KrokiDiagram do
70
70
  output_dir_path = "#{__dir__}/../.asciidoctor/kroki"
71
71
  diagram_name = kroki_diagram.save(output_dir_path, kroki_client)
72
72
  diagram_path = File.join(output_dir_path, diagram_name)
73
- expect(diagram_name).to start_with('hello-world-'), "diagram name should use the target as a prefix, got: #{diagram_name}"
73
+ expect(diagram_name).to eq('hello-world.txt'), "diagram name should be the target name without a checksum, got: #{diagram_name}"
74
74
  expect(File.exist?(diagram_path)).to be_truthy, "diagram should be saved at: #{diagram_path}"
75
75
  content = <<-TXT.chomp
76
76
  ,-----. ,---.
@@ -99,4 +99,27 @@ describe AsciidoctorExtensions::KrokiDiagram do
99
99
  kroki_diagram.save(output_dir_path, kroki_client)
100
100
  expect(File.size(diagram_path)).to be_eql(diagram_contents.length), 'diagram should be fully saved on disk'
101
101
  end
102
+ it 'should warn when the same target name is reused for diagrams with different content' do
103
+ generated_files = {}
104
+ logger = double('logger', warn: nil)
105
+ kroki_http_client = AsciidoctorExtensions::KrokiHttpClient
106
+ kroki_client = AsciidoctorExtensions::KrokiClient.new(server_url: 'https://kroki.io', http_method: 'get', http_client: kroki_http_client)
107
+ output_dir_path = "#{__dir__}/../.asciidoctor/kroki"
108
+ allow(kroki_http_client).to receive(:get).and_return('content')
109
+ AsciidoctorExtensions::KrokiDiagram.new('plantuml', 'svg', 'alice -> bob', 'shared').save(output_dir_path, kroki_client, generated_files, logger)
110
+ AsciidoctorExtensions::KrokiDiagram.new('plantuml', 'svg', 'carol -> dave', 'shared').save(output_dir_path, kroki_client, generated_files, logger)
111
+ expect(logger).to have_received(:warn).once
112
+ end
113
+ it 'should not warn when the same target name maps to the same diagram' do
114
+ generated_files = {}
115
+ logger = double('logger', warn: nil)
116
+ kroki_http_client = AsciidoctorExtensions::KrokiHttpClient
117
+ kroki_client = AsciidoctorExtensions::KrokiClient.new(server_url: 'https://kroki.io', http_method: 'get', http_client: kroki_http_client)
118
+ output_dir_path = "#{__dir__}/../.asciidoctor/kroki"
119
+ allow(kroki_http_client).to receive(:get).and_return('content')
120
+ 2.times do
121
+ AsciidoctorExtensions::KrokiDiagram.new('plantuml', 'svg', 'alice -> bob', 'shared').save(output_dir_path, kroki_client, generated_files, logger)
122
+ end
123
+ expect(logger).not_to have_received(:warn)
124
+ end
102
125
  end
@@ -30,4 +30,24 @@ describe '::AsciidoctorExtensions::KrokiProcessor' do
30
30
  output_dir_path = AsciidoctorExtensions::KrokiProcessor.send(:output_dir_path, doc)
31
31
  expect(output_dir_path).to eq "#{Dir.pwd}/img"
32
32
  end
33
+ it 'should return the option defined on the block' do
34
+ doc = Asciidoctor.load('hello')
35
+ option = AsciidoctorExtensions::KrokiProcessor.send(:get_option, { 'inline-option' => '' }, doc)
36
+ expect(option).to eq 'inline'
37
+ end
38
+ it 'should fall back to the kroki-default-options document attribute' do
39
+ doc = Asciidoctor.load('hello', attributes: { 'kroki-default-options' => 'inline' })
40
+ option = AsciidoctorExtensions::KrokiProcessor.send(:get_option, {}, doc)
41
+ expect(option).to eq 'inline'
42
+ end
43
+ it 'should let the block option override the kroki-default-options document attribute' do
44
+ doc = Asciidoctor.load('hello', attributes: { 'kroki-default-options' => 'inline' })
45
+ option = AsciidoctorExtensions::KrokiProcessor.send(:get_option, { 'none-option' => '' }, doc)
46
+ expect(option).to eq 'none'
47
+ end
48
+ it 'should return nil when no option is defined' do
49
+ doc = Asciidoctor.load('hello')
50
+ option = AsciidoctorExtensions::KrokiProcessor.send(:get_option, {}, doc)
51
+ expect(option).to be_nil
52
+ end
33
53
  end
data/spec/rspec_helper.rb CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  RSpec.configure do |config|
4
4
  config.before(:suite) do
5
- FileUtils.rm(Dir.glob("#{__dir__}/../.asciidoctor/kroki/diag-*"))
5
+ FileUtils.rm(Dir.glob("#{__dir__}/../.asciidoctor/kroki/{diag-*,hello-world.*,shared.*}"))
6
6
  end
7
7
  config.after(:suite) do
8
- FileUtils.rm(Dir.glob("#{__dir__}/../.asciidoctor/kroki/diag-*")) unless ENV['DEBUG']
8
+ FileUtils.rm(Dir.glob("#{__dir__}/../.asciidoctor/kroki/{diag-*,hello-world.*,shared.*}")) unless ENV['DEBUG']
9
9
  end
10
10
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciidoctor-kroki
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.2
4
+ version: 1.0.0.beta.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Guillaume Grossetie
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2026-03-04 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: asciidoctor
@@ -100,14 +99,13 @@ files:
100
99
  - tasks/bundler.rake
101
100
  - tasks/lint.rake
102
101
  - tasks/rspec.rake
103
- homepage: https://github.com/ggrossetie/asciidoctor-kroki
102
+ homepage: https://github.com/asciidoctor/asciidoctor-kroki
104
103
  licenses:
105
104
  - MIT
106
105
  metadata:
107
- bug_tracker_uri: https://github.com/ggrossetie/asciidoctor-kroki/issues
108
- source_code_uri: https://github.com/ggrossetie/asciidoctor-kroki
106
+ bug_tracker_uri: https://github.com/asciidoctor/asciidoctor-kroki/issues
107
+ source_code_uri: https://github.com/asciidoctor/asciidoctor-kroki
109
108
  rubygems_mfa_required: 'true'
110
- post_install_message:
111
109
  rdoc_options: []
112
110
  require_paths:
113
111
  - lib
@@ -122,8 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
120
  - !ruby/object:Gem::Version
123
121
  version: '0'
124
122
  requirements: []
125
- rubygems_version: 3.1.6
126
- signing_key:
123
+ rubygems_version: 3.6.9
127
124
  specification_version: 4
128
125
  summary: Asciidoctor extension to convert diagrams to images using Kroki
129
126
  test_files: []