metanorma-plugin-lutaml 0.7.30 → 0.7.31
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/Gemfile +10 -8
- data/README.adoc +16 -1030
- data/docs/usages/enterprise_architect.adoc +583 -0
- data/docs/usages/express.adoc +299 -0
- data/docs/usages/json_yaml.adoc +1034 -0
- data/docs/usages/lutaml-gml.adoc +73 -0
- data/docs/usages/lutaml-uml.adoc +73 -0
- data/lib/metanorma/plugin/lutaml/asciidoctor/preprocessor.rb +1 -1
- data/lib/metanorma/plugin/lutaml/base_structured_text_preprocessor.rb +192 -0
- data/lib/metanorma/plugin/lutaml/content.rb +89 -0
- data/lib/metanorma/plugin/lutaml/data2_text_preprocessor.rb +45 -0
- data/lib/metanorma/plugin/lutaml/express_remarks_decorator.rb +19 -6
- data/lib/metanorma/plugin/lutaml/json2_text_preprocessor.rb +43 -0
- data/lib/metanorma/plugin/lutaml/liquid/custom_blocks/key_iterator.rb +31 -0
- data/lib/metanorma/plugin/lutaml/liquid/custom_filters/loadfile.rb +18 -0
- data/lib/metanorma/plugin/lutaml/liquid/custom_filters/replace_regex.rb +14 -0
- data/lib/metanorma/plugin/lutaml/liquid/custom_filters/values.rb +13 -0
- data/lib/metanorma/plugin/lutaml/liquid/multiply_local_file_system.rb +29 -22
- data/lib/metanorma/plugin/lutaml/liquid_drops/gml_dictionary_drop.rb +1 -1
- data/lib/metanorma/plugin/lutaml/lutaml_diagram_base.rb +1 -1
- data/lib/metanorma/plugin/lutaml/lutaml_diagram_block_macro.rb +2 -1
- data/lib/metanorma/plugin/lutaml/lutaml_ea_diagram_block_macro.rb +2 -1
- data/lib/metanorma/plugin/lutaml/lutaml_ea_xmi_base.rb +48 -36
- data/lib/metanorma/plugin/lutaml/lutaml_figure_inline_macro.rb +2 -1
- data/lib/metanorma/plugin/lutaml/lutaml_gml_dictionary_block_macro.rb +3 -1
- data/lib/metanorma/plugin/lutaml/lutaml_klass_table_block_macro.rb +2 -1
- data/lib/metanorma/plugin/lutaml/lutaml_preprocessor.rb +15 -2
- data/lib/metanorma/plugin/lutaml/lutaml_table_inline_macro.rb +2 -1
- data/lib/metanorma/plugin/lutaml/source_extractor.rb +97 -0
- data/lib/metanorma/plugin/lutaml/utils.rb +59 -26
- data/lib/metanorma/plugin/lutaml/version.rb +1 -1
- data/lib/metanorma/plugin/lutaml/yaml2_text_preprocessor.rb +41 -0
- data/lib/metanorma-plugin-lutaml.rb +3 -0
- data/metanorma-plugin-lutaml.gemspec +7 -1
- metadata +35 -6
- data/lib/metanorma/plugin/lutaml/liquid_templates/test.rb +0 -1
- /data/lib/metanorma/plugin/lutaml/liquid/{custom_filters.rb → custom_filters/html2adoc.rb} +0 -0
@@ -0,0 +1,1034 @@
|
|
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
|
+
=== Advanced usage
|
608
|
+
|
609
|
+
==== General
|
610
|
+
|
611
|
+
The `data2text` block supports a variety of advanced features, including:
|
612
|
+
|
613
|
+
* array of objects
|
614
|
+
* array of arrays
|
615
|
+
* nested loading of data file paths
|
616
|
+
* interpolated file names
|
617
|
+
* multiple contexts
|
618
|
+
* multiple contexts with mixed file formats
|
619
|
+
|
620
|
+
==== Array of objects
|
621
|
+
|
622
|
+
[example]
|
623
|
+
====
|
624
|
+
Given:
|
625
|
+
|
626
|
+
array_of_objects.yaml
|
627
|
+
[source,yaml]
|
628
|
+
----
|
629
|
+
---
|
630
|
+
- name: Lorem
|
631
|
+
desc: ipsum
|
632
|
+
nums: [2]
|
633
|
+
- name: dolor
|
634
|
+
desc: sit
|
635
|
+
nums: []
|
636
|
+
- name: amet
|
637
|
+
desc: lorem
|
638
|
+
nums: [2, 4, 6]
|
639
|
+
----
|
640
|
+
|
641
|
+
And the block:
|
642
|
+
[source,asciidoc]
|
643
|
+
------
|
644
|
+
[data2text,ar=array_of_objects.yaml]
|
645
|
+
----
|
646
|
+
{% for item in ar %}
|
647
|
+
|
648
|
+
{{item.name}}:: {{item.desc}}
|
649
|
+
|
650
|
+
{% for num in item.nums %}
|
651
|
+
- {{item.name}}: {{num}}
|
652
|
+
{% endfor %}
|
653
|
+
|
654
|
+
{% endfor %}
|
655
|
+
----
|
656
|
+
------
|
657
|
+
|
658
|
+
Notice we are now defining multiple contexts:
|
659
|
+
|
660
|
+
* using different context names: `ar`, `item`, and `num`
|
661
|
+
|
662
|
+
Will render as:
|
663
|
+
[source,asciidoc]
|
664
|
+
----
|
665
|
+
Lorem:: ipsum
|
666
|
+
|
667
|
+
- Lorem: 2
|
668
|
+
|
669
|
+
dolor:: sit
|
670
|
+
|
671
|
+
amet:: lorem
|
672
|
+
|
673
|
+
- amet: 2
|
674
|
+
- amet: 4
|
675
|
+
- amet: 6
|
676
|
+
----
|
677
|
+
====
|
678
|
+
|
679
|
+
|
680
|
+
==== Interpolated file names
|
681
|
+
|
682
|
+
`data2text` blocks can be used for pre-processing document elements for AsciiDoc
|
683
|
+
consumption.
|
684
|
+
|
685
|
+
[example]
|
686
|
+
====
|
687
|
+
Given:
|
688
|
+
|
689
|
+
strings.yaml
|
690
|
+
[source,yaml]
|
691
|
+
----
|
692
|
+
---
|
693
|
+
prefix: doc-
|
694
|
+
items:
|
695
|
+
- lorem
|
696
|
+
- ipsum
|
697
|
+
- dolor
|
698
|
+
----
|
699
|
+
|
700
|
+
And the block:
|
701
|
+
|
702
|
+
[source,asciidoc]
|
703
|
+
--------
|
704
|
+
[data2text,yaml=strings.yaml]
|
705
|
+
------
|
706
|
+
First item is {{yaml.items.first}}.
|
707
|
+
Last item is {{yaml.items.last}}.
|
708
|
+
|
709
|
+
{% for s in yaml.items %}
|
710
|
+
=== {{forloop.index0}} -> {{forloop.index0 | plus: 1}} {{s}} == {{yaml.items[forloop.index0]}}
|
711
|
+
|
712
|
+
[source,ruby]
|
713
|
+
----
|
714
|
+
\include::{{yaml.prefix}}{{forloop.index0}}.rb[]
|
715
|
+
----
|
716
|
+
|
717
|
+
{% endfor %}
|
718
|
+
------
|
719
|
+
--------
|
720
|
+
|
721
|
+
|
722
|
+
Will render as:
|
723
|
+
[source,asciidoc]
|
724
|
+
------
|
725
|
+
First item is lorem.
|
726
|
+
Last item is dolor.
|
727
|
+
|
728
|
+
=== 0 -> 1 lorem == lorem
|
729
|
+
|
730
|
+
[source,ruby]
|
731
|
+
----
|
732
|
+
\include::doc-0.rb[]
|
733
|
+
----
|
734
|
+
|
735
|
+
=== 1 -> 2 ipsum == ipsum
|
736
|
+
|
737
|
+
[source,ruby]
|
738
|
+
----
|
739
|
+
\include::doc-1.rb[]
|
740
|
+
----
|
741
|
+
|
742
|
+
=== 2 -> 3 dolor == dolor
|
743
|
+
|
744
|
+
[source,ruby]
|
745
|
+
----
|
746
|
+
\include::doc-2.rb[]
|
747
|
+
----
|
748
|
+
------
|
749
|
+
|
750
|
+
This block instructs Metanorma to include the file `doc-0.rb`, `doc-1.rb`, and
|
751
|
+
`doc-2.rb` in the resulting document.
|
752
|
+
====
|
753
|
+
|
754
|
+
|
755
|
+
==== Multiple contexts
|
756
|
+
|
757
|
+
Multiple contexts can be defined in a single block.
|
758
|
+
|
759
|
+
[example]
|
760
|
+
====
|
761
|
+
Given:
|
762
|
+
|
763
|
+
strings1.yaml
|
764
|
+
[source,yaml]
|
765
|
+
----
|
766
|
+
---
|
767
|
+
foo: bar
|
768
|
+
dead: beef
|
769
|
+
----
|
770
|
+
|
771
|
+
strings2.yaml
|
772
|
+
[source,yaml]
|
773
|
+
----
|
774
|
+
---
|
775
|
+
hello: world
|
776
|
+
color: red
|
777
|
+
shape: square
|
778
|
+
----
|
779
|
+
|
780
|
+
And the block:
|
781
|
+
[source,asciidoc]
|
782
|
+
------
|
783
|
+
[data2text,data1=strings1.yaml,data2=strings2.yaml]
|
784
|
+
----
|
785
|
+
I'm heading to the {{data1.foo}} for {{data1.dead}}.
|
786
|
+
|
787
|
+
This is hello {{data2.hello}}.
|
788
|
+
The color is {{data2.color}} and the shape is {{data2.shape}}.
|
789
|
+
----
|
790
|
+
------
|
791
|
+
|
792
|
+
The file path is `strings1.yaml`, and context name is `data1`.
|
793
|
+
`{{data1.foo}}` evaluates to the value of the key `foo` in `data1`.
|
794
|
+
|
795
|
+
The file path is `strings2.yaml`, and context name is `data2`.
|
796
|
+
`{{data2.hello}}` evaluates to the value of the key `hello` in `data2`.
|
797
|
+
|
798
|
+
Will render as:
|
799
|
+
[source,asciidoc]
|
800
|
+
----
|
801
|
+
I'm heading to the bar for beef.
|
802
|
+
|
803
|
+
This is hello world.
|
804
|
+
The color is red and the shape is square.
|
805
|
+
----
|
806
|
+
====
|
807
|
+
|
808
|
+
|
809
|
+
==== Multiple contexts with mixed file formats
|
810
|
+
|
811
|
+
When the file formats are mixed, use the `data2text` block to load multiple
|
812
|
+
files of different formats.
|
813
|
+
|
814
|
+
NOTE: The file format is determined by the file extension of the file path.
|
815
|
+
|
816
|
+
[example]
|
817
|
+
====
|
818
|
+
Given:
|
819
|
+
|
820
|
+
`strings1.json`
|
821
|
+
[source,json]
|
822
|
+
----
|
823
|
+
{
|
824
|
+
"foo": "bar",
|
825
|
+
"dead": "beef"
|
826
|
+
}
|
827
|
+
----
|
828
|
+
|
829
|
+
`strings2.yaml`
|
830
|
+
[source,yaml]
|
831
|
+
----
|
832
|
+
---
|
833
|
+
hello: world
|
834
|
+
color: red
|
835
|
+
shape: square
|
836
|
+
----
|
837
|
+
|
838
|
+
And the block:
|
839
|
+
[source,asciidoc]
|
840
|
+
------
|
841
|
+
[data2text,my_json=strings1.json,my_yaml=strings2.yaml]
|
842
|
+
----
|
843
|
+
I'm heading to the {{my_json.foo}} for {{my_json.dead}}.
|
844
|
+
|
845
|
+
This is hello {{my_yaml.hello}}.
|
846
|
+
The color is {{my_yaml.color}} and the shape is {{my_yaml.shape}}.
|
847
|
+
----
|
848
|
+
------
|
849
|
+
|
850
|
+
The file path is `strings1.json`, and context name is `my_json`.
|
851
|
+
`{{my_json.foo}}` evaluates to the value of the key `foo` in `my_json`.
|
852
|
+
|
853
|
+
The file path is `strings2.yaml`, and context name is `my_yaml`.
|
854
|
+
`{{my_yaml.hello}}` evaluates to the value of the key `hello` in `my_yaml`.
|
855
|
+
|
856
|
+
Will render as:
|
857
|
+
[source,asciidoc]
|
858
|
+
----
|
859
|
+
I'm heading to the bar for beef.
|
860
|
+
|
861
|
+
This is hello world.
|
862
|
+
The color is red and the shape is square.
|
863
|
+
----
|
864
|
+
====
|
865
|
+
|
866
|
+
|
867
|
+
==== Options in multiple contexts
|
868
|
+
|
869
|
+
When using the `data2text` block, you can use `include_path` option or
|
870
|
+
`template` option.
|
871
|
+
|
872
|
+
The `include_path` option add the path of the template files for
|
873
|
+
rendering liquid templates other than the location of the document.
|
874
|
+
|
875
|
+
[example]
|
876
|
+
====
|
877
|
+
Given:
|
878
|
+
|
879
|
+
`strings1.json`
|
880
|
+
[source,json]
|
881
|
+
----
|
882
|
+
{
|
883
|
+
"foo": "bar",
|
884
|
+
"dead": "beef"
|
885
|
+
}
|
886
|
+
----
|
887
|
+
|
888
|
+
`strings2.yaml`
|
889
|
+
[source,yaml]
|
890
|
+
----
|
891
|
+
---
|
892
|
+
hello: world
|
893
|
+
color: red
|
894
|
+
shape: square
|
895
|
+
----
|
896
|
+
|
897
|
+
`_my_template.liquid` in `templates` folder:
|
898
|
+
[source,liquid]
|
899
|
+
----
|
900
|
+
I'm heading to the {{my_json.foo}} for {{my_json.dead}}.
|
901
|
+
----
|
902
|
+
|
903
|
+
And the block:
|
904
|
+
[source,asciidoc]
|
905
|
+
------
|
906
|
+
[data2text,my_json=strings1.json,my_yaml=strings2.yaml,include_path=templates]
|
907
|
+
----
|
908
|
+
Hello {{my_yaml.hello}}.
|
909
|
+
|
910
|
+
{% render 'my_template' my_json: my_json %}
|
911
|
+
----
|
912
|
+
------
|
913
|
+
|
914
|
+
Will render as:
|
915
|
+
[source,asciidoc]
|
916
|
+
----
|
917
|
+
Hello world.
|
918
|
+
|
919
|
+
I'm heading to the bar for beef.
|
920
|
+
----
|
921
|
+
====
|
922
|
+
|
923
|
+
|
924
|
+
The `template` option can be used to specify the liquid template file to be
|
925
|
+
used.
|
926
|
+
|
927
|
+
[example]
|
928
|
+
====
|
929
|
+
Given:
|
930
|
+
|
931
|
+
`strings1.json`
|
932
|
+
[source,json]
|
933
|
+
----
|
934
|
+
{
|
935
|
+
"foo": "bar",
|
936
|
+
"dead": "beef"
|
937
|
+
}
|
938
|
+
----
|
939
|
+
|
940
|
+
`_my_template.liquid` in `templates` folder
|
941
|
+
[source,liquid]
|
942
|
+
----
|
943
|
+
I'm heading to the {{my_json.foo}} for {{myjson.dead}}.
|
944
|
+
----
|
945
|
+
|
946
|
+
And the block:
|
947
|
+
[source,asciidoc]
|
948
|
+
------
|
949
|
+
[data2text,my_json=strings1.json,template=templates/_my_template.liquid]
|
950
|
+
----
|
951
|
+
----
|
952
|
+
------
|
953
|
+
|
954
|
+
Will render as:
|
955
|
+
[source,asciidoc]
|
956
|
+
----
|
957
|
+
I'm heading to the bar for beef.
|
958
|
+
----
|
959
|
+
====
|
960
|
+
|
961
|
+
|
962
|
+
==== Nested loading of data file paths
|
963
|
+
|
964
|
+
There are cases where the data file paths are not known in advance or are
|
965
|
+
provided via a variable. In such cases, you can use the Metanorma-specific
|
966
|
+
`load_file` filter to load the data file paths dynamically.
|
967
|
+
|
968
|
+
This is useful when the data file paths are provided as part of the data
|
969
|
+
structure itself or when you want to load data files based on certain
|
970
|
+
conditions.
|
971
|
+
|
972
|
+
[example]
|
973
|
+
====
|
974
|
+
Given:
|
975
|
+
|
976
|
+
`strings1.json`
|
977
|
+
[source,json]
|
978
|
+
----
|
979
|
+
{
|
980
|
+
"foo": "bar",
|
981
|
+
"paths": ["a.yaml", "b.yaml"]
|
982
|
+
}
|
983
|
+
----
|
984
|
+
|
985
|
+
Where:
|
986
|
+
|
987
|
+
* `paths` is an array of filepaths relative to the Metanorma document
|
988
|
+
|
989
|
+
`a.yaml`
|
990
|
+
[source,yaml]
|
991
|
+
----
|
992
|
+
---
|
993
|
+
shape: circle
|
994
|
+
color: red
|
995
|
+
----
|
996
|
+
|
997
|
+
`b.yaml`
|
998
|
+
[source,yaml]
|
999
|
+
----
|
1000
|
+
---
|
1001
|
+
shape: square
|
1002
|
+
color: blue
|
1003
|
+
corners: 4
|
1004
|
+
----
|
1005
|
+
|
1006
|
+
And the block:
|
1007
|
+
[source,asciidoc]
|
1008
|
+
------
|
1009
|
+
[data2text,my_context=strings1.json]
|
1010
|
+
----
|
1011
|
+
I'm heading to the {{my_context.foo}}.
|
1012
|
+
|
1013
|
+
{% for path in my_context.paths %}
|
1014
|
+
{% assign data = path | loadfile: "." %}
|
1015
|
+
This is {{ data.shape }} with color {{ data.color }}.
|
1016
|
+
{% endfor %}
|
1017
|
+
----
|
1018
|
+
------
|
1019
|
+
|
1020
|
+
Where:
|
1021
|
+
|
1022
|
+
* `loadfile:` is a liquid filter that loads the file content based on `path`
|
1023
|
+
with argument `.`. The argument is the path of the parent folder, which is the
|
1024
|
+
current directory of the Metanorma document.
|
1025
|
+
|
1026
|
+
Will render as:
|
1027
|
+
[source,asciidoc]
|
1028
|
+
----
|
1029
|
+
I'm heading to the bar.
|
1030
|
+
|
1031
|
+
This is circle with color red.
|
1032
|
+
This is square with color blue.
|
1033
|
+
----
|
1034
|
+
====
|