metanorma-plugin-datastruct 0.3.6 → 0.3.7
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/.rubocop.yml +1 -0
- data/README.adoc +338 -138
- data/lib/metanorma/plugin/datastruct/base_structured_text_preprocessor.rb +26 -14
- data/lib/metanorma/plugin/datastruct/liquid/custom_blocks/key_iterator.rb +31 -0
- data/lib/metanorma/plugin/datastruct/liquid/custom_filters/loadfile.rb +18 -0
- data/lib/metanorma/plugin/datastruct/liquid/custom_filters/replace_regex.rb +14 -0
- data/lib/metanorma/plugin/datastruct/liquid/custom_filters/values.rb +13 -0
- data/lib/metanorma/plugin/datastruct/version.rb +1 -1
- metadata +5 -5
- data/lib/liquid/custom_blocks/key_iterator.rb +0 -25
- data/lib/liquid/custom_filters/loadfile.rb +0 -12
- data/lib/liquid/custom_filters/replace_regex.rb +0 -8
- data/lib/liquid/custom_filters/values.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ea219e7fd4daff9f73f0c42ec77c18e72b4b432fbc8b211d51fddac827adcc22
|
4
|
+
data.tar.gz: a8b9113037ab104b726bfbcf0cd0fc07492cdd343f0c348aadf514ca8b6591e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2eb61b32eab083097ea5bac2ad0ce0d193b5266b71619beeb5a356febf199efe79fe6080714025a2ee90e892e2bee2b9e1c86838692efe04c703d29fddda9630
|
7
|
+
data.tar.gz: ab5f9e073dea75c14b5923b678f5cff8453affaa6f2e6928dabc327b9a31ec835c4e0d624a8eb47feb36f9d168d875dc2a20a3f6e6555a6a557c6c02efd4ca4b
|
data/.rubocop.yml
CHANGED
data/README.adoc
CHANGED
@@ -1,82 +1,230 @@
|
|
1
|
-
= Metanorma
|
1
|
+
= Metanorma Datastruct plugin
|
2
2
|
|
3
|
-
==
|
3
|
+
== Purpose
|
4
|
+
|
5
|
+
This plugin allows you to access static data structures including JSON and YAML
|
6
|
+
from within a Metanorma document.
|
4
7
|
|
5
|
-
Metanorma plugin that allows you to access static data structures like JSON, YAML, XML from a Metanorma document
|
6
8
|
|
7
9
|
== Installation
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
The functionality of this plugin is included in the default distribution of
|
12
|
+
Metanorma.
|
13
|
+
|
14
|
+
* For users there is no need to install the plugin separately.
|
15
|
+
|
16
|
+
* For development purposes or to use the Git version of the plugin, you may
|
17
|
+
directly add the gem 'metanorma-plugin-datastruct' to your Gemfile.
|
18
|
+
|
13
19
|
|
14
20
|
== Usage
|
15
21
|
|
16
|
-
|
22
|
+
=== General
|
23
|
+
|
24
|
+
The plugin provides the following block commands:
|
25
|
+
|
26
|
+
`data2text`:: Loads one or more JSON/YAML files and makes them available for
|
27
|
+
use in a Metanorma template context.
|
17
28
|
|
18
|
-
|
29
|
+
`yaml2text`:: Identical to `data2text`, but only loads YAML files.
|
19
30
|
|
20
|
-
|
21
|
-
|
31
|
+
`json2text`:: Identical to `data2text`, but only loads JSON files.
|
32
|
+
|
33
|
+
|
34
|
+
=== Liquid syntax
|
35
|
+
|
36
|
+
These block commands make specified data available in the context of a template
|
37
|
+
block that supports Liquid. Liquid is a template language that allows you to
|
38
|
+
create dynamic content through templating.
|
39
|
+
|
40
|
+
Liquid supports many templating features, including:
|
22
41
|
|
23
42
|
* variables, variable assignment
|
24
43
|
* flow control (if/case)
|
25
44
|
* filters
|
26
45
|
* loops
|
27
46
|
|
28
|
-
See
|
47
|
+
NOTE: See the introduction to the
|
48
|
+
https://shopify.github.io/liquid/basics/introduction/[Liquid language] for
|
49
|
+
reference.
|
50
|
+
|
51
|
+
In the following sections, we will use `data2text` as an example, but the
|
52
|
+
same applies to `yaml2text` and `json2text`.
|
29
53
|
|
30
54
|
|
31
55
|
[[defining_syntax]]
|
32
|
-
=== Defining
|
56
|
+
=== Defining a block
|
33
57
|
|
34
|
-
A `
|
58
|
+
A `data2text` block is created by specifying the block name `[data2text]`
|
59
|
+
followed by a comma and the file paths of the JSON/YAML file and the assigned
|
60
|
+
context name.
|
35
61
|
|
36
|
-
|
37
|
-
or the `[source]` block syntax (`----` or more `-`).
|
62
|
+
Syntax:
|
38
63
|
|
39
64
|
[source,adoc]
|
40
65
|
--
|
41
|
-
[
|
66
|
+
[data2text,{self-defined-context-name}={data-file-path}{, ...}] <1>
|
42
67
|
----
|
43
|
-
|
68
|
+
Liquid template content
|
44
69
|
----
|
45
70
|
--
|
46
71
|
|
47
72
|
Where:
|
48
73
|
|
49
|
-
*
|
74
|
+
* `[data2text]` is the block name;
|
75
|
+
* `{self-defined-context-name}` is the name of the context where the data
|
76
|
+
will be loaded into;
|
77
|
+
* `{data-file-path}` is the path to the JSON/YAML file to be loaded;
|
78
|
+
* `{, ...}` is optional and can be used to load multiple files in the same pattern;
|
79
|
+
* content within the block is called the "`template`". `Liquid template content`
|
80
|
+
is the content of the block where Liquid expressions can be used.
|
81
|
+
|
82
|
+
NOTE: The block opening and closing is demarcated by a `[source]` block syntax
|
83
|
+
(`----` or more `-`) or an open block delimiter (`--`).
|
84
|
+
|
85
|
+
`data-file-path` can be a relative or absolute path to the JSON/YAML file. If it is
|
86
|
+
a relative path, it is computed relative to the source where the block is
|
87
|
+
invoked.
|
88
|
+
|
89
|
+
[example]
|
90
|
+
====
|
91
|
+
When `[data2text,data=data.yaml]` is invoked from the `foo/bar/doc.adoc` file,
|
92
|
+
then the data file `foo/bar/data.yaml` is loaded.
|
93
|
+
====
|
94
|
+
|
95
|
+
|
96
|
+
=== Template environment
|
97
|
+
|
98
|
+
Within the template environment, the data loaded from the JSON/YAML file can be
|
99
|
+
accessed by using the data context name defined in the block.
|
100
|
+
|
101
|
+
In addition to the typical Liquid syntax, the following features are available:
|
102
|
+
|
103
|
+
* `load_file` filter: loads a data file (of file types supported by `data2text`)
|
104
|
+
and makes its content available in the template context.
|
105
|
+
|
106
|
+
|
107
|
+
It is important to note that the Liquid template is rendered into a Metanorma
|
108
|
+
AsciiDoc block. This means that while AsciiDoc syntax can be used within the
|
109
|
+
template, the Liquid syntax is evaluated first.
|
110
|
+
|
111
|
+
[source]
|
112
|
+
----
|
113
|
+
┌──────────────────────┐
|
114
|
+
│ │
|
115
|
+
│ JSON/YAML files │
|
116
|
+
│ │
|
117
|
+
└──────────┬───────────┘
|
118
|
+
│
|
119
|
+
│ loaded into
|
120
|
+
▼
|
121
|
+
┌──────────────────────┐ ┌──────────────────────┐
|
122
|
+
│ │ │ │
|
123
|
+
│ data2text context │ │ Metanorma Document │
|
124
|
+
│ │ │ (with AsciiDoc │
|
125
|
+
└──────────┬───────────┘ │ attributes) │
|
126
|
+
│ │ │
|
127
|
+
│ available in └──────────┬───────────┘
|
128
|
+
▼ │
|
129
|
+
┌──────────────────────┐ │
|
130
|
+
│ │ │
|
131
|
+
│ Liquid Template │ │
|
132
|
+
│ Evaluation │ │
|
133
|
+
│ │ │
|
134
|
+
└──────────┬───────────┘ │
|
135
|
+
│ │
|
136
|
+
│ renders into │
|
137
|
+
▼ │
|
138
|
+
┌──────────────────────┐ │
|
139
|
+
│ │ │
|
140
|
+
│ Rendered Liquid as │ │
|
141
|
+
│ Metanorma AsciiDoc │ │
|
142
|
+
│ │ │
|
143
|
+
└──────────┬───────────┘ │
|
144
|
+
│ │
|
145
|
+
│ becomes │
|
146
|
+
▼ │
|
147
|
+
┌──────────────────────┐ │
|
148
|
+
│ │◄──────────────────┘
|
149
|
+
│ Metanorma AsciiDoc │ evaluated as
|
150
|
+
│ Content │ Metanorma AsciiDoc
|
151
|
+
│ │
|
152
|
+
└──────────────────────┘
|
153
|
+
----
|
154
|
+
|
155
|
+
|
156
|
+
|
157
|
+
=== AsciiDoc usage within the template
|
158
|
+
|
159
|
+
The Liquid template is rendered into a Metanorma AsciiDoc document.
|
160
|
+
This means that the following AsciiDoc syntax can be used within the template
|
161
|
+
as Liquid does not interfere with AsciiDoc syntax:
|
50
162
|
|
51
|
-
|
163
|
+
. `{variable}`: as in AsciiDoc syntax;
|
52
164
|
|
53
|
-
|
165
|
+
In `{variable}`(`{{variable}}`), `variable` is the name of the variable or
|
166
|
+
AsciiDoc attribute.
|
54
167
|
|
55
|
-
=== Interpolation
|
56
168
|
|
57
|
-
|
169
|
+
=== Liquid syntax within the template
|
58
170
|
|
59
|
-
|
60
|
-
|
171
|
+
As with normal Liquid, you can use the following syntax to access variables
|
172
|
+
and attributes:
|
61
173
|
|
62
|
-
|
174
|
+
. Rendered variables: `{{ variable }}`
|
63
175
|
|
64
|
-
|
176
|
+
. Control syntaxes: `{% if/else/for/case %}`
|
177
|
+
|
178
|
+
. Filters: `{{ variable | filter_name: arg1, arg2 }}`
|
179
|
+
|
180
|
+
. Assignments: `{% assign variable = value %}`
|
181
|
+
|
182
|
+
. Comments: `{% comment %} ... {% endcomment %}`
|
65
183
|
|
66
|
-
|
67
|
-
|
68
|
-
|
184
|
+
. Raw content: `{% raw %} ... {% endraw %}`
|
185
|
+
|
186
|
+
. Multi-line Liquid code:
|
187
|
+
+
|
188
|
+
[source]
|
189
|
+
----
|
190
|
+
{% liquid
|
191
|
+
assign variable = value
|
192
|
+
if condition
|
193
|
+
...
|
194
|
+
else
|
195
|
+
...
|
196
|
+
endif
|
197
|
+
%}
|
198
|
+
{{ variable }}
|
199
|
+
----
|
69
200
|
|
70
201
|
|
71
202
|
=== Accessing object values
|
72
203
|
|
73
|
-
Object values
|
204
|
+
Object values can be accessed via:
|
74
205
|
|
75
|
-
|
76
|
-
|
206
|
+
* the `.` (dot) separator
|
207
|
+
* the `[]` (bracket) operator
|
208
|
+
|
209
|
+
Syntax:
|
210
|
+
|
211
|
+
[source,adoc]
|
212
|
+
----
|
213
|
+
{{object_name.key}} <1>
|
214
|
+
{{object_name["key"]}} <2>
|
215
|
+
----
|
216
|
+
<1> `object_name` is the name of the context where the data is loaded,
|
217
|
+
`key` is the key name in the object.
|
218
|
+
|
219
|
+
<2> The bracket syntax can be used when the key name contains special characters
|
220
|
+
or spaces or when the key name is a variable.
|
221
|
+
|
222
|
+
|
223
|
+
[example]
|
224
|
+
====
|
77
225
|
Given:
|
78
226
|
|
79
|
-
strings.yaml
|
227
|
+
`strings.yaml`
|
80
228
|
[source,yaml]
|
81
229
|
----
|
82
230
|
---
|
@@ -85,9 +233,10 @@ dead: beef
|
|
85
233
|
----
|
86
234
|
|
87
235
|
And the block:
|
236
|
+
|
88
237
|
[source,asciidoc]
|
89
238
|
------
|
90
|
-
[
|
239
|
+
[data2text,data=strings.yaml]
|
91
240
|
----
|
92
241
|
I'm heading to the {{data.foo}} for {{data.dead}}.
|
93
242
|
----
|
@@ -97,12 +246,50 @@ The file path is `strings.yaml`, and context name is `data`.
|
|
97
246
|
`{{data.foo}}` evaluates to the value of the key `foo` in `data`.
|
98
247
|
|
99
248
|
Will render as:
|
249
|
+
|
100
250
|
[source,asciidoc]
|
101
251
|
----
|
102
252
|
I'm heading to the bar for beef.
|
103
253
|
----
|
254
|
+
====
|
104
255
|
|
105
|
-
|
256
|
+
|
257
|
+
When the key name is interpolated, the bracket syntax can be used.
|
258
|
+
|
259
|
+
[example]
|
260
|
+
====
|
261
|
+
Given:
|
262
|
+
|
263
|
+
`strings.yaml`
|
264
|
+
[source,yaml]
|
265
|
+
----
|
266
|
+
---
|
267
|
+
foo: bar
|
268
|
+
dead: beef
|
269
|
+
----
|
270
|
+
|
271
|
+
And the block:
|
272
|
+
|
273
|
+
[source,asciidoc]
|
274
|
+
------
|
275
|
+
[data2text,data=strings.yaml]
|
276
|
+
----
|
277
|
+
{% assign key = "foo" %}
|
278
|
+
I'm heading to the {{data[key]}} for {{data["dead"]}}.
|
279
|
+
----
|
280
|
+
------
|
281
|
+
|
282
|
+
The file path is `strings.yaml`, and context name is `data`.
|
283
|
+
`{{data[key]}}` evaluates to the value of the key `foo` in `data`.
|
284
|
+
`{{data["dead"]}}` evaluates to the value of the key `dead` in `data`.
|
285
|
+
|
286
|
+
Will render as:
|
287
|
+
|
288
|
+
[source,asciidoc]
|
289
|
+
----
|
290
|
+
I'm heading to the bar for beef.
|
291
|
+
----
|
292
|
+
====
|
106
293
|
|
107
294
|
|
108
295
|
=== Accessing arrays
|
@@ -111,11 +298,11 @@ I'm heading to the bar for beef.
|
|
111
298
|
|
112
299
|
The length of an array can be obtained by `{{arrayname.size}}`.
|
113
300
|
|
114
|
-
|
115
|
-
|
301
|
+
[example]
|
302
|
+
====
|
116
303
|
Given:
|
117
304
|
|
118
|
-
strings.yaml
|
305
|
+
`strings.yaml`
|
119
306
|
[source,yaml]
|
120
307
|
----
|
121
308
|
---
|
@@ -127,56 +314,61 @@ strings.yaml
|
|
127
314
|
And the block:
|
128
315
|
[source,asciidoc]
|
129
316
|
------
|
130
|
-
[
|
317
|
+
[data2text,data=strings.yaml]
|
131
318
|
----
|
132
319
|
The length of the YAML array is {{data.size}}.
|
133
320
|
----
|
134
321
|
------
|
135
322
|
|
136
323
|
The file path is `strings.yaml`, and context name is `data`.
|
137
|
-
|
324
|
+
|
325
|
+
`{{data.size}}` evaluates to the length of the array using liquid `size`
|
326
|
+
https://shopify.github.io/liquid/filters/size/[filter].
|
138
327
|
|
139
328
|
Will render as:
|
140
329
|
[source,asciidoc]
|
141
330
|
----
|
142
331
|
The length of the YAML array is 3.
|
143
332
|
----
|
144
|
-
|
145
|
-
--
|
333
|
+
====
|
146
334
|
|
147
335
|
==== Enumeration and context
|
148
336
|
|
149
337
|
The following syntax is used to enumerate items within an array:
|
150
338
|
|
151
|
-
[source,
|
339
|
+
[source,liquid]
|
152
340
|
--
|
153
|
-
{% for item in array_name %}
|
154
|
-
...content...
|
341
|
+
{% for item in array_name %} <1>
|
342
|
+
...content... <2>
|
155
343
|
{% endfor %}
|
156
344
|
--
|
345
|
+
<1> `array_name` is the name of the existing context that contains array data,
|
346
|
+
`item` is the current item within the array.
|
347
|
+
<2> `...content...` is the content of the block within the for-loop.
|
157
348
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
* `item` is the current item within the array
|
162
|
-
|
163
|
-
Within an array enumerator, the following https://shopify.dev/docs/themes/liquid/reference/objects/for-loops[expressions] can be used:
|
349
|
+
Within a Liquid
|
350
|
+
https://shopify.dev/docs/themes/liquid/reference/objects/for-loops[for-loop],
|
351
|
+
the following expressions can be used:
|
164
352
|
|
165
|
-
* `{{forloop.index0}}
|
353
|
+
* `{{forloop.index0}}`: the zero-based position of the item `item_name` within
|
354
|
+
the parent array
|
166
355
|
|
167
|
-
* `{{forloop.length}}
|
356
|
+
* `{{forloop.length}}`: the total number of iterations of the loop.
|
168
357
|
|
169
|
-
* `{{forloop.first}}
|
358
|
+
* `{{forloop.first}}`: returns `true` if it's the first iteration of the for loop. Returns `false` if it is not the first iteration.
|
170
359
|
|
171
|
-
* `{{forloop.last}}
|
360
|
+
* `{{forloop.last}}`: returns `true` if it's the last iteration of the for loop.
|
361
|
+
Returns `false` if it is not the last iteration.
|
172
362
|
|
173
|
-
* `{{array_name.size}}
|
363
|
+
* `{{array_name.size}}`: the length of the array `array_name`
|
174
364
|
|
175
|
-
* `{{array_name[i]}}
|
365
|
+
* `{{array_name[i]}}`: provides the value at index `i` (this is zero-based:
|
366
|
+
starts with `0`) in the array `array_name`; `array_name[-1]` can be used to
|
367
|
+
refer to the last item, `array_name[-2]` the second last item, and so on.
|
176
368
|
|
177
369
|
|
178
|
-
|
179
|
-
|
370
|
+
[example]
|
371
|
+
====
|
180
372
|
Given:
|
181
373
|
|
182
374
|
strings.yaml
|
@@ -191,7 +383,7 @@ strings.yaml
|
|
191
383
|
And the block:
|
192
384
|
[source,asciidoc]
|
193
385
|
------
|
194
|
-
[
|
386
|
+
[data2text,arr=strings.yaml]
|
195
387
|
----
|
196
388
|
{% for item in arr %}
|
197
389
|
=== {{forloop.index0}} {item}
|
@@ -223,21 +415,19 @@ This section is about ipsum.
|
|
223
415
|
|
224
416
|
This section is about dolor.
|
225
417
|
----
|
226
|
-
|
227
|
-
--
|
418
|
+
====
|
228
419
|
|
229
420
|
|
230
421
|
|
231
422
|
=== Accessing objects
|
232
423
|
|
233
|
-
|
234
424
|
==== Size
|
235
425
|
|
236
426
|
Similar to arrays, the number of key-value pairs within an object can be
|
237
427
|
obtained by `{{objectname.size}}`.
|
238
428
|
|
239
|
-
|
240
|
-
|
429
|
+
[example]
|
430
|
+
====
|
241
431
|
Given:
|
242
432
|
|
243
433
|
object.yaml
|
@@ -251,7 +441,7 @@ desc: dolor sit amet
|
|
251
441
|
And the block:
|
252
442
|
[source,asciidoc]
|
253
443
|
------
|
254
|
-
[
|
444
|
+
[data2text,data=object.yaml]
|
255
445
|
----
|
256
446
|
=== {{data.name}}
|
257
447
|
|
@@ -269,30 +459,26 @@ Will render as:
|
|
269
459
|
|
270
460
|
dolor sit amet
|
271
461
|
----
|
272
|
-
|
273
|
-
--
|
462
|
+
====
|
274
463
|
|
275
464
|
==== Enumeration and context
|
276
465
|
|
277
466
|
The following syntax is used to enumerate key-value pairs within an object:
|
278
467
|
|
279
|
-
[source,
|
468
|
+
[source,liquid]
|
280
469
|
--
|
281
|
-
{% for item in object_name %}
|
282
|
-
{{item[0]}}, {{item[1]}}
|
283
|
-
{% endfor %}
|
470
|
+
{% for item in object_name %} <1>
|
471
|
+
{{item[0]}}, {{item[1]}} <2>
|
472
|
+
{% endfor %} <3>
|
284
473
|
--
|
285
474
|
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
* `{{item[0]}}` contains the key of the current enumrated object
|
290
|
-
* `{{item[1]}}` contains the value
|
291
|
-
* `{% endfor %}` indicates where the object enumeration block ends
|
475
|
+
<1> `object_name` is the name of the existing context that contains the object
|
476
|
+
<2> `{{item[0]}}` contains the key of the current enumerated object, `{{item[1]}}` contains the value
|
477
|
+
<3> `{% endfor %}` indicates where the object enumeration block ends
|
292
478
|
|
293
479
|
|
294
|
-
|
295
|
-
|
480
|
+
[example]
|
481
|
+
====
|
296
482
|
Given:
|
297
483
|
|
298
484
|
object.yaml
|
@@ -306,7 +492,7 @@ desc: dolor sit amet
|
|
306
492
|
And the block:
|
307
493
|
[source,asciidoc]
|
308
494
|
------
|
309
|
-
[
|
495
|
+
[data2text,my_item=object.yaml]
|
310
496
|
----
|
311
497
|
{% for item in my_item %}
|
312
498
|
=== {{item[0]}}
|
@@ -335,16 +521,14 @@ Lorem ipsum
|
|
335
521
|
|
336
522
|
dolor sit amet
|
337
523
|
----
|
338
|
-
|
339
|
-
--
|
340
|
-
|
524
|
+
====
|
341
525
|
|
342
526
|
|
343
527
|
Moreover, the `keys` and `values` attributes can also be used in object enumerators.
|
344
528
|
|
345
529
|
|
346
|
-
|
347
|
-
|
530
|
+
[example]
|
531
|
+
====
|
348
532
|
Given:
|
349
533
|
|
350
534
|
object.yaml
|
@@ -358,7 +542,7 @@ desc: dolor sit amet
|
|
358
542
|
And the block:
|
359
543
|
[source,asciidoc]
|
360
544
|
------
|
361
|
-
[
|
545
|
+
[data2text,item=object.yaml]
|
362
546
|
----
|
363
547
|
.{{item.values[1]}}
|
364
548
|
[%noheader,cols="h,1"]
|
@@ -389,17 +573,17 @@ Will render as:
|
|
389
573
|
| desc | dolor sit amet
|
390
574
|
|===
|
391
575
|
----
|
576
|
+
====
|
392
577
|
|
393
|
-
|
394
|
-
|
395
|
-
There are several optional arguments to the for tag that can influence which items you receive in your loop and what order they appear in:
|
578
|
+
There are several optional arguments to the `for` tag that can influence which
|
579
|
+
items you receive in your loop and what order they appear in:
|
396
580
|
|
397
581
|
* limit:<INTEGER> lets you restrict how many items you get.
|
398
582
|
* offset:<INTEGER> lets you start the collection with the nth item.
|
399
583
|
* reversed iterates over the collection from last to first.
|
400
584
|
|
401
|
-
|
402
|
-
|
585
|
+
[example]
|
586
|
+
====
|
403
587
|
Given:
|
404
588
|
|
405
589
|
strings.yaml
|
@@ -416,7 +600,7 @@ strings.yaml
|
|
416
600
|
And the block:
|
417
601
|
[source,asciidoc]
|
418
602
|
------
|
419
|
-
[
|
603
|
+
[data2text,items=strings.yaml]
|
420
604
|
----
|
421
605
|
{% for elem in items limit:2 offset:2 %}
|
422
606
|
{{item}}
|
@@ -436,21 +620,26 @@ Will render as:
|
|
436
620
|
----
|
437
621
|
dolor sit
|
438
622
|
----
|
439
|
-
|
440
|
-
--
|
623
|
+
====
|
441
624
|
|
442
625
|
|
443
|
-
== Advanced
|
626
|
+
== Advanced usage
|
444
627
|
|
445
|
-
|
628
|
+
=== General
|
446
629
|
|
630
|
+
The `data2text` block supports a variety of advanced features, including:
|
447
631
|
|
632
|
+
* array of objects
|
633
|
+
* array of arrays
|
634
|
+
* nested loading of data file paths
|
635
|
+
* interpolated file names
|
636
|
+
* multiple contexts
|
637
|
+
* multiple contexts with mixed file formats
|
448
638
|
|
449
639
|
=== Array of objects
|
450
640
|
|
451
|
-
|
452
|
-
|
453
|
-
--
|
641
|
+
[example]
|
642
|
+
====
|
454
643
|
Given:
|
455
644
|
|
456
645
|
array_of_objects.yaml
|
@@ -471,7 +660,7 @@ array_of_objects.yaml
|
|
471
660
|
And the block:
|
472
661
|
[source,asciidoc]
|
473
662
|
------
|
474
|
-
[
|
663
|
+
[data2text,ar=array_of_objects.yaml]
|
475
664
|
----
|
476
665
|
{% for item in ar %}
|
477
666
|
|
@@ -504,16 +693,16 @@ amet:: lorem
|
|
504
693
|
- amet: 4
|
505
694
|
- amet: 6
|
506
695
|
----
|
507
|
-
|
508
|
-
--
|
696
|
+
====
|
509
697
|
|
510
698
|
|
511
|
-
===
|
699
|
+
=== Interpolated file names
|
512
700
|
|
513
|
-
`
|
701
|
+
`data2text` blocks can be used for pre-processing document elements for AsciiDoc
|
702
|
+
consumption.
|
514
703
|
|
515
|
-
|
516
|
-
|
704
|
+
[example]
|
705
|
+
====
|
517
706
|
Given:
|
518
707
|
|
519
708
|
strings.yaml
|
@@ -528,9 +717,10 @@ items:
|
|
528
717
|
----
|
529
718
|
|
530
719
|
And the block:
|
720
|
+
|
531
721
|
[source,asciidoc]
|
532
722
|
--------
|
533
|
-
[
|
723
|
+
[data2text,yaml=strings.yaml]
|
534
724
|
------
|
535
725
|
First item is {{yaml.items.first}}.
|
536
726
|
Last item is {{yaml.items.last}}.
|
@@ -574,18 +764,19 @@ Last item is dolor.
|
|
574
764
|
----
|
575
765
|
\include::doc-2.rb[]
|
576
766
|
----
|
577
|
-
|
578
767
|
------
|
579
768
|
|
580
|
-
|
769
|
+
This block instructs Metanorma to include the file `doc-0.rb`, `doc-1.rb`, and
|
770
|
+
`doc-2.rb` in the resulting document.
|
771
|
+
====
|
581
772
|
|
582
773
|
|
583
774
|
=== Multiple contexts
|
584
775
|
|
585
776
|
Multiple contexts can be defined in a single block.
|
586
777
|
|
587
|
-
|
588
|
-
|
778
|
+
[example]
|
779
|
+
====
|
589
780
|
Given:
|
590
781
|
|
591
782
|
strings1.yaml
|
@@ -608,13 +799,12 @@ shape: square
|
|
608
799
|
And the block:
|
609
800
|
[source,asciidoc]
|
610
801
|
------
|
611
|
-
[
|
802
|
+
[data2text,data1=data=strings1.yaml2=strings2.yaml]
|
612
803
|
----
|
613
804
|
I'm heading to the {{data1.foo}} for {{data1.dead}}.
|
614
805
|
|
615
806
|
This is hello {{data2.hello}}.
|
616
807
|
The color is {{data2.color}} and the shape is {{data2.shape}}.
|
617
|
-
|
618
808
|
----
|
619
809
|
------
|
620
810
|
|
@@ -632,20 +822,21 @@ I'm heading to the bar for beef.
|
|
632
822
|
This is hello world.
|
633
823
|
The color is red and the shape is square.
|
634
824
|
----
|
825
|
+
====
|
635
826
|
|
636
|
-
--
|
637
827
|
|
828
|
+
=== Multiple contexts with mixed file formats
|
638
829
|
|
639
|
-
|
830
|
+
When the file formats are mixed, use the `data2text` block to load multiple
|
831
|
+
files of different formats.
|
640
832
|
|
641
|
-
|
642
|
-
`data2text`.
|
833
|
+
NOTE: The file format is determined by the file extension of the file path.
|
643
834
|
|
644
|
-
|
645
|
-
|
835
|
+
[example]
|
836
|
+
====
|
646
837
|
Given:
|
647
838
|
|
648
|
-
strings1.json
|
839
|
+
`strings1.json`
|
649
840
|
[source,json]
|
650
841
|
----
|
651
842
|
{
|
@@ -654,7 +845,7 @@ strings1.json
|
|
654
845
|
}
|
655
846
|
----
|
656
847
|
|
657
|
-
strings2.yaml
|
848
|
+
`strings2.yaml`
|
658
849
|
[source,yaml]
|
659
850
|
----
|
660
851
|
---
|
@@ -672,7 +863,6 @@ I'm heading to the {{my_json.foo}} for {{my_json.dead}}.
|
|
672
863
|
|
673
864
|
This is hello {{my_yaml.hello}}.
|
674
865
|
The color is {{my_yaml.color}} and the shape is {{my_yaml.shape}}.
|
675
|
-
|
676
866
|
----
|
677
867
|
------
|
678
868
|
|
@@ -690,21 +880,24 @@ I'm heading to the bar for beef.
|
|
690
880
|
This is hello world.
|
691
881
|
The color is red and the shape is square.
|
692
882
|
----
|
883
|
+
====
|
693
884
|
|
694
|
-
--
|
695
885
|
|
886
|
+
=== Nested loading of data file paths
|
696
887
|
|
697
|
-
|
888
|
+
There are cases where the data file paths are not known in advance or are
|
889
|
+
provided via a variable. In such cases, you can use the Metanorma-specific
|
890
|
+
`load_file` filter to load the data file paths dynamically.
|
698
891
|
|
699
|
-
|
700
|
-
|
701
|
-
|
892
|
+
This is useful when the data file paths are provided as part of the data
|
893
|
+
structure itself or when you want to load data files based on certain
|
894
|
+
conditions.
|
702
895
|
|
703
|
-
|
704
|
-
|
896
|
+
[example]
|
897
|
+
====
|
705
898
|
Given:
|
706
899
|
|
707
|
-
strings1.json
|
900
|
+
`strings1.json`
|
708
901
|
[source,json]
|
709
902
|
----
|
710
903
|
{
|
@@ -717,7 +910,7 @@ Where:
|
|
717
910
|
|
718
911
|
* `paths` is an array of filepaths relative to the Metanorma document
|
719
912
|
|
720
|
-
a.yaml
|
913
|
+
`a.yaml`
|
721
914
|
[source,yaml]
|
722
915
|
----
|
723
916
|
---
|
@@ -725,7 +918,7 @@ shape: circle
|
|
725
918
|
color: red
|
726
919
|
----
|
727
920
|
|
728
|
-
b.yaml
|
921
|
+
`b.yaml`
|
729
922
|
[source,yaml]
|
730
923
|
----
|
731
924
|
---
|
@@ -742,15 +935,15 @@ And the block:
|
|
742
935
|
I'm heading to the {{my_context.foo}}.
|
743
936
|
|
744
937
|
{% for path in my_context.paths %}
|
745
|
-
{% assign
|
746
|
-
This is {{
|
938
|
+
{% assign data = path | load_file %}
|
939
|
+
This is {{ data.shape }} with color {{ data.color }}.
|
747
940
|
{% endfor %}
|
748
941
|
----
|
749
942
|
------
|
750
943
|
|
751
944
|
Where:
|
752
945
|
|
753
|
-
* load_file is a liquid filter that loads the file content
|
946
|
+
* `load_file` is a liquid filter that loads the file content
|
754
947
|
|
755
948
|
Will render as:
|
756
949
|
[source,asciidoc]
|
@@ -760,5 +953,12 @@ I'm heading to the bar.
|
|
760
953
|
This is circle with color red.
|
761
954
|
This is square with color blue.
|
762
955
|
----
|
956
|
+
====
|
957
|
+
|
958
|
+
|
959
|
+
== Copyright and license
|
960
|
+
|
961
|
+
Copyright Ribose.
|
962
|
+
|
963
|
+
Licensed under the MIT License.
|
763
964
|
|
764
|
-
--
|
@@ -3,15 +3,11 @@
|
|
3
3
|
require "liquid"
|
4
4
|
require "asciidoctor"
|
5
5
|
require "asciidoctor/reader"
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
Liquid::Environment.default
|
13
|
-
.register_tag("keyiterator", Liquid::CustomBlocks::KeyIterator)
|
14
|
-
Liquid::Environment.default.register_filter(Liquid::CustomFilters)
|
6
|
+
require_relative "liquid/custom_blocks/key_iterator"
|
7
|
+
require_relative "liquid/custom_filters/values"
|
8
|
+
require_relative "liquid/custom_filters/replace_regex"
|
9
|
+
require_relative "liquid/custom_filters/loadfile"
|
10
|
+
require_relative "source_extractor"
|
15
11
|
|
16
12
|
module Asciidoctor
|
17
13
|
class PreprocessorNoIfdefsReader < PreprocessorReader
|
@@ -187,17 +183,33 @@ module Metanorma
|
|
187
183
|
end
|
188
184
|
|
189
185
|
def render_liquid_string(template_string:, contexts:, document:)
|
190
|
-
liquid_template = Liquid::Template
|
186
|
+
liquid_template = ::Liquid::Template
|
187
|
+
.parse(template_string, environment: create_liquid_environment)
|
188
|
+
|
191
189
|
# Allow includes for the template
|
192
190
|
liquid_template.registers[:file_system] =
|
193
191
|
::Liquid::LocalFileSystem.new(relative_file_path(document, ""))
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
192
|
+
|
193
|
+
rendered_string = liquid_template.render(
|
194
|
+
contexts,
|
195
|
+
strict_variables: false,
|
196
|
+
error_mode: :warn,
|
197
|
+
)
|
198
198
|
[rendered_string, liquid_template.errors]
|
199
199
|
end
|
200
200
|
|
201
|
+
def create_liquid_environment
|
202
|
+
::Liquid::Environment.new.tap do |liquid_env|
|
203
|
+
liquid_env.register_tag(
|
204
|
+
"keyiterator",
|
205
|
+
::Metanorma::Plugin::Datastruct::Liquid::CustomBlocks::KeyIterator,
|
206
|
+
)
|
207
|
+
liquid_env.register_filter(
|
208
|
+
::Metanorma::Plugin::Datastruct::Liquid::CustomFilters,
|
209
|
+
)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
201
213
|
def notify_render_errors(document, errors)
|
202
214
|
errors.each do |error_obj|
|
203
215
|
document
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Metanorma
|
2
|
+
module Plugin
|
3
|
+
module Datastruct
|
4
|
+
module Liquid
|
5
|
+
module CustomBlocks
|
6
|
+
class KeyIterator < ::Liquid::Block
|
7
|
+
def initialize(tag_name, markup, tokens)
|
8
|
+
super
|
9
|
+
@context_name, @var_name = markup.split(",").map(&:strip)
|
10
|
+
end
|
11
|
+
|
12
|
+
def render(context) # rubocop:disable Metrics/MethodLength
|
13
|
+
res = ""
|
14
|
+
iterator = if context[@context_name].is_a?(Hash)
|
15
|
+
context[@context_name].keys
|
16
|
+
else
|
17
|
+
context[@context_name]
|
18
|
+
end
|
19
|
+
iterator.each.with_index do |key, index|
|
20
|
+
context["index"] = index
|
21
|
+
context[@var_name] = key
|
22
|
+
res += super
|
23
|
+
end
|
24
|
+
res
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative "../../content"
|
2
|
+
|
3
|
+
module Metanorma
|
4
|
+
module Plugin
|
5
|
+
module Datastruct
|
6
|
+
module Liquid
|
7
|
+
module CustomFilters
|
8
|
+
include ::Metanorma::Plugin::Datastruct::Content
|
9
|
+
|
10
|
+
def loadfile(path, parent_folder)
|
11
|
+
resolved_file_path = File.expand_path(path, parent_folder)
|
12
|
+
load_content_from_file(resolved_file_path)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Metanorma
|
2
|
+
module Plugin
|
3
|
+
module Datastruct
|
4
|
+
module Liquid
|
5
|
+
module CustomFilters
|
6
|
+
def replace_regex(text, regex_search, replace_value)
|
7
|
+
regex = /#{regex_search}/
|
8
|
+
text.to_s.gsub(regex, replace_value)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: metanorma-plugin-datastruct
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
@@ -254,15 +254,15 @@ files:
|
|
254
254
|
- Rakefile
|
255
255
|
- bin/console
|
256
256
|
- bin/setup
|
257
|
-
- lib/liquid/custom_blocks/key_iterator.rb
|
258
|
-
- lib/liquid/custom_filters/loadfile.rb
|
259
|
-
- lib/liquid/custom_filters/replace_regex.rb
|
260
|
-
- lib/liquid/custom_filters/values.rb
|
261
257
|
- lib/metanorma-plugin-datastruct.rb
|
262
258
|
- lib/metanorma/plugin/datastruct/base_structured_text_preprocessor.rb
|
263
259
|
- lib/metanorma/plugin/datastruct/content.rb
|
264
260
|
- lib/metanorma/plugin/datastruct/data2_text_preprocessor.rb
|
265
261
|
- lib/metanorma/plugin/datastruct/json2_text_preprocessor.rb
|
262
|
+
- lib/metanorma/plugin/datastruct/liquid/custom_blocks/key_iterator.rb
|
263
|
+
- lib/metanorma/plugin/datastruct/liquid/custom_filters/loadfile.rb
|
264
|
+
- lib/metanorma/plugin/datastruct/liquid/custom_filters/replace_regex.rb
|
265
|
+
- lib/metanorma/plugin/datastruct/liquid/custom_filters/values.rb
|
266
266
|
- lib/metanorma/plugin/datastruct/source_extractor.rb
|
267
267
|
- lib/metanorma/plugin/datastruct/version.rb
|
268
268
|
- lib/metanorma/plugin/datastruct/yaml2_text_preprocessor.rb
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module Liquid
|
2
|
-
module CustomBlocks
|
3
|
-
class KeyIterator < Block
|
4
|
-
def initialize(tag_name, markup, tokens)
|
5
|
-
super
|
6
|
-
@context_name, @var_name = markup.split(",").map(&:strip)
|
7
|
-
end
|
8
|
-
|
9
|
-
def render(context) # rubocop:disable Metrics/MethodLength
|
10
|
-
res = ""
|
11
|
-
iterator = if context[@context_name].is_a?(Hash)
|
12
|
-
context[@context_name].keys
|
13
|
-
else
|
14
|
-
context[@context_name]
|
15
|
-
end
|
16
|
-
iterator.each.with_index do |key, index|
|
17
|
-
context["index"] = index
|
18
|
-
context[@var_name] = key
|
19
|
-
res += super
|
20
|
-
end
|
21
|
-
res
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,12 +0,0 @@
|
|
1
|
-
require "metanorma/plugin/datastruct/content"
|
2
|
-
|
3
|
-
module Liquid
|
4
|
-
module CustomFilters
|
5
|
-
include ::Metanorma::Plugin::Datastruct::Content
|
6
|
-
|
7
|
-
def loadfile(path, parent_folder)
|
8
|
-
resolved_file_path = File.expand_path(path, parent_folder)
|
9
|
-
load_content_from_file(resolved_file_path)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|