metanorma-plugin-plantuml 1.0.1 → 1.0.3
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 +4 -4
- data/.github/workflows/rake.yml +1 -1
- data/Gemfile +1 -1
- data/README.adoc +569 -40
- data/lib/metanorma/plugin/plantuml/backend.rb +24 -11
- data/lib/metanorma/plugin/plantuml/block_processor.rb +11 -45
- data/lib/metanorma/plugin/plantuml/block_processor_base.rb +99 -0
- data/lib/metanorma/plugin/plantuml/image_block_macro_processor.rb +57 -0
- data/lib/metanorma/plugin/plantuml/version.rb +1 -1
- data/lib/metanorma/plugin/plantuml/wrapper.rb +95 -36
- data/lib/metanorma-plugin-plantuml.rb +2 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c7c85595e30e3155c473b4f44936209c3f95c8ab5cf29d55a2368bad6584c136
|
4
|
+
data.tar.gz: d7e58a9934d9995c9b36c3b86dc543a7c633d0c31fab5dd543707b7f347207c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '05039945787b1a1d65f8a37193db39346f2d42ac820dff54d70724fbb09bdbe2808a9ca20477a78e78b1357f65de337c289a075feabf27c9e3ae92264e671865'
|
7
|
+
data.tar.gz: 1cff1673fbed5b3e00a6e05d7642cccce29e6d5f5d2cd62500860fddf089a8fc7046a2c49df41b422804b03eb762bd0bb6ac21d67e8763e6d38583f29df4e0ed
|
data/.github/workflows/rake.yml
CHANGED
data/Gemfile
CHANGED
data/README.adoc
CHANGED
@@ -4,7 +4,7 @@ image:https://github.com/metanorma/metanorma-plugin-plantuml/workflows/rake/badg
|
|
4
4
|
|
5
5
|
== Purpose
|
6
6
|
|
7
|
-
This
|
7
|
+
This Metanorma plugin enables the usage of PlantUML diagrams in Metanorma
|
8
8
|
documents.
|
9
9
|
|
10
10
|
It provides a Ruby API that wraps a bundled PlantUML JAR file.
|
@@ -59,12 +59,134 @@ $ gem install metanorma-plugin-plantuml
|
|
59
59
|
|
60
60
|
== Usage
|
61
61
|
|
62
|
+
=== General
|
63
|
+
|
62
64
|
This plugin enables PlantUML diagram generation in Metanorma documents through
|
63
|
-
|
65
|
+
multiple methods, including:
|
66
|
+
|
67
|
+
* Block syntax using `[plantuml]` blocks
|
68
|
+
* Command syntax using `plantuml_image::{path}[{options}]`
|
69
|
+
|
70
|
+
Both syntaxes support various diagram types, output formats, and image
|
71
|
+
attributes, as well as PlantUML's `include!` and `includesub!` directives for
|
72
|
+
modular diagrams.
|
73
|
+
|
74
|
+
The effect of both syntaxes is the same: they generate and embed PlantUML diagrams
|
75
|
+
as images in the output document.
|
76
|
+
|
77
|
+
However, there are important differences in using them with external files, as
|
78
|
+
it is described in the various options.
|
79
|
+
|
80
|
+
The difference lies in how the PlantUML source is provided:
|
81
|
+
|
82
|
+
* In the block syntax, the PlantUML source is defined directly within the
|
83
|
+
document, and hence generated by PlantUML without a specific file context.
|
84
|
+
|
85
|
+
* In the command syntax, the PlantUML source is read from an external file,
|
86
|
+
which provides a file context for the PlantUML source.
|
87
|
+
|
88
|
+
Generally, the command syntax is more suitable for referencing external PlantUML
|
89
|
+
files.
|
90
|
+
|
91
|
+
|
92
|
+
=== Command syntax for external diagrams
|
93
|
+
|
94
|
+
PlantUML diagrams can be directly referenced from external files using the
|
95
|
+
`plantuml_image::{path}[{options}]` command.
|
96
|
+
|
97
|
+
Syntax:
|
98
|
+
|
99
|
+
[source,asciidoc]
|
100
|
+
----
|
101
|
+
plantuml_image::{plantuml-source.puml}[{options}]
|
102
|
+
----
|
103
|
+
|
104
|
+
Where,
|
105
|
+
|
106
|
+
`{plantuml-source.puml}`:: Path to the PlantUML source file, relative to the
|
107
|
+
path of the current file.
|
108
|
+
|
109
|
+
`{options}`:: (Optional) Comma-separated list of options to customize diagram
|
110
|
+
generation.
|
111
|
+
|
112
|
+
.Specifying an external PlantUML diagram using the `plantuml_image` command without options
|
113
|
+
[example]
|
114
|
+
====
|
115
|
+
[source,asciidoc]
|
116
|
+
----
|
117
|
+
plantuml_image::foo/bar.puml[]
|
118
|
+
----
|
119
|
+
|
120
|
+
The file `foo/bar.puml` looks like:
|
121
|
+
|
122
|
+
[source,plantuml]
|
123
|
+
----
|
124
|
+
@startuml
|
125
|
+
Alice -> Bob: Hello
|
126
|
+
Bob -> Alice: Hi there
|
127
|
+
@enduml
|
128
|
+
----
|
129
|
+
====
|
130
|
+
|
131
|
+
.Specifying an external PlantUML diagram using the `plantuml_image` command with options
|
132
|
+
[example]
|
133
|
+
====
|
134
|
+
[source,asciidoc]
|
135
|
+
----
|
136
|
+
plantuml_image::foo/bar.puml[format=svg]
|
137
|
+
----
|
138
|
+
|
139
|
+
The file `foo/bar.puml` is the same as above.
|
140
|
+
The `format=svg` option specifies the output format as SVG.
|
141
|
+
====
|
142
|
+
|
64
143
|
|
65
144
|
|
66
|
-
===
|
145
|
+
=== Block syntax for inline diagrams
|
146
|
+
|
147
|
+
PlantUML diagrams can be defined directly within your Metanorma document using
|
148
|
+
`[plantuml]` blocks.
|
149
|
+
|
150
|
+
Syntax:
|
67
151
|
|
152
|
+
[source,asciidoc]
|
153
|
+
----
|
154
|
+
[plantuml]
|
155
|
+
....
|
156
|
+
{PlantUML diagram source here}
|
157
|
+
....
|
158
|
+
----
|
159
|
+
|
160
|
+
Where,
|
161
|
+
|
162
|
+
`[plantuml]`:: Specifies that the block contains PlantUML source code.
|
163
|
+
|
164
|
+
`....`:: Delimiters that indicate the start and end of the PlantUML source code.
|
165
|
+
|
166
|
+
`{PlantUML diagram source here}`:: The actual PlantUML diagram definition using
|
167
|
+
PlantUML syntax.
|
168
|
+
|
169
|
+
|
170
|
+
The block can be used with or without options.
|
171
|
+
|
172
|
+
Syntax with options:
|
173
|
+
|
174
|
+
[source,asciidoc]
|
175
|
+
----
|
176
|
+
[plantuml,{options}]
|
177
|
+
....
|
178
|
+
{PlantUML diagram source here}
|
179
|
+
....
|
180
|
+
----
|
181
|
+
|
182
|
+
Where,
|
183
|
+
|
184
|
+
`{options}`:: Comma-separated list of options to customize diagram generation.
|
185
|
+
|
186
|
+
|
187
|
+
.Specifying a simple PlantUML diagram in the `[plantuml]` block
|
188
|
+
[example]
|
189
|
+
====
|
68
190
|
[source,asciidoc]
|
69
191
|
----
|
70
192
|
[plantuml]
|
@@ -75,10 +197,14 @@ Bob -> Alice: Hi there
|
|
75
197
|
@enduml
|
76
198
|
....
|
77
199
|
----
|
200
|
+
====
|
201
|
+
|
202
|
+
|
78
203
|
|
79
204
|
=== Supported diagram types
|
80
205
|
|
81
|
-
PlantUML supports various diagram types, each with
|
206
|
+
PlantUML, and therefore this plugin, supports various diagram types, each with
|
207
|
+
its own `@start` and `@end` directives:
|
82
208
|
|
83
209
|
`@startuml` / `@enduml`:: UML diagrams (sequence, class, activity, etc.)
|
84
210
|
`@startmindmap` / `@endmindmap`:: Mind map diagrams
|
@@ -129,12 +255,40 @@ Bob --> Alice: Authentication Response
|
|
129
255
|
----
|
130
256
|
====
|
131
257
|
|
258
|
+
|
132
259
|
=== Format options
|
133
260
|
|
134
261
|
==== Single format specification
|
135
262
|
|
136
|
-
|
263
|
+
The output format is specified using the `format` option, which can be applied
|
264
|
+
in both block and command syntaxes.
|
265
|
+
|
266
|
+
Block syntax:
|
267
|
+
|
268
|
+
[source,adoc]
|
269
|
+
----
|
270
|
+
[plantuml,format={format}]
|
271
|
+
----
|
272
|
+
|
273
|
+
Command syntax:
|
274
|
+
|
275
|
+
[source,adoc]
|
276
|
+
----
|
277
|
+
plantuml_image::{path}[format={format}]
|
278
|
+
----
|
279
|
+
|
280
|
+
Where `{format}` can be one of the following:
|
281
|
+
|
282
|
+
`png`:: (default) Portable Network Graphics
|
283
|
+
`svg`:: Scalable Vector Graphics
|
284
|
+
`pdf`:: Portable Document Format
|
285
|
+
`txt`:: ASCII art text output
|
286
|
+
`eps`:: Encapsulated PostScript
|
287
|
+
|
137
288
|
|
289
|
+
.Block syntax with format option
|
290
|
+
[example]
|
291
|
+
====
|
138
292
|
[source,asciidoc]
|
139
293
|
----
|
140
294
|
[plantuml,format=svg]
|
@@ -144,19 +298,47 @@ Alice -> Bob: Hello
|
|
144
298
|
@enduml
|
145
299
|
....
|
146
300
|
----
|
301
|
+
====
|
147
302
|
|
148
|
-
|
303
|
+
.Command syntax with format option
|
304
|
+
[example]
|
305
|
+
====
|
306
|
+
[source,asciidoc]
|
307
|
+
----
|
308
|
+
plantuml_image::path/to/my-plantuml.puml[format=svg]
|
309
|
+
----
|
310
|
+
====
|
149
311
|
|
150
|
-
`png`:: (default) Portable Network Graphics
|
151
|
-
`svg`:: Scalable Vector Graphics
|
152
|
-
`pdf`:: Portable Document Format
|
153
|
-
`txt`:: ASCII art text output
|
154
|
-
`eps`:: Encapsulated PostScript
|
155
312
|
|
156
313
|
==== Multiple format generation
|
157
314
|
|
158
|
-
|
315
|
+
It is possible to generate multiple output formats simultaneously by specifying
|
316
|
+
the `formats` option, which accepts a comma-separated list of formats.
|
317
|
+
|
318
|
+
While Metanorma does not currently support embedding multiple images for a single
|
319
|
+
diagram, generating multiple formats can be useful for documentation or other
|
320
|
+
purposes.
|
159
321
|
|
322
|
+
Block syntax:
|
323
|
+
|
324
|
+
[source,adoc]
|
325
|
+
----
|
326
|
+
[plantuml,formats="{format1},{format2},..."]
|
327
|
+
----
|
328
|
+
|
329
|
+
Command syntax:
|
330
|
+
|
331
|
+
[source,adoc]
|
332
|
+
----
|
333
|
+
plantuml_image::{path}[formats="{format1},{format2},..."]
|
334
|
+
----
|
335
|
+
|
336
|
+
Where `{format1}`, `{format2}`, etc. can be any of the supported formats listed
|
337
|
+
above.
|
338
|
+
|
339
|
+
.Block syntax with multiple formats
|
340
|
+
[example]
|
341
|
+
====
|
160
342
|
[source,asciidoc]
|
161
343
|
----
|
162
344
|
[plantuml,formats="png,svg,pdf"]
|
@@ -166,11 +348,26 @@ Alice -> Bob: Hello
|
|
166
348
|
@enduml
|
167
349
|
....
|
168
350
|
----
|
351
|
+
====
|
352
|
+
|
169
353
|
|
170
354
|
==== Document-level format configuration
|
171
355
|
|
172
|
-
|
356
|
+
The default format for all PlantUML diagrams in a document can be set using the
|
357
|
+
`plantuml-image-format` document attribute.
|
358
|
+
|
359
|
+
Syntax:
|
360
|
+
|
361
|
+
[source,asciidoc]
|
362
|
+
----
|
363
|
+
:plantuml-image-format: {format}
|
364
|
+
----
|
365
|
+
|
366
|
+
Where `{format}` can be any of the supported formats listed above.
|
173
367
|
|
368
|
+
.Document with document-level format configuration
|
369
|
+
[example]
|
370
|
+
====
|
174
371
|
[source,asciidoc]
|
175
372
|
----
|
176
373
|
:plantuml-image-format: svg
|
@@ -182,22 +379,246 @@ Alice -> Bob: Hello
|
|
182
379
|
@enduml
|
183
380
|
....
|
184
381
|
----
|
382
|
+
====
|
185
383
|
|
186
|
-
===
|
384
|
+
=== Using `!include` and `!includesub`
|
385
|
+
|
386
|
+
==== General
|
387
|
+
|
388
|
+
PlantUML supports modular diagram definitions using the `!include` and
|
389
|
+
`!includesub` directives to include external PlantUML files or specific parts of
|
390
|
+
them.
|
391
|
+
|
392
|
+
PlantUML is able to resolve relative paths in these directives based on the context
|
393
|
+
of the PlantUML source.
|
394
|
+
|
395
|
+
This is where the behavior differs between the block syntax and the command
|
396
|
+
syntax:
|
397
|
+
|
398
|
+
* In the block syntax, as the PlantUML source is defined inline within the
|
399
|
+
document, there is no associated file path for the PlantUML source. The
|
400
|
+
consequence is that PlantUML cannot resolve relative paths in `!include` or
|
401
|
+
`!includesub` directives, as there is no associated file path. In order to
|
402
|
+
resolve includes, you must specify the `includedirs` option to provide
|
403
|
+
directories to search for included files.
|
404
|
+
|
405
|
+
* In the command syntax, the PlantUML source is read from an external file. This
|
406
|
+
means that relative paths in `!include` or `!includesub` directives are resolved
|
407
|
+
relative to the location of the PlantUML source file. The `includedirs` option
|
408
|
+
is not needed for resolving includes, but can still be used to add additional
|
409
|
+
directories to search.
|
410
|
+
|
411
|
+
|
412
|
+
==== Setting `includedirs`
|
187
413
|
|
188
|
-
|
414
|
+
PlantUML allows you to specify include directories using the `includedirs`
|
415
|
+
option. This option can be set at both the document level and the block level,
|
416
|
+
through the option of the same name.
|
417
|
+
|
418
|
+
There are two ways to set `includedirs`:
|
419
|
+
|
420
|
+
* Document-level configuration using the `plantuml-includedirs` document attribute
|
421
|
+
|
422
|
+
* The `includedirs` option in the `[plantuml]` block or `plantuml_image` command
|
423
|
+
|
424
|
+
Note that when using the `plantuml_image` command, the directory that contains
|
425
|
+
the specified PlantUML file will be automatically added as one of the
|
426
|
+
`includedirs` directories. This means that any relative includes in the PlantUML
|
427
|
+
file will be resolved relative to the file's location, even if `includedirs` is
|
428
|
+
not explicitly set.
|
429
|
+
|
430
|
+
|
431
|
+
==== Document-level `plantuml-includedirs` attribute
|
432
|
+
|
433
|
+
It is possible to set default include directories (separated by semicolons) for
|
434
|
+
all PlantUML diagrams in a document using the `plantuml-includedirs` document
|
435
|
+
attribute.
|
436
|
+
|
437
|
+
This is useful when a document contains multiple PlantUML diagrams that share
|
438
|
+
common include files stored in specific directories, e.g. style definitions.
|
439
|
+
|
440
|
+
The directories specified in this attribute will be used as the default include
|
441
|
+
paths for all PlantUML diagrams in the document, including for both `[plantuml]`
|
442
|
+
blocks and `plantuml_image` commands.
|
443
|
+
|
444
|
+
NOTE: When using the `plantuml_image` command, the directory that contains the
|
445
|
+
specified PlantUML file will always be automatically added as one of the
|
446
|
+
`includedirs` directories.
|
447
|
+
|
448
|
+
Syntax:
|
189
449
|
|
190
450
|
[source,asciidoc]
|
191
451
|
----
|
192
|
-
|
452
|
+
:plantuml-includedirs: {path1};{path2};...
|
453
|
+
----
|
454
|
+
|
455
|
+
.Resolving PlantUML includes with document-level `includedirs` attribute
|
456
|
+
[example]
|
457
|
+
====
|
458
|
+
[source,asciidoc]
|
459
|
+
----
|
460
|
+
:plantuml-includedirs: path/to/plantuml/include-1;path/to/plantuml/include-2
|
461
|
+
|
462
|
+
[plantuml]
|
193
463
|
....
|
194
464
|
@startuml
|
195
|
-
|
465
|
+
!include sequences.puml!1
|
466
|
+
@enduml
|
467
|
+
....
|
468
|
+
|
469
|
+
[plantuml]
|
470
|
+
....
|
471
|
+
@startuml
|
472
|
+
!include components.puml!FRONTEND
|
473
|
+
!include components.puml!BACKEND
|
474
|
+
|
475
|
+
WebApp --> APIGateway
|
476
|
+
MobileApp --> APIGateway
|
477
|
+
APIGateway --> DB
|
478
|
+
@enduml
|
479
|
+
....
|
480
|
+
|
481
|
+
[plantuml]
|
482
|
+
....
|
483
|
+
@startuml
|
484
|
+
title this contains only B and D
|
485
|
+
!includesub subpart.puml!BASIC
|
486
|
+
@enduml
|
487
|
+
....
|
488
|
+
----
|
489
|
+
|
490
|
+
These `[plantuml]` blocks use `!include` and `!includesub` directives to include
|
491
|
+
external PlantUML files. PlantUML will search the include directories specified
|
492
|
+
by `includedirs` options to find `sequences.puml`, `components.puml` and
|
493
|
+
`subpart.puml`, at:
|
494
|
+
|
495
|
+
* `path/to/plantuml/include-1`
|
496
|
+
* `path/to/plantuml/include-2`
|
497
|
+
====
|
498
|
+
|
499
|
+
|
500
|
+
.Resolving PlantUML includes in `plantuml_image` command with document-level `includedirs` attribute
|
501
|
+
[example]
|
502
|
+
====
|
503
|
+
[source,asciidoc]
|
504
|
+
----
|
505
|
+
:plantuml-includedirs: path/to/plantuml/include-1;path/to/plantuml/include-2
|
506
|
+
|
507
|
+
plantuml_image::path/to/my-plantuml-1.puml[]
|
508
|
+
|
509
|
+
plantuml_image::path/to/my-plantuml-2.puml[]
|
510
|
+
----
|
511
|
+
|
512
|
+
With `path/to/my-plantuml-1.puml` as:
|
513
|
+
|
514
|
+
[source,plantuml]
|
515
|
+
----
|
516
|
+
@startuml
|
517
|
+
!include sequences.puml!1
|
518
|
+
@enduml
|
519
|
+
----
|
520
|
+
|
521
|
+
With `path/to/my-plantuml-2.puml` as:
|
522
|
+
|
523
|
+
[source,plantuml]
|
524
|
+
----
|
525
|
+
@startuml
|
526
|
+
!include components.puml!FRONTEND
|
527
|
+
!include components.puml!BACKEND
|
528
|
+
|
529
|
+
WebApp --> APIGateway
|
530
|
+
MobileApp --> APIGateway
|
531
|
+
APIGateway --> DB
|
196
532
|
@enduml
|
533
|
+
----
|
534
|
+
|
535
|
+
In using the `plantuml_image` command, the directory containing each PlantUML file
|
536
|
+
(`path/to` in this case) is automatically added to the `includedirs`.
|
537
|
+
|
538
|
+
Thus in rendering `path/to/my-plantuml-1.puml`, PlantUML will search for
|
539
|
+
`sequences.puml` in both `path/to` and the directories specified by the
|
540
|
+
`plantuml-includedirs` attribute.
|
541
|
+
|
542
|
+
Similarly, in rendering `path/to/my-plantuml-2.puml`, PlantUML will search for
|
543
|
+
`components.puml` in both `path/to` and the directories specified by the
|
544
|
+
`plantuml-includedirs` attribute.
|
545
|
+
====
|
546
|
+
|
547
|
+
|
548
|
+
==== Diagram-level `includedirs` option
|
549
|
+
|
550
|
+
The `includedirs` option can be used to specify include directories (separated
|
551
|
+
by semicolons) for both `[plantuml]` blocks and the `plantuml_image` command.
|
552
|
+
|
553
|
+
This option applies only to a single diagram in the document without affecting
|
554
|
+
others.
|
555
|
+
|
556
|
+
The diagram-level `includedirs` configuration can be used together with the
|
557
|
+
document-level configuration to provide more granular control over include
|
558
|
+
paths, where it is considered to have higher precedence than the document-level
|
559
|
+
configuration.
|
560
|
+
|
561
|
+
Syntax:
|
562
|
+
|
563
|
+
[source,asciidoc]
|
564
|
+
----
|
565
|
+
[plantuml,includedirs="{path1};{path2};..."]
|
566
|
+
----
|
567
|
+
|
568
|
+
Where,
|
569
|
+
|
570
|
+
`{path1}`, `{path2}`, etc.:: paths to directories containing PlantUML files to
|
571
|
+
be included, delimited by semicolons.
|
572
|
+
|
573
|
+
|
574
|
+
.Resolving PlantUML includes using diagram-level `includedirs` in `[plantuml]` blocks
|
575
|
+
[example]
|
576
|
+
====
|
577
|
+
[source,asciidoc]
|
578
|
+
----
|
579
|
+
[plantuml,includedirs="path/to/plantuml/include-1"]
|
580
|
+
....
|
581
|
+
@startuml
|
582
|
+
!include sequences.puml!1
|
583
|
+
@enduml
|
584
|
+
....
|
585
|
+
|
586
|
+
[plantuml,includedirs="path/to/plantuml/include-2"]
|
197
587
|
....
|
588
|
+
@startuml
|
589
|
+
!include components.puml!FRONTEND
|
590
|
+
!include components.puml!BACKEND
|
591
|
+
|
592
|
+
WebApp --> APIGateway
|
593
|
+
MobileApp --> APIGateway
|
594
|
+
APIGateway --> DB
|
595
|
+
@enduml
|
596
|
+
....
|
597
|
+
----
|
598
|
+
|
599
|
+
This plugin will search `sequences.puml` in `path/to/plantuml/include-1` and
|
600
|
+
`components.puml` in `path/to/plantuml/include-2`.
|
601
|
+
====
|
602
|
+
|
603
|
+
|
604
|
+
.Resolving PlantUML includes using diagram-level `includedirs` with `plantuml_image` command
|
605
|
+
[example]
|
606
|
+
====
|
607
|
+
[source,asciidoc]
|
608
|
+
----
|
609
|
+
plantuml_image::path/to/my-plantuml-1.puml[includedirs=path/to/plantuml/include-1]
|
610
|
+
|
611
|
+
plantuml_image::path/to/my-plantuml-2.puml[includedirs=path/to/plantuml/include-2]
|
198
612
|
----
|
613
|
+
====
|
614
|
+
|
615
|
+
|
616
|
+
=== Image attributes
|
617
|
+
|
618
|
+
The block and command syntaxes both support standard AsciiDoc image attributes
|
619
|
+
to customize the appearance and behavior of the generated PlantUML diagrams.
|
199
620
|
|
200
|
-
Supported attributes:
|
621
|
+
Supported attributes are as follows:
|
201
622
|
|
202
623
|
`id`:: Element identifier
|
203
624
|
`title`:: Image title/caption
|
@@ -208,34 +629,124 @@ Supported attributes:
|
|
208
629
|
`float`:: Float positioning
|
209
630
|
`role`:: CSS class/role
|
210
631
|
|
632
|
+
|
633
|
+
Block syntax:
|
634
|
+
|
635
|
+
[source,asciidoc]
|
636
|
+
----
|
637
|
+
[plantuml,{image-attributes}]
|
638
|
+
....
|
639
|
+
{PlantUML diagram source here}
|
640
|
+
....
|
641
|
+
----
|
642
|
+
|
643
|
+
Command syntax:
|
644
|
+
|
645
|
+
[source,asciidoc]
|
646
|
+
----
|
647
|
+
plantuml_image::{path}[{image-attributes}]
|
648
|
+
----
|
649
|
+
|
650
|
+
Where,
|
651
|
+
|
652
|
+
`{image-attributes}`:: Comma-separated list of AsciiDoc image attributes in
|
653
|
+
`key=value` format.
|
654
|
+
|
655
|
+
|
656
|
+
.Specifying image attributes in `[plantuml]` block
|
657
|
+
[example]
|
658
|
+
====
|
659
|
+
[source,asciidoc]
|
660
|
+
----
|
661
|
+
[plantuml,id=my-diagram,title="My Sequence Diagram",width=600,height=400]
|
662
|
+
....
|
663
|
+
@startuml
|
664
|
+
Alice -> Bob: Hello
|
665
|
+
@enduml
|
666
|
+
....
|
667
|
+
----
|
668
|
+
====
|
669
|
+
|
670
|
+
|
211
671
|
=== Filename specification
|
212
672
|
|
213
|
-
|
673
|
+
PlantUML supports specifying custom filenames for generated diagrams using the
|
674
|
+
`@start{type} [filename]` directive, where `{type}` is the diagram type (e.g.,
|
675
|
+
`uml`, `mindmap`, etc.) and `filename` is the desired name for the output
|
676
|
+
file.
|
677
|
+
|
678
|
+
This feature is not well documented in official PlantUML documentation, but is
|
679
|
+
described at:
|
680
|
+
|
681
|
+
* PlantUML Language Reference Guide, 4.7, where `@startuml PERT` is used
|
682
|
+
* https://forum.plantuml.net/19896/name-conventions-for-%40startuml-filename[PlantUML Forum: Name conventions for @startuml filename]
|
683
|
+
* https://forum.plantuml.net/5483/please-specify-filename-%40startuml-extension-automatically[PlantUML Forum: Please specify filename @startuml extension automatically]
|
684
|
+
|
685
|
+
When a custom filename is specified, PlantUML generates the output file using
|
686
|
+
the specified filename and the appropriate file extension based on the diagram
|
687
|
+
type.
|
688
|
+
|
689
|
+
This custom filename feature is supported in both block and command syntaxes.
|
690
|
+
|
691
|
+
Syntax:
|
692
|
+
|
693
|
+
[source,asciidoc]
|
694
|
+
----
|
695
|
+
[plantuml]
|
696
|
+
....
|
697
|
+
@startuml {custom-filename}
|
698
|
+
{PlantUML diagram source here}
|
699
|
+
@enduml
|
700
|
+
....
|
701
|
+
----
|
702
|
+
|
703
|
+
Where,
|
214
704
|
|
705
|
+
`{custom-filename}`:: Desired name for the generated diagram file, without
|
706
|
+
file extension.
|
707
|
+
|
708
|
+
.Specifying a custom filename in `[plantuml]` block
|
709
|
+
[example]
|
710
|
+
====
|
215
711
|
[source,asciidoc]
|
216
712
|
----
|
217
713
|
[plantuml]
|
218
714
|
....
|
219
|
-
@startuml
|
715
|
+
@startuml AliceToBob
|
220
716
|
Alice -> Bob: Hello
|
221
717
|
@enduml
|
222
718
|
....
|
223
719
|
----
|
224
720
|
|
225
|
-
This generates `
|
226
|
-
auto-generated filename.
|
721
|
+
This generates `AliceToBob.png` (which is the default format since none was
|
722
|
+
specified) instead of an auto-generated filename. This file is then embedded in
|
723
|
+
the output document using the specified filename.
|
724
|
+
====
|
725
|
+
|
227
726
|
|
228
727
|
|
229
|
-
===
|
728
|
+
=== Disable PlantUML processing
|
230
729
|
|
231
|
-
|
730
|
+
It is possible to disable PlantUML processing either document-wide or via an
|
731
|
+
environment variable.
|
232
732
|
|
233
|
-
|
733
|
+
When disabled, PlantUML blocks are rendered as code listings instead of
|
734
|
+
diagrams.
|
735
|
+
|
736
|
+
The `:plantuml-disabled:` document attribute can be used to disable PlantUML
|
737
|
+
processing for a specific document.
|
738
|
+
|
739
|
+
Syntax:
|
234
740
|
|
235
741
|
[source,asciidoc]
|
236
742
|
----
|
237
743
|
:plantuml-disabled:
|
744
|
+
----
|
238
745
|
|
746
|
+
[example]
|
747
|
+
====
|
748
|
+
[source,asciidoc]
|
749
|
+
----
|
239
750
|
[plantuml]
|
240
751
|
....
|
241
752
|
@startuml
|
@@ -244,22 +755,36 @@ Alice -> Bob: Hello
|
|
244
755
|
....
|
245
756
|
----
|
246
757
|
|
247
|
-
|
758
|
+
This renders the PlantUML block as a code listing instead of a diagram.
|
759
|
+
====
|
248
760
|
|
249
|
-
|
761
|
+
The same effect can be achieved using by setting the `PLANTUML_DISABLED`
|
762
|
+
environment variable to `true`.
|
250
763
|
|
251
|
-
|
764
|
+
Syntax:
|
252
765
|
|
766
|
+
[source,console]
|
767
|
+
----
|
768
|
+
$ PLANTUML_DISABLED=true metanorma ...
|
769
|
+
----
|
770
|
+
|
771
|
+
[example]
|
772
|
+
====
|
253
773
|
[source,console]
|
254
774
|
----
|
255
775
|
$ PLANTUML_DISABLED=true metanorma document.adoc
|
256
776
|
----
|
777
|
+
====
|
778
|
+
|
257
779
|
|
258
780
|
=== File organization
|
259
781
|
|
260
|
-
Generated PlantUML images are stored in
|
261
|
-
relative to
|
262
|
-
|
782
|
+
Generated PlantUML images are stored in a `_plantuml_images/` directory
|
783
|
+
relative to the document location (the document root, if it is made of multiple
|
784
|
+
files).
|
785
|
+
|
786
|
+
This directory is automatically created if it doesn't exist.
|
787
|
+
|
263
788
|
|
264
789
|
== Development
|
265
790
|
|
@@ -270,20 +795,24 @@ Metanorma integration and PlantUML execution:
|
|
270
795
|
|
271
796
|
[source]
|
272
797
|
----
|
273
|
-
Metanorma Document
|
274
|
-
|
275
|
-
BlockProcessor ← (processes [plantuml] blocks)
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
798
|
+
Metanorma Document
|
799
|
+
↓
|
800
|
+
BlockProcessor ← (processes `[plantuml]` blocks)
|
801
|
+
and ImageBlockMacroProcessor ← (processes `plantuml_image::` commands)
|
802
|
+
↓
|
803
|
+
Backend ← (Metanorma integration, paths, validation)
|
804
|
+
↓
|
805
|
+
Wrapper ← (Java/JAR execution, file I/O)
|
806
|
+
↓
|
807
|
+
PlantUML JAR ← (diagram generation)
|
282
808
|
----
|
283
809
|
|
284
810
|
`BlockProcessor`:: Processes `[plantuml]` blocks in Metanorma documents and
|
285
811
|
integrates with the Metanorma rendering pipeline.
|
286
812
|
|
813
|
+
`ImageBlockMacroProcessor`:: Processes `plantuml_image::{path}[{options}]` commands
|
814
|
+
in Metanorma documents and integrates with the Metanorma rendering pipeline.
|
815
|
+
|
287
816
|
`Backend`:: Handles Metanorma-specific logic including document paths, PlantUML
|
288
817
|
source validation, filename extraction, and attribute mapping.
|
289
818
|
|
@@ -14,19 +14,21 @@ module Metanorma
|
|
14
14
|
class Backend
|
15
15
|
class << self
|
16
16
|
def plantuml_installed?
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
return true if plantuml_available?
|
18
|
+
|
19
|
+
raise "PlantUML not installed"
|
20
20
|
end
|
21
21
|
|
22
22
|
def plantuml_available?
|
23
23
|
Wrapper.available?
|
24
24
|
end
|
25
25
|
|
26
|
-
def generate_file(
|
26
|
+
def generate_file( # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
27
|
+
parent, reader, format_override: nil, options: {}
|
28
|
+
)
|
27
29
|
ldir, imagesdir, fmt = generate_file_prep(parent)
|
28
30
|
fmt = format_override if format_override
|
29
|
-
plantuml_content = prep_source(reader)
|
31
|
+
plantuml_content = prep_source(parent, reader)
|
30
32
|
|
31
33
|
# Extract filename from PlantUML source if specified
|
32
34
|
filename = generate_unique_filename(fmt)
|
@@ -43,6 +45,7 @@ module Metanorma
|
|
43
45
|
plantuml_content,
|
44
46
|
format: fmt,
|
45
47
|
output_file: output_file,
|
48
|
+
includedirs: options[:includedirs],
|
46
49
|
)
|
47
50
|
|
48
51
|
unless result[:success]
|
@@ -52,10 +55,12 @@ module Metanorma
|
|
52
55
|
File.join(relative_path, filename)
|
53
56
|
end
|
54
57
|
|
55
|
-
def generate_multiple_files(
|
58
|
+
def generate_multiple_files(
|
59
|
+
parent, reader, formats, attrs, options: {}
|
60
|
+
)
|
56
61
|
# Generate files for each format
|
57
62
|
filenames = formats.map do |format|
|
58
|
-
generate_file(parent, reader, format)
|
63
|
+
generate_file(parent, reader, format, options: options)
|
59
64
|
end
|
60
65
|
|
61
66
|
# Return data for BlockProcessor to create image block
|
@@ -72,8 +77,9 @@ module Metanorma
|
|
72
77
|
def generate_file_prep(parent)
|
73
78
|
ldir = localdir(parent)
|
74
79
|
imagesdir = parent.document.attr("imagesdir")
|
75
|
-
fmt = parent
|
76
|
-
.
|
80
|
+
fmt = parent.document
|
81
|
+
.attr("plantuml-image-format")&.strip&.downcase ||
|
82
|
+
Wrapper::DEFAULT_FORMAT
|
77
83
|
[ldir, imagesdir, fmt]
|
78
84
|
end
|
79
85
|
|
@@ -100,8 +106,15 @@ module Metanorma
|
|
100
106
|
]
|
101
107
|
end
|
102
108
|
|
103
|
-
def prep_source(reader)
|
104
|
-
src = reader.source
|
109
|
+
def prep_source(parent, reader) # rubocop:disable Metrics/MethodLength
|
110
|
+
src = if reader.respond_to?(:source)
|
111
|
+
# get content from BlockProcessor
|
112
|
+
reader.source
|
113
|
+
else
|
114
|
+
# get content from ImageBlockMacroProcessor
|
115
|
+
docdir = parent.document.attributes["docdir"]
|
116
|
+
File.read(File.join(docdir, reader))
|
117
|
+
end
|
105
118
|
|
106
119
|
# Validate that we have matching start/end pairs
|
107
120
|
validate_plantuml_delimiters(src)
|
@@ -1,29 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "asciidoctor"
|
4
|
-
require "asciidoctor/extensions"
|
5
|
-
require_relative "backend"
|
6
|
-
|
7
3
|
module Metanorma
|
8
4
|
module Plugin
|
9
5
|
module Plantuml
|
10
|
-
# PlantUML block processor
|
6
|
+
# PlantUML block processor
|
11
7
|
class BlockProcessor < ::Asciidoctor::Extensions::BlockProcessor
|
8
|
+
include ::Metanorma::Plugin::Plantuml::BlockProcessorBase
|
12
9
|
use_dsl
|
13
10
|
named :plantuml
|
14
11
|
on_context :literal
|
15
12
|
parse_content_as :raw
|
16
13
|
|
17
|
-
def abort(parent, reader, attrs, msg)
|
18
|
-
warn msg
|
19
|
-
attrs["language"] = "plantuml"
|
20
|
-
create_listing_block(
|
21
|
-
parent,
|
22
|
-
reader.source,
|
23
|
-
attrs.reject { |k, _v| k.to_s.match?(/^\d+$/) },
|
24
|
-
)
|
25
|
-
end
|
26
|
-
|
27
14
|
def process(parent, reader, attrs) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
28
15
|
# Check for document-level disable flag
|
29
16
|
if parent.document.attr("plantuml-disabled")
|
@@ -37,45 +24,24 @@ module Metanorma
|
|
37
24
|
|
38
25
|
# Parse format specifications
|
39
26
|
formats = parse_formats(attrs, parent.document)
|
27
|
+
options = parse_options(parent, reader, attrs)
|
40
28
|
|
41
|
-
|
42
|
-
# Single format - original behavior
|
43
|
-
filename = Backend.generate_file(parent, reader, formats.first)
|
44
|
-
through_attrs = Backend.generate_attrs(attrs)
|
45
|
-
through_attrs["target"] = filename
|
46
|
-
else
|
47
|
-
# Multiple formats - generate multiple files
|
48
|
-
through_attrs = Backend
|
49
|
-
.generate_multiple_files(parent, reader, formats, attrs)
|
50
|
-
end
|
51
|
-
create_image_block parent, through_attrs
|
29
|
+
process_image_block(parent, reader, attrs, formats, options)
|
52
30
|
rescue StandardError => e
|
53
31
|
abort(parent, reader, attrs, e.message)
|
54
32
|
end
|
55
33
|
|
56
34
|
private
|
57
35
|
|
58
|
-
def
|
59
|
-
|
60
|
-
if attrs["formats"]
|
61
|
-
formats = attrs["formats"].split(",").map(&:strip).map(&:downcase)
|
62
|
-
return formats.select { |f| valid_format?(f) }
|
63
|
-
end
|
64
|
-
|
65
|
-
# Check for format attribute (single format override)
|
66
|
-
if attrs["format"]
|
67
|
-
format = attrs["format"].strip.downcase
|
68
|
-
return [format] if valid_format?(format)
|
69
|
-
end
|
36
|
+
def parse_options(parent, _reader, attrs)
|
37
|
+
options = {}
|
70
38
|
|
71
|
-
#
|
72
|
-
|
73
|
-
.
|
74
|
-
|
75
|
-
end
|
39
|
+
# Parse include directory
|
40
|
+
options[:includedirs] = add_attrs_to_includedirs(
|
41
|
+
parent.document, attrs, parse_doc_includedirs(parent.document)
|
42
|
+
)
|
76
43
|
|
77
|
-
|
78
|
-
%w[png svg pdf txt eps].include?(format)
|
44
|
+
options
|
79
45
|
end
|
80
46
|
end
|
81
47
|
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "asciidoctor"
|
4
|
+
require "asciidoctor/extensions"
|
5
|
+
require_relative "backend"
|
6
|
+
|
7
|
+
module Metanorma
|
8
|
+
module Plugin
|
9
|
+
module Plantuml
|
10
|
+
module BlockProcessorBase
|
11
|
+
def abort(parent, reader, attrs, msg)
|
12
|
+
warn msg
|
13
|
+
attrs["language"] = "plantuml"
|
14
|
+
create_listing_block(
|
15
|
+
parent,
|
16
|
+
reader.respond_to?(:source) ? reader.source : reader,
|
17
|
+
attrs.reject { |k, _v| k.to_s.match?(/^\d+$/) },
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def parse_doc_includedirs(document)
|
24
|
+
docdir = document.attributes["docdir"]
|
25
|
+
includedirs = document.attr("plantuml-includedirs")&.split(";") || []
|
26
|
+
|
27
|
+
includedirs.map! do |includedir|
|
28
|
+
if Pathname.new(includedir).relative?
|
29
|
+
Pathname.new(docdir).join(includedir).to_s
|
30
|
+
else
|
31
|
+
includedir
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
includedirs.compact.uniq
|
36
|
+
end
|
37
|
+
|
38
|
+
def parse_formats(attrs, document) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize, Metrics/MethodLength
|
39
|
+
# Check for formats attribute (multiple formats)
|
40
|
+
if attrs["formats"]
|
41
|
+
formats = attrs["formats"].split(",").map(&:strip).map(&:downcase)
|
42
|
+
return formats.select { |f| valid_format?(f) }
|
43
|
+
end
|
44
|
+
|
45
|
+
# Check for format attribute (single format override)
|
46
|
+
if attrs["format"]
|
47
|
+
format = attrs["format"].strip.downcase
|
48
|
+
return [format] if valid_format?(format)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Fall back to document attribute or default
|
52
|
+
default_format = document
|
53
|
+
.attr("plantuml-image-format")&.strip&.downcase ||
|
54
|
+
Wrapper::DEFAULT_FORMAT
|
55
|
+
|
56
|
+
[default_format]
|
57
|
+
end
|
58
|
+
|
59
|
+
def valid_format?(format)
|
60
|
+
Wrapper::SUPPORTED_FORMATS.include?(format)
|
61
|
+
end
|
62
|
+
|
63
|
+
def add_attrs_to_includedirs(document, attrs, includedirs)
|
64
|
+
docdir = document.attributes["docdir"]
|
65
|
+
attrs_includedirs = attrs["includedirs"]&.split(";") || []
|
66
|
+
|
67
|
+
attrs_includedirs.each do |attrs_includedir|
|
68
|
+
includedirs << if Pathname.new(attrs_includedir).relative?
|
69
|
+
Pathname.new(docdir).join(attrs_includedir).to_s
|
70
|
+
else
|
71
|
+
attrs_includedir
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
includedirs.compact.uniq
|
76
|
+
end
|
77
|
+
|
78
|
+
def process_image_block(parent, reader, attrs, formats, options) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
79
|
+
if formats.length == 1
|
80
|
+
# Single format - original behavior
|
81
|
+
filename = Backend.generate_file(
|
82
|
+
parent, reader, format_override: formats.first, options: options
|
83
|
+
)
|
84
|
+
through_attrs = Backend.generate_attrs(attrs)
|
85
|
+
through_attrs["target"] = filename
|
86
|
+
else
|
87
|
+
# Multiple formats - generate multiple files
|
88
|
+
through_attrs = Backend
|
89
|
+
.generate_multiple_files(
|
90
|
+
parent, reader, formats, attrs, options: options
|
91
|
+
)
|
92
|
+
end
|
93
|
+
|
94
|
+
create_image_block parent, through_attrs
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Metanorma
|
4
|
+
module Plugin
|
5
|
+
module Plantuml
|
6
|
+
# PlantUML block processor
|
7
|
+
class ImageBlockMacroProcessor < ::Asciidoctor::Extensions::BlockMacroProcessor
|
8
|
+
include ::Metanorma::Plugin::Plantuml::BlockProcessorBase
|
9
|
+
use_dsl
|
10
|
+
named :plantuml_image
|
11
|
+
|
12
|
+
def process(parent, reader, attrs) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
13
|
+
# Check for document-level disable flag
|
14
|
+
if parent.document.attr("plantuml-disabled")
|
15
|
+
return abort(parent, reader, attrs, "PlantUML processing disabled")
|
16
|
+
end
|
17
|
+
|
18
|
+
# Check PlantUML availability explicitly
|
19
|
+
unless Backend.plantuml_available?
|
20
|
+
return abort(parent, reader, attrs, "PlantUML not installed")
|
21
|
+
end
|
22
|
+
|
23
|
+
# Parse format specifications
|
24
|
+
formats = parse_formats(attrs, parent.document)
|
25
|
+
options = parse_options(parent, reader, attrs)
|
26
|
+
|
27
|
+
process_image_block(parent, reader, attrs, formats, options)
|
28
|
+
rescue StandardError => e
|
29
|
+
abort(parent, reader, attrs, e.message)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def add_image_path_to_includedirs(document, image_path, includedirs)
|
35
|
+
docdir = document.attributes["docdir"]
|
36
|
+
includedirs << File.dirname(File.join(docdir, image_path))
|
37
|
+
includedirs.compact.uniq
|
38
|
+
end
|
39
|
+
|
40
|
+
def parse_options(parent, reader, attrs)
|
41
|
+
options = {}
|
42
|
+
|
43
|
+
# Parse include directory
|
44
|
+
options[:includedirs] = parse_doc_includedirs(parent.document)
|
45
|
+
options[:includedirs] = add_attrs_to_includedirs(
|
46
|
+
parent.document, attrs, options[:includedirs]
|
47
|
+
)
|
48
|
+
options[:includedirs] = add_image_path_to_includedirs(
|
49
|
+
parent.document, reader, options[:includedirs]
|
50
|
+
)
|
51
|
+
|
52
|
+
options
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -32,7 +32,7 @@ module Metanorma
|
|
32
32
|
options
|
33
33
|
end
|
34
34
|
|
35
|
-
def generate( # rubocop:disable Metrics/MethodLength
|
35
|
+
def generate( # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
36
36
|
content,
|
37
37
|
format: DEFAULT_FORMAT,
|
38
38
|
output_file: nil,
|
@@ -42,6 +42,9 @@ module Metanorma
|
|
42
42
|
ensure_jar_available!
|
43
43
|
ensure_java_available!
|
44
44
|
|
45
|
+
include_files = get_include_files(content, options)
|
46
|
+
options[:include_files] = include_files unless include_files.empty?
|
47
|
+
|
45
48
|
result = if output_file
|
46
49
|
generate_to_file(content, format, output_file, options)
|
47
50
|
elsif base64
|
@@ -55,6 +58,24 @@ module Metanorma
|
|
55
58
|
{ success: false, error: e }
|
56
59
|
end
|
57
60
|
|
61
|
+
def get_include_files(content, _options) # rubocop:disable Metrics/MethodLength
|
62
|
+
include_files = []
|
63
|
+
content.each_line do |line|
|
64
|
+
case line
|
65
|
+
when /(!include|!includesub)\s(.+){1}/
|
66
|
+
found_file = $2.split("!").first
|
67
|
+
|
68
|
+
# skip web links and standard libraries
|
69
|
+
if found_file.start_with?("<", "http")
|
70
|
+
found_file = nil
|
71
|
+
end
|
72
|
+
|
73
|
+
include_files << found_file
|
74
|
+
end
|
75
|
+
end
|
76
|
+
include_files.compact.uniq
|
77
|
+
end
|
78
|
+
|
58
79
|
def generate_from_file(
|
59
80
|
input_file, format: DEFAULT_FORMAT,
|
60
81
|
output_file: nil, base64: false, **options
|
@@ -169,47 +190,85 @@ module Metanorma
|
|
169
190
|
end
|
170
191
|
|
171
192
|
def execute_plantuml(content, format, output_file, options) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize, Metrics/MethodLength
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
#
|
177
|
-
#
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
end
|
190
|
-
raise GenerationError.new(error_message, error)
|
193
|
+
# PlantUML generates output files based on filename specified in
|
194
|
+
# @start... line
|
195
|
+
# We need to use a temp directory and then move the file
|
196
|
+
Dir.mktmpdir do |temp_dir| # rubocop:disable Metrics/BlockLength
|
197
|
+
# create input file
|
198
|
+
File.open("#{temp_dir}/plantuml_input.puml", "w") do |f|
|
199
|
+
f.write(content)
|
200
|
+
end
|
201
|
+
|
202
|
+
# Handle include files
|
203
|
+
if options[:include_files] && !options[:include_files].empty?
|
204
|
+
if options[:includedirs].empty?
|
205
|
+
# raise error when include files are found but includedirs
|
206
|
+
# is nil
|
207
|
+
raise PlantumlError.new(
|
208
|
+
"includedirs is required when include files are specified",
|
209
|
+
)
|
191
210
|
end
|
192
211
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
212
|
+
options[:include_files].each do |include_file|
|
213
|
+
# find local include file in includedirs
|
214
|
+
found_include_file = nil
|
215
|
+
options[:includedirs].each do |includedir|
|
216
|
+
include_file_path = File.join(includedir, include_file)
|
217
|
+
if File.exist?(include_file_path)
|
218
|
+
found_include_file = include_file_path
|
219
|
+
break
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
if found_include_file
|
224
|
+
# create include file in temp directory
|
225
|
+
temp_include_file = File.join(temp_dir, include_file)
|
226
|
+
FileUtils.mkdir_p(File.dirname(temp_include_file))
|
227
|
+
|
228
|
+
File.open(temp_include_file, "w") do |f|
|
229
|
+
f.write(File.read(found_include_file))
|
230
|
+
end
|
208
231
|
end
|
209
232
|
end
|
233
|
+
end
|
234
|
+
|
235
|
+
cmd = build_command(
|
236
|
+
"#{temp_dir}/plantuml_input.puml",
|
237
|
+
format,
|
238
|
+
temp_dir,
|
239
|
+
options,
|
240
|
+
)
|
210
241
|
|
211
|
-
|
242
|
+
output, error, status = Open3.capture3(*cmd)
|
243
|
+
|
244
|
+
unless status.success?
|
245
|
+
error_message = if error.empty?
|
246
|
+
"Unknown PlantUML error"
|
247
|
+
else
|
248
|
+
error.strip
|
249
|
+
end
|
250
|
+
raise GenerationError.new(error_message, error)
|
212
251
|
end
|
252
|
+
|
253
|
+
# Find the generated file and move it to the desired location
|
254
|
+
if output_file
|
255
|
+
generated_file = find_generated_file(temp_dir, content,
|
256
|
+
format)
|
257
|
+
if generated_file && File.exist?(generated_file)
|
258
|
+
FileUtils.mv(generated_file, output_file)
|
259
|
+
else
|
260
|
+
# Debug: List what files were actually generated
|
261
|
+
generated_files = Dir.glob(File.join(temp_dir, "*"))
|
262
|
+
error_msg = "Generated file not found in temp directory. "
|
263
|
+
error_msg += "Expected: #{generated_file}. "
|
264
|
+
error_msg += "Found files: #{generated_files.map do |f|
|
265
|
+
File.basename(f)
|
266
|
+
end.join(', ')}"
|
267
|
+
raise GenerationError.new(error_msg)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
output
|
213
272
|
end
|
214
273
|
end
|
215
274
|
|
@@ -11,4 +11,6 @@ require "metanorma/plugin/plantuml/config"
|
|
11
11
|
require "metanorma/plugin/plantuml/wrapper"
|
12
12
|
require "metanorma/plugin/plantuml/utils"
|
13
13
|
require "metanorma/plugin/plantuml/backend"
|
14
|
+
require "metanorma/plugin/plantuml/block_processor_base"
|
14
15
|
require "metanorma/plugin/plantuml/block_processor"
|
16
|
+
require "metanorma/plugin/plantuml/image_block_macro_processor"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: metanorma-plugin-plantuml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-09-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: asciidoctor
|
@@ -58,8 +58,10 @@ files:
|
|
58
58
|
- lib/metanorma-plugin-plantuml.rb
|
59
59
|
- lib/metanorma/plugin/plantuml/backend.rb
|
60
60
|
- lib/metanorma/plugin/plantuml/block_processor.rb
|
61
|
+
- lib/metanorma/plugin/plantuml/block_processor_base.rb
|
61
62
|
- lib/metanorma/plugin/plantuml/config.rb
|
62
63
|
- lib/metanorma/plugin/plantuml/errors.rb
|
64
|
+
- lib/metanorma/plugin/plantuml/image_block_macro_processor.rb
|
63
65
|
- lib/metanorma/plugin/plantuml/utils.rb
|
64
66
|
- lib/metanorma/plugin/plantuml/version.rb
|
65
67
|
- lib/metanorma/plugin/plantuml/wrapper.rb
|