metanorma-plugin-lutaml 0.7.30 → 0.7.32

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +10 -8
  3. data/README.adoc +16 -1030
  4. data/docs/usages/enterprise_architect.adoc +583 -0
  5. data/docs/usages/express.adoc +299 -0
  6. data/docs/usages/json_yaml.adoc +1050 -0
  7. data/docs/usages/lutaml-gml.adoc +73 -0
  8. data/docs/usages/lutaml-uml.adoc +73 -0
  9. data/lib/metanorma/plugin/lutaml/asciidoctor/preprocessor.rb +1 -1
  10. data/lib/metanorma/plugin/lutaml/base_structured_text_preprocessor.rb +188 -0
  11. data/lib/metanorma/plugin/lutaml/content.rb +103 -0
  12. data/lib/metanorma/plugin/lutaml/data2_text_preprocessor.rb +45 -0
  13. data/lib/metanorma/plugin/lutaml/express_remarks_decorator.rb +19 -6
  14. data/lib/metanorma/plugin/lutaml/file_not_found_error.rb +10 -0
  15. data/lib/metanorma/plugin/lutaml/json2_text_preprocessor.rb +43 -0
  16. data/lib/metanorma/plugin/lutaml/liquid/custom_blocks/key_iterator.rb +31 -0
  17. data/lib/metanorma/plugin/lutaml/liquid/custom_filters/loadfile.rb +18 -0
  18. data/lib/metanorma/plugin/lutaml/liquid/custom_filters/replace_regex.rb +14 -0
  19. data/lib/metanorma/plugin/lutaml/liquid/custom_filters/values.rb +13 -0
  20. data/lib/metanorma/plugin/lutaml/liquid/multiply_local_file_system.rb +29 -22
  21. data/lib/metanorma/plugin/lutaml/liquid_drops/gml_dictionary_drop.rb +1 -1
  22. data/lib/metanorma/plugin/lutaml/lutaml_diagram_base.rb +1 -1
  23. data/lib/metanorma/plugin/lutaml/lutaml_diagram_block_macro.rb +2 -1
  24. data/lib/metanorma/plugin/lutaml/lutaml_ea_diagram_block_macro.rb +2 -1
  25. data/lib/metanorma/plugin/lutaml/lutaml_ea_xmi_base.rb +48 -36
  26. data/lib/metanorma/plugin/lutaml/lutaml_figure_inline_macro.rb +2 -1
  27. data/lib/metanorma/plugin/lutaml/lutaml_gml_dictionary_block_macro.rb +3 -1
  28. data/lib/metanorma/plugin/lutaml/lutaml_klass_table_block_macro.rb +2 -1
  29. data/lib/metanorma/plugin/lutaml/lutaml_preprocessor.rb +15 -2
  30. data/lib/metanorma/plugin/lutaml/lutaml_table_inline_macro.rb +2 -1
  31. data/lib/metanorma/plugin/lutaml/parse_error.rb +10 -0
  32. data/lib/metanorma/plugin/lutaml/source_extractor.rb +97 -0
  33. data/lib/metanorma/plugin/lutaml/utils.rb +59 -26
  34. data/lib/metanorma/plugin/lutaml/version.rb +1 -1
  35. data/lib/metanorma/plugin/lutaml/yaml2_text_preprocessor.rb +41 -0
  36. data/lib/metanorma-plugin-lutaml.rb +3 -0
  37. data/metanorma-plugin-lutaml.gemspec +7 -1
  38. metadata +37 -6
  39. data/lib/metanorma/plugin/lutaml/liquid_templates/test.rb +0 -1
  40. /data/lib/metanorma/plugin/lutaml/liquid/{custom_filters.rb → custom_filters/html2adoc.rb} +0 -0
@@ -0,0 +1,1050 @@
1
+
2
+ == Usage with JSON or YAML files
3
+
4
+ === General
5
+
6
+ The plugin provides the following block commands:
7
+
8
+ `data2text`:: Loads one or more JSON/YAML files and makes them available for
9
+ use in a Metanorma template context.
10
+
11
+ `yaml2text`:: Identical to `data2text`, but only loads YAML files.
12
+
13
+ `json2text`:: Identical to `data2text`, but only loads JSON files.
14
+
15
+
16
+ === Liquid syntax
17
+
18
+ These block commands make specified data available in the context of a template
19
+ block that supports Liquid. Liquid is a template language that allows you to
20
+ create dynamic content through templating.
21
+
22
+ Liquid supports many templating features, including:
23
+
24
+ * variables, variable assignment
25
+ * flow control (if/case)
26
+ * filters
27
+ * loops
28
+
29
+ NOTE: See the introduction to the
30
+ https://shopify.github.io/liquid/basics/introduction/[Liquid language] for
31
+ reference.
32
+
33
+ In the following sections, we will use `data2text` as an example, but the
34
+ same applies to `yaml2text` and `json2text`.
35
+
36
+
37
+ [[defining_syntax]]
38
+ === Defining a block
39
+
40
+ A `data2text` block is created by specifying the block name `[data2text]`
41
+ followed by a comma and the file paths of the JSON/YAML file and the assigned
42
+ context name.
43
+
44
+ Syntax:
45
+
46
+ [source,adoc]
47
+ --
48
+ [data2text,{self-defined-context-name}={data-file-path}{, ...}] <1>
49
+ ----
50
+ Liquid template content
51
+ ----
52
+ --
53
+
54
+ Where:
55
+
56
+ * `[data2text]` is the block name;
57
+ * `{self-defined-context-name}` is the name of the context where the data
58
+ will be loaded into;
59
+ * `{data-file-path}` is the path to the JSON/YAML file to be loaded;
60
+ * `{, ...}` is optional and can be used to load multiple files in the same pattern;
61
+ * content within the block is called the "`template`". `Liquid template content`
62
+ is the content of the block where Liquid expressions can be used.
63
+
64
+ NOTE: The block opening and closing is demarcated by a `[source]` block syntax
65
+ (`----` or more `-`) or an open block delimiter (`--`).
66
+
67
+ `data-file-path` can be a relative or absolute path to the JSON/YAML file. If it is
68
+ a relative path, it is computed relative to the source where the block is
69
+ invoked.
70
+
71
+ [example]
72
+ ====
73
+ When `[data2text,data=data.yaml]` is invoked from the `foo/bar/doc.adoc` file,
74
+ then the data file `foo/bar/data.yaml` is loaded.
75
+ ====
76
+
77
+
78
+ === Template environment
79
+
80
+ Within the template environment, the data loaded from the JSON/YAML file can be
81
+ accessed by using the data context name defined in the block.
82
+
83
+ In addition to the typical Liquid syntax, the following features are available:
84
+
85
+ * `load_file` filter: loads a data file (of file types supported by `data2text`)
86
+ and makes its content available in the template context.
87
+
88
+
89
+ It is important to note that the Liquid template is rendered into a Metanorma
90
+ AsciiDoc block. This means that while AsciiDoc syntax can be used within the
91
+ template, the Liquid syntax is evaluated first.
92
+
93
+ [source]
94
+ ----
95
+ ┌──────────────────────┐
96
+ │ │
97
+ │ JSON/YAML files │
98
+ │ │
99
+ └──────────┬───────────┘
100
+
101
+ │ loaded into
102
+
103
+ ┌──────────────────────┐ ┌──────────────────────┐
104
+ │ │ │ │
105
+ │ data2text context │ │ Metanorma Document │
106
+ │ │ │ (with AsciiDoc │
107
+ └──────────┬───────────┘ │ attributes) │
108
+ │ │ │
109
+ │ available in └──────────┬───────────┘
110
+ ▼ │
111
+ ┌──────────────────────┐ │
112
+ │ │ │
113
+ │ Liquid Template │ │
114
+ │ Evaluation │ │
115
+ │ │ │
116
+ └──────────┬───────────┘ │
117
+ │ │
118
+ │ renders into │
119
+ ▼ │
120
+ ┌──────────────────────┐ │
121
+ │ │ │
122
+ │ Rendered Liquid as │ │
123
+ │ Metanorma AsciiDoc │ │
124
+ │ │ │
125
+ └──────────┬───────────┘ │
126
+ │ │
127
+ │ becomes │
128
+ ▼ │
129
+ ┌──────────────────────┐ │
130
+ │ │◄──────────────────┘
131
+ │ Metanorma AsciiDoc │ evaluated as
132
+ │ Content │ Metanorma AsciiDoc
133
+ │ │
134
+ └──────────────────────┘
135
+ ----
136
+
137
+
138
+
139
+ === AsciiDoc usage within the template
140
+
141
+ The Liquid template is rendered into a Metanorma AsciiDoc document.
142
+ This means that the following AsciiDoc syntax can be used within the template
143
+ as Liquid does not interfere with AsciiDoc syntax:
144
+
145
+ . `{variable}`: as in AsciiDoc syntax;
146
+
147
+ In `{variable}`(`{{variable}}`), `variable` is the name of the variable or
148
+ AsciiDoc attribute.
149
+
150
+
151
+ === Liquid syntax within the template
152
+
153
+ As with normal Liquid, you can use the following syntax to access variables
154
+ and attributes:
155
+
156
+ . Rendered variables: `{{ variable }}`
157
+
158
+ . Control syntaxes: `{% if/else/for/case %}`
159
+
160
+ . Filters: `{{ variable | filter_name: arg1, arg2 }}`
161
+
162
+ . Assignments: `{% assign variable = value %}`
163
+
164
+ . Comments: `{% comment %} ... {% endcomment %}`
165
+
166
+ . Raw content: `{% raw %} ... {% endraw %}`
167
+
168
+ . Multi-line Liquid code:
169
+ +
170
+ [source]
171
+ ----
172
+ {% liquid
173
+ assign variable = value
174
+ if condition
175
+ ...
176
+ else
177
+ ...
178
+ endif
179
+ %}
180
+ {{ variable }}
181
+ ----
182
+
183
+
184
+ === Accessing object values
185
+
186
+ Object values can be accessed via:
187
+
188
+ * the `.` (dot) separator
189
+ * the `[]` (bracket) operator
190
+
191
+ Syntax:
192
+
193
+ [source,adoc]
194
+ ----
195
+ {{object_name.key}} <1>
196
+ {{object_name["key"]}} <2>
197
+ ----
198
+ <1> `object_name` is the name of the context where the data is loaded,
199
+ `key` is the key name in the object.
200
+
201
+ <2> The bracket syntax can be used when the key name contains special characters
202
+ or spaces or when the key name is a variable.
203
+
204
+
205
+ [example]
206
+ ====
207
+ Given:
208
+
209
+ `strings.yaml`
210
+ [source,yaml]
211
+ ----
212
+ ---
213
+ foo: bar
214
+ dead: beef
215
+ ----
216
+
217
+ And the block:
218
+
219
+ [source,asciidoc]
220
+ ------
221
+ [data2text,data=strings.yaml]
222
+ ----
223
+ I'm heading to the {{data.foo}} for {{data.dead}}.
224
+ ----
225
+ ------
226
+
227
+ The file path is `strings.yaml`, and context name is `data`.
228
+ `{{data.foo}}` evaluates to the value of the key `foo` in `data`.
229
+
230
+ Will render as:
231
+
232
+ [source,asciidoc]
233
+ ----
234
+ I'm heading to the bar for beef.
235
+ ----
236
+ ====
237
+
238
+
239
+ When the key name is interpolated, the bracket syntax can be used.
240
+
241
+ [example]
242
+ ====
243
+ Given:
244
+
245
+ `strings.yaml`
246
+ [source,yaml]
247
+ ----
248
+ ---
249
+ foo: bar
250
+ dead: beef
251
+ ----
252
+
253
+ And the block:
254
+
255
+ [source,asciidoc]
256
+ ------
257
+ [data2text,data=strings.yaml]
258
+ ----
259
+ {% assign key = "foo" %}
260
+ I'm heading to the {{data[key]}} for {{data["dead"]}}.
261
+ ----
262
+ ------
263
+
264
+ The file path is `strings.yaml`, and context name is `data`.
265
+ `{{data[key]}}` evaluates to the value of the key `foo` in `data`.
266
+ `{{data["dead"]}}` evaluates to the value of the key `dead` in `data`.
267
+
268
+ Will render as:
269
+
270
+ [source,asciidoc]
271
+ ----
272
+ I'm heading to the bar for beef.
273
+ ----
274
+ ====
275
+
276
+
277
+ === Accessing arrays
278
+
279
+ ==== Length
280
+
281
+ The length of an array can be obtained by `{{arrayname.size}}`.
282
+
283
+ [example]
284
+ ====
285
+ Given:
286
+
287
+ `strings.yaml`
288
+ [source,yaml]
289
+ ----
290
+ ---
291
+ - lorem
292
+ - ipsum
293
+ - dolor
294
+ ----
295
+
296
+ And the block:
297
+ [source,asciidoc]
298
+ ------
299
+ [data2text,data=strings.yaml]
300
+ ----
301
+ The length of the YAML array is {{data.size}}.
302
+ ----
303
+ ------
304
+
305
+ The file path is `strings.yaml`, and context name is `data`.
306
+
307
+ `{{data.size}}` evaluates to the length of the array using liquid `size`
308
+ https://shopify.github.io/liquid/filters/size/[filter].
309
+
310
+ Will render as:
311
+ [source,asciidoc]
312
+ ----
313
+ The length of the YAML array is 3.
314
+ ----
315
+ ====
316
+
317
+ ==== Enumeration and context
318
+
319
+ The following syntax is used to enumerate items within an array:
320
+
321
+ [source,liquid]
322
+ --
323
+ {% for item in array_name %} <1>
324
+ ...content... <2>
325
+ {% endfor %}
326
+ --
327
+ <1> `array_name` is the name of the existing context that contains array data,
328
+ `item` is the current item within the array.
329
+ <2> `...content...` is the content of the block within the for-loop.
330
+
331
+ Within a Liquid
332
+ https://shopify.dev/docs/themes/liquid/reference/objects/for-loops[for-loop],
333
+ the following expressions can be used:
334
+
335
+ * `{{forloop.index0}}`: the zero-based position of the item `item_name` within
336
+ the parent array
337
+
338
+ * `{{forloop.length}}`: the total number of iterations of the loop.
339
+
340
+ * `{{forloop.first}}`: returns `true` if it's the first iteration of the for loop. Returns `false` if it is not the first iteration.
341
+
342
+ * `{{forloop.last}}`: returns `true` if it's the last iteration of the for loop.
343
+ Returns `false` if it is not the last iteration.
344
+
345
+ * `{{array_name.size}}`: the length of the array `array_name`
346
+
347
+ * `{{array_name[i]}}`: provides the value at index `i` (this is zero-based:
348
+ starts with `0`) in the array `array_name`; `array_name[-1]` can be used to
349
+ refer to the last item, `array_name[-2]` the second last item, and so on.
350
+
351
+
352
+ [example]
353
+ ====
354
+ Given:
355
+
356
+ strings.yaml
357
+ [source,yaml]
358
+ ----
359
+ ---
360
+ - lorem
361
+ - ipsum
362
+ - dolor
363
+ ----
364
+
365
+ And the block:
366
+ [source,asciidoc]
367
+ ------
368
+ [data2text,arr=strings.yaml]
369
+ ----
370
+ {% for item in arr %}
371
+ === {{forloop.index0}} {item}
372
+
373
+ This section is about {item}.
374
+
375
+ {endfor}
376
+ ----
377
+ ------
378
+
379
+ Where:
380
+
381
+ * file path is `strings.yaml`
382
+ * current context within the enumerator is called `item`
383
+ * `{{forloop.index0}}` gives the zero-based position of item `item` in the parent array `arr`.
384
+
385
+ Will render as:
386
+ [source,text]
387
+ ----
388
+ === 0 lorem
389
+
390
+ This section is about lorem.
391
+
392
+ === 1 ipsum
393
+
394
+ This section is about ipsum.
395
+
396
+ === 2 dolor
397
+
398
+ This section is about dolor.
399
+ ----
400
+ ====
401
+
402
+
403
+ === Accessing objects
404
+
405
+ ==== Size
406
+
407
+ Similar to arrays, the number of key-value pairs within an object can be
408
+ obtained by `{{objectname.size}}`.
409
+
410
+ [example]
411
+ ====
412
+ Given:
413
+
414
+ object.yaml
415
+ [source,yaml]
416
+ ----
417
+ ---
418
+ name: Lorem ipsum
419
+ desc: dolor sit amet
420
+ ----
421
+
422
+ And the block:
423
+ [source,asciidoc]
424
+ ------
425
+ [data2text,data=object.yaml]
426
+ ----
427
+ === {{data.name}}
428
+
429
+ {{data.desc}}
430
+ ----
431
+ ------
432
+
433
+ The file path is `object.yaml`, and context name is `data`.
434
+ `{{data.size}}` evaluates to the size of the object.
435
+
436
+ Will render as:
437
+ [source,asciidoc]
438
+ ----
439
+ === Lorem ipsum
440
+
441
+ dolor sit amet
442
+ ----
443
+ ====
444
+
445
+ ==== Enumeration and context
446
+
447
+ The following syntax is used to enumerate key-value pairs within an object:
448
+
449
+ [source,liquid]
450
+ --
451
+ {% for item in object_name %} <1>
452
+ {{item[0]}}, {{item[1]}} <2>
453
+ {% endfor %} <3>
454
+ --
455
+
456
+ <1> `object_name` is the name of the existing context that contains the object
457
+ <2> `{{item[0]}}` contains the key of the current enumerated object, `{{item[1]}}` contains the value
458
+ <3> `{% endfor %}` indicates where the object enumeration block ends
459
+
460
+
461
+ [example]
462
+ ====
463
+ Given:
464
+
465
+ object.yaml
466
+ [source,yaml]
467
+ ----
468
+ ---
469
+ name: Lorem ipsum
470
+ desc: dolor sit amet
471
+ ----
472
+
473
+ And the block:
474
+ [source,asciidoc]
475
+ ------
476
+ [data2text,my_item=object.yaml]
477
+ ----
478
+ {% for item in my_item %}
479
+ === {{item[0]}}
480
+
481
+ {{item[1]}}
482
+
483
+ {% endfor %}
484
+ ----
485
+ ------
486
+
487
+ Where:
488
+
489
+ * file path is `object.yaml`
490
+ * current key within the enumerator is called `item[0]`
491
+ * `{{item[0]}}` gives the key name in the current iteration
492
+ * `{{item[1]}}` gives the value in the current iteration
493
+
494
+ Will render as:
495
+ [source,text]
496
+ ----
497
+ === name
498
+
499
+ Lorem ipsum
500
+
501
+ === desc
502
+
503
+ dolor sit amet
504
+ ----
505
+ ====
506
+
507
+
508
+ Moreover, the `keys` and `values` attributes can also be used in object enumerators.
509
+
510
+
511
+ [example]
512
+ ====
513
+ Given:
514
+
515
+ object.yaml
516
+ [source,yaml]
517
+ ----
518
+ ---
519
+ name: Lorem ipsum
520
+ desc: dolor sit amet
521
+ ----
522
+
523
+ And the block:
524
+ [source,asciidoc]
525
+ ------
526
+ [data2text,item=object.yaml]
527
+ ----
528
+ .{{item.values[1]}}
529
+ [%noheader,cols="h,1"]
530
+ |===
531
+ {% for elem in item %}
532
+ | {{elem[0]}} | {{elem[1]}}
533
+
534
+ {% endfor %}
535
+ |===
536
+ ----
537
+ ------
538
+
539
+ Where:
540
+
541
+ * file path is `object.yaml`
542
+ * current key within the enumerator is called `key`
543
+ * `{{item[1]}}` gives the value of key in the current iteration the parent array `my_item`.
544
+ * `{{item.values[1]}}` gives the value located at the second key within `item`
545
+
546
+ Will render as:
547
+ [source,text]
548
+ ----
549
+ .dolor sit amet
550
+
551
+ [%noheader,cols="h,1"]
552
+ |===
553
+ | name | Lorem ipsum
554
+ | desc | dolor sit amet
555
+ |===
556
+ ----
557
+ ====
558
+
559
+ There are several optional arguments to the `for` tag that can influence which
560
+ items you receive in your loop and what order they appear in:
561
+
562
+ * limit:<INTEGER> lets you restrict how many items you get.
563
+ * offset:<INTEGER> lets you start the collection with the nth item.
564
+ * reversed iterates over the collection from last to first.
565
+
566
+ [example]
567
+ ====
568
+ Given:
569
+
570
+ strings.yaml
571
+ [source,yaml]
572
+ ----
573
+ ---
574
+ - lorem
575
+ - ipsum
576
+ - dolor
577
+ - sit
578
+ - amet
579
+ ----
580
+
581
+ And the block:
582
+ [source,asciidoc]
583
+ ------
584
+ [data2text,items=strings.yaml]
585
+ ----
586
+ {% for elem in items limit:2 offset:2 %}
587
+ {{item}}
588
+ {% endfor %}
589
+ ----
590
+ ------
591
+
592
+ Where:
593
+
594
+ * file path is `strings.yaml`
595
+ * `limit` - how many items we should take from the array
596
+ * `offset` - zero-based offset of item from which start the loop
597
+ * `{{item}}` gives the value of item in the array
598
+
599
+ Will render as:
600
+ [source,text]
601
+ ----
602
+ dolor sit
603
+ ----
604
+ ====
605
+
606
+
607
+ === Error Handling
608
+
609
+ ==== Invalid JSON or YAML file
610
+
611
+ If the specified file is an invalid JSON or YAML file, the block will raise an
612
+ error when the document is processed. The error will be:
613
+ `Metanorma::Plugin::Lutaml::ParseError`.
614
+
615
+ Detailed error messages will also be provided for troubleshooting.
616
+
617
+ ==== Invalid path of file
618
+
619
+ If the specified file path does not exist, the block will raise an
620
+ error when the document is processed. The error will be:
621
+ `Metanorma::Plugin::Lutaml::FileNotFoundError`.
622
+
623
+ === Advanced usage
624
+
625
+ ==== General
626
+
627
+ The `data2text` block supports a variety of advanced features, including:
628
+
629
+ * array of objects
630
+ * array of arrays
631
+ * nested loading of data file paths
632
+ * interpolated file names
633
+ * multiple contexts
634
+ * multiple contexts with mixed file formats
635
+
636
+ ==== Array of objects
637
+
638
+ [example]
639
+ ====
640
+ Given:
641
+
642
+ array_of_objects.yaml
643
+ [source,yaml]
644
+ ----
645
+ ---
646
+ - name: Lorem
647
+ desc: ipsum
648
+ nums: [2]
649
+ - name: dolor
650
+ desc: sit
651
+ nums: []
652
+ - name: amet
653
+ desc: lorem
654
+ nums: [2, 4, 6]
655
+ ----
656
+
657
+ And the block:
658
+ [source,asciidoc]
659
+ ------
660
+ [data2text,ar=array_of_objects.yaml]
661
+ ----
662
+ {% for item in ar %}
663
+
664
+ {{item.name}}:: {{item.desc}}
665
+
666
+ {% for num in item.nums %}
667
+ - {{item.name}}: {{num}}
668
+ {% endfor %}
669
+
670
+ {% endfor %}
671
+ ----
672
+ ------
673
+
674
+ Notice we are now defining multiple contexts:
675
+
676
+ * using different context names: `ar`, `item`, and `num`
677
+
678
+ Will render as:
679
+ [source,asciidoc]
680
+ ----
681
+ Lorem:: ipsum
682
+
683
+ - Lorem: 2
684
+
685
+ dolor:: sit
686
+
687
+ amet:: lorem
688
+
689
+ - amet: 2
690
+ - amet: 4
691
+ - amet: 6
692
+ ----
693
+ ====
694
+
695
+
696
+ ==== Interpolated file names
697
+
698
+ `data2text` blocks can be used for pre-processing document elements for AsciiDoc
699
+ consumption.
700
+
701
+ [example]
702
+ ====
703
+ Given:
704
+
705
+ strings.yaml
706
+ [source,yaml]
707
+ ----
708
+ ---
709
+ prefix: doc-
710
+ items:
711
+ - lorem
712
+ - ipsum
713
+ - dolor
714
+ ----
715
+
716
+ And the block:
717
+
718
+ [source,asciidoc]
719
+ --------
720
+ [data2text,yaml=strings.yaml]
721
+ ------
722
+ First item is {{yaml.items.first}}.
723
+ Last item is {{yaml.items.last}}.
724
+
725
+ {% for s in yaml.items %}
726
+ === {{forloop.index0}} -> {{forloop.index0 | plus: 1}} {{s}} == {{yaml.items[forloop.index0]}}
727
+
728
+ [source,ruby]
729
+ ----
730
+ \include::{{yaml.prefix}}{{forloop.index0}}.rb[]
731
+ ----
732
+
733
+ {% endfor %}
734
+ ------
735
+ --------
736
+
737
+
738
+ Will render as:
739
+ [source,asciidoc]
740
+ ------
741
+ First item is lorem.
742
+ Last item is dolor.
743
+
744
+ === 0 -> 1 lorem == lorem
745
+
746
+ [source,ruby]
747
+ ----
748
+ \include::doc-0.rb[]
749
+ ----
750
+
751
+ === 1 -> 2 ipsum == ipsum
752
+
753
+ [source,ruby]
754
+ ----
755
+ \include::doc-1.rb[]
756
+ ----
757
+
758
+ === 2 -> 3 dolor == dolor
759
+
760
+ [source,ruby]
761
+ ----
762
+ \include::doc-2.rb[]
763
+ ----
764
+ ------
765
+
766
+ This block instructs Metanorma to include the file `doc-0.rb`, `doc-1.rb`, and
767
+ `doc-2.rb` in the resulting document.
768
+ ====
769
+
770
+
771
+ ==== Multiple contexts
772
+
773
+ Multiple contexts can be defined in a single block.
774
+
775
+ [example]
776
+ ====
777
+ Given:
778
+
779
+ strings1.yaml
780
+ [source,yaml]
781
+ ----
782
+ ---
783
+ foo: bar
784
+ dead: beef
785
+ ----
786
+
787
+ strings2.yaml
788
+ [source,yaml]
789
+ ----
790
+ ---
791
+ hello: world
792
+ color: red
793
+ shape: square
794
+ ----
795
+
796
+ And the block:
797
+ [source,asciidoc]
798
+ ------
799
+ [data2text,data1=strings1.yaml,data2=strings2.yaml]
800
+ ----
801
+ I'm heading to the {{data1.foo}} for {{data1.dead}}.
802
+
803
+ This is hello {{data2.hello}}.
804
+ The color is {{data2.color}} and the shape is {{data2.shape}}.
805
+ ----
806
+ ------
807
+
808
+ The file path is `strings1.yaml`, and context name is `data1`.
809
+ `{{data1.foo}}` evaluates to the value of the key `foo` in `data1`.
810
+
811
+ The file path is `strings2.yaml`, and context name is `data2`.
812
+ `{{data2.hello}}` evaluates to the value of the key `hello` in `data2`.
813
+
814
+ Will render as:
815
+ [source,asciidoc]
816
+ ----
817
+ I'm heading to the bar for beef.
818
+
819
+ This is hello world.
820
+ The color is red and the shape is square.
821
+ ----
822
+ ====
823
+
824
+
825
+ ==== Multiple contexts with mixed file formats
826
+
827
+ When the file formats are mixed, use the `data2text` block to load multiple
828
+ files of different formats.
829
+
830
+ NOTE: The file format is determined by the file extension of the file path.
831
+
832
+ [example]
833
+ ====
834
+ Given:
835
+
836
+ `strings1.json`
837
+ [source,json]
838
+ ----
839
+ {
840
+ "foo": "bar",
841
+ "dead": "beef"
842
+ }
843
+ ----
844
+
845
+ `strings2.yaml`
846
+ [source,yaml]
847
+ ----
848
+ ---
849
+ hello: world
850
+ color: red
851
+ shape: square
852
+ ----
853
+
854
+ And the block:
855
+ [source,asciidoc]
856
+ ------
857
+ [data2text,my_json=strings1.json,my_yaml=strings2.yaml]
858
+ ----
859
+ I'm heading to the {{my_json.foo}} for {{my_json.dead}}.
860
+
861
+ This is hello {{my_yaml.hello}}.
862
+ The color is {{my_yaml.color}} and the shape is {{my_yaml.shape}}.
863
+ ----
864
+ ------
865
+
866
+ The file path is `strings1.json`, and context name is `my_json`.
867
+ `{{my_json.foo}}` evaluates to the value of the key `foo` in `my_json`.
868
+
869
+ The file path is `strings2.yaml`, and context name is `my_yaml`.
870
+ `{{my_yaml.hello}}` evaluates to the value of the key `hello` in `my_yaml`.
871
+
872
+ Will render as:
873
+ [source,asciidoc]
874
+ ----
875
+ I'm heading to the bar for beef.
876
+
877
+ This is hello world.
878
+ The color is red and the shape is square.
879
+ ----
880
+ ====
881
+
882
+
883
+ ==== Options in multiple contexts
884
+
885
+ When using the `data2text` block, you can use `include_path` option or
886
+ `template` option.
887
+
888
+ The `include_path` option add the path of the template files for
889
+ rendering liquid templates other than the location of the document.
890
+
891
+ [example]
892
+ ====
893
+ Given:
894
+
895
+ `strings1.json`
896
+ [source,json]
897
+ ----
898
+ {
899
+ "foo": "bar",
900
+ "dead": "beef"
901
+ }
902
+ ----
903
+
904
+ `strings2.yaml`
905
+ [source,yaml]
906
+ ----
907
+ ---
908
+ hello: world
909
+ color: red
910
+ shape: square
911
+ ----
912
+
913
+ `_my_template.liquid` in `templates` folder:
914
+ [source,liquid]
915
+ ----
916
+ I'm heading to the {{my_json.foo}} for {{my_json.dead}}.
917
+ ----
918
+
919
+ And the block:
920
+ [source,asciidoc]
921
+ ------
922
+ [data2text,my_json=strings1.json,my_yaml=strings2.yaml,include_path=templates]
923
+ ----
924
+ Hello {{my_yaml.hello}}.
925
+
926
+ {% render 'my_template' my_json: my_json %}
927
+ ----
928
+ ------
929
+
930
+ Will render as:
931
+ [source,asciidoc]
932
+ ----
933
+ Hello world.
934
+
935
+ I'm heading to the bar for beef.
936
+ ----
937
+ ====
938
+
939
+
940
+ The `template` option can be used to specify the liquid template file to be
941
+ used.
942
+
943
+ [example]
944
+ ====
945
+ Given:
946
+
947
+ `strings1.json`
948
+ [source,json]
949
+ ----
950
+ {
951
+ "foo": "bar",
952
+ "dead": "beef"
953
+ }
954
+ ----
955
+
956
+ `_my_template.liquid` in `templates` folder
957
+ [source,liquid]
958
+ ----
959
+ I'm heading to the {{my_json.foo}} for {{myjson.dead}}.
960
+ ----
961
+
962
+ And the block:
963
+ [source,asciidoc]
964
+ ------
965
+ [data2text,my_json=strings1.json,template=templates/_my_template.liquid]
966
+ ----
967
+ ----
968
+ ------
969
+
970
+ Will render as:
971
+ [source,asciidoc]
972
+ ----
973
+ I'm heading to the bar for beef.
974
+ ----
975
+ ====
976
+
977
+
978
+ ==== Nested loading of data file paths
979
+
980
+ There are cases where the data file paths are not known in advance or are
981
+ provided via a variable. In such cases, you can use the Metanorma-specific
982
+ `load_file` filter to load the data file paths dynamically.
983
+
984
+ This is useful when the data file paths are provided as part of the data
985
+ structure itself or when you want to load data files based on certain
986
+ conditions.
987
+
988
+ [example]
989
+ ====
990
+ Given:
991
+
992
+ `strings1.json`
993
+ [source,json]
994
+ ----
995
+ {
996
+ "foo": "bar",
997
+ "paths": ["a.yaml", "b.yaml"]
998
+ }
999
+ ----
1000
+
1001
+ Where:
1002
+
1003
+ * `paths` is an array of filepaths relative to the Metanorma document
1004
+
1005
+ `a.yaml`
1006
+ [source,yaml]
1007
+ ----
1008
+ ---
1009
+ shape: circle
1010
+ color: red
1011
+ ----
1012
+
1013
+ `b.yaml`
1014
+ [source,yaml]
1015
+ ----
1016
+ ---
1017
+ shape: square
1018
+ color: blue
1019
+ corners: 4
1020
+ ----
1021
+
1022
+ And the block:
1023
+ [source,asciidoc]
1024
+ ------
1025
+ [data2text,my_context=strings1.json]
1026
+ ----
1027
+ I'm heading to the {{my_context.foo}}.
1028
+
1029
+ {% for path in my_context.paths %}
1030
+ {% assign data = path | loadfile: "." %}
1031
+ This is {{ data.shape }} with color {{ data.color }}.
1032
+ {% endfor %}
1033
+ ----
1034
+ ------
1035
+
1036
+ Where:
1037
+
1038
+ * `loadfile:` is a liquid filter that loads the file content based on `path`
1039
+ with argument `.`. The argument is the path of the parent folder, which is the
1040
+ current directory of the Metanorma document.
1041
+
1042
+ Will render as:
1043
+ [source,asciidoc]
1044
+ ----
1045
+ I'm heading to the bar.
1046
+
1047
+ This is circle with color red.
1048
+ This is square with color blue.
1049
+ ----
1050
+ ====