expressir 2.1.30 → 2.1.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/.github/workflows/docs.yml +98 -0
- data/.github/workflows/links.yml +100 -0
- data/.github/workflows/rake.yml +4 -0
- data/.github/workflows/release.yml +5 -0
- data/.github/workflows/validate_schemas.yml +1 -1
- data/.gitignore +3 -0
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +244 -39
- data/Gemfile +2 -1
- data/README.adoc +621 -54
- data/docs/Gemfile +12 -0
- data/docs/_config.yml +141 -0
- data/docs/_guides/changes/changes-format.adoc +778 -0
- data/docs/_guides/changes/importing-eengine.adoc +898 -0
- data/docs/_guides/changes/index.adoc +396 -0
- data/docs/_guides/changes/programmatic-usage.adoc +1038 -0
- data/docs/_guides/changes/validating-changes.adoc +681 -0
- data/docs/_guides/cli/benchmark-performance.adoc +834 -0
- data/docs/_guides/cli/coverage-analysis.adoc +921 -0
- data/docs/_guides/cli/format-schemas.adoc +547 -0
- data/docs/_guides/cli/index.adoc +8 -0
- data/docs/_guides/cli/managing-changes.adoc +927 -0
- data/docs/_guides/cli/validate-ascii.adoc +645 -0
- data/docs/_guides/cli/validate-schemas.adoc +534 -0
- data/docs/_guides/index.adoc +165 -0
- data/docs/_guides/ler/creating-packages.adoc +664 -0
- data/docs/_guides/ler/index.adoc +305 -0
- data/docs/_guides/ler/loading-packages.adoc +707 -0
- data/docs/_guides/ler/package-formats.adoc +748 -0
- data/docs/_guides/ler/querying-packages.adoc +826 -0
- data/docs/_guides/ler/validating-packages.adoc +750 -0
- data/docs/_guides/liquid/basic-templates.adoc +813 -0
- data/docs/_guides/liquid/documentation-generation.adoc +1042 -0
- data/docs/_guides/liquid/drops-reference.adoc +829 -0
- data/docs/_guides/liquid/filters-and-tags.adoc +912 -0
- data/docs/_guides/liquid/index.adoc +468 -0
- data/docs/_guides/manifests/creating-manifests.adoc +483 -0
- data/docs/_guides/manifests/index.adoc +307 -0
- data/docs/_guides/manifests/resolving-manifests.adoc +557 -0
- data/docs/_guides/manifests/validating-manifests.adoc +713 -0
- data/docs/_guides/ruby-api/formatting-schemas.adoc +605 -0
- data/docs/_guides/ruby-api/index.adoc +257 -0
- data/docs/_guides/ruby-api/parsing-files.adoc +421 -0
- data/docs/_guides/ruby-api/search-engine.adoc +609 -0
- data/docs/_guides/ruby-api/working-with-repository.adoc +577 -0
- data/docs/_pages/data-model.adoc +665 -0
- data/docs/_pages/express-language.adoc +506 -0
- data/docs/_pages/getting-started.adoc +414 -0
- data/docs/_pages/index.adoc +116 -0
- data/docs/_pages/introduction.adoc +256 -0
- data/docs/_pages/ler-packages.adoc +837 -0
- data/docs/_pages/parsers.adoc +683 -0
- data/docs/_pages/schema-manifests.adoc +431 -0
- data/docs/_references/index.adoc +228 -0
- data/docs/_tutorials/creating-ler-package.adoc +735 -0
- data/docs/_tutorials/documentation-coverage.adoc +795 -0
- data/docs/_tutorials/index.adoc +221 -0
- data/docs/_tutorials/liquid-templates.adoc +806 -0
- data/docs/_tutorials/parsing-your-first-schema.adoc +522 -0
- data/docs/_tutorials/querying-schemas.adoc +751 -0
- data/docs/_tutorials/working-with-multiple-schemas.adoc +676 -0
- data/docs/index.adoc +242 -0
- data/docs/lychee.toml +84 -0
- data/examples/demo_ler_usage.sh +86 -0
- data/examples/ler/README.md +111 -0
- data/examples/ler/simple_example.ler +0 -0
- data/examples/ler/simple_schema.exp +33 -0
- data/examples/ler_build.rb +75 -0
- data/examples/ler_cli.rb +79 -0
- data/examples/ler_demo_complete.rb +276 -0
- data/examples/ler_query.rb +91 -0
- data/examples/ler_query_examples.rb +305 -0
- data/examples/ler_stats.rb +81 -0
- data/examples/phase3_demo.rb +159 -0
- data/examples/query_demo_simple.rb +131 -0
- data/expressir.gemspec +2 -0
- data/lib/expressir/cli.rb +12 -4
- data/lib/expressir/commands/manifest.rb +427 -0
- data/lib/expressir/commands/package.rb +1274 -0
- data/lib/expressir/commands/validate.rb +70 -37
- data/lib/expressir/commands/validate_ascii.rb +607 -0
- data/lib/expressir/commands/validate_load.rb +88 -0
- data/lib/expressir/express/formatter.rb +5 -1
- data/lib/expressir/express/formatters/remark_item_formatter.rb +25 -0
- data/lib/expressir/express/parser.rb +33 -0
- data/lib/expressir/manifest/resolver.rb +213 -0
- data/lib/expressir/manifest/validator.rb +195 -0
- data/lib/expressir/model/declarations/entity.rb +6 -0
- data/lib/expressir/model/dependency_resolver.rb +270 -0
- data/lib/expressir/model/indexes/entity_index.rb +103 -0
- data/lib/expressir/model/indexes/reference_index.rb +148 -0
- data/lib/expressir/model/indexes/type_index.rb +149 -0
- data/lib/expressir/model/interface_validator.rb +384 -0
- data/lib/expressir/model/repository.rb +400 -5
- data/lib/expressir/model/repository_validator.rb +295 -0
- data/lib/expressir/model/search_engine.rb +525 -0
- data/lib/expressir/model.rb +4 -94
- data/lib/expressir/package/builder.rb +200 -0
- data/lib/expressir/package/metadata.rb +81 -0
- data/lib/expressir/package/reader.rb +165 -0
- data/lib/expressir/schema_manifest.rb +11 -1
- data/lib/expressir/version.rb +1 -1
- data/lib/expressir.rb +15 -2
- metadata +114 -4
- data/docs/benchmarking.adoc +0 -107
- data/docs/liquid_drops.adoc +0 -1547
|
@@ -0,0 +1,813 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Basic Templates
|
|
3
|
+
parent: Liquid
|
|
4
|
+
grand_parent: Guides
|
|
5
|
+
nav_order: 1
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
= Basic Liquid templates
|
|
9
|
+
|
|
10
|
+
== Purpose
|
|
11
|
+
|
|
12
|
+
This guide covers Liquid template fundamentals including syntax,
|
|
13
|
+
variables, control flow, loops, and template organization. Master these
|
|
14
|
+
basics to create effective documentation templates for EXPRESS schemas.
|
|
15
|
+
|
|
16
|
+
== References
|
|
17
|
+
|
|
18
|
+
* link:index.html[Liquid Overview] - Integration fundamentals
|
|
19
|
+
* link:drops-reference.html[Drops Reference] - Available data objects
|
|
20
|
+
* link:filters-and-tags.html[Filters and Tags] - Built-in operations
|
|
21
|
+
* https://shopify.github.io/liquid/basics/introduction/[Liquid Basics] -
|
|
22
|
+
Official introduction
|
|
23
|
+
|
|
24
|
+
== Concepts
|
|
25
|
+
|
|
26
|
+
Object:: A piece of data that Liquid can output, accessed with `{{}}`.
|
|
27
|
+
|
|
28
|
+
Tag:: Logic and control flow elements that use `{%%}` delimiters.
|
|
29
|
+
|
|
30
|
+
Filter:: A function that transforms values, applied with the `|`
|
|
31
|
+
operator.
|
|
32
|
+
|
|
33
|
+
Variable:: A named reference to data, either from input or created with
|
|
34
|
+
`assign`.
|
|
35
|
+
|
|
36
|
+
Whitespace control:: Techniques to manage blank lines and spacing in
|
|
37
|
+
output.
|
|
38
|
+
|
|
39
|
+
== Template structure
|
|
40
|
+
|
|
41
|
+
A Liquid template is a text file containing:
|
|
42
|
+
|
|
43
|
+
* **Static content**: Output as-is
|
|
44
|
+
* **Output tags**: `{{ }}` to display data
|
|
45
|
+
* **Logic tags**: `{% %}` for control flow
|
|
46
|
+
* **Filters**: Transform output values
|
|
47
|
+
* **Comments**: Documentation within templates
|
|
48
|
+
|
|
49
|
+
.Basic template anatomy
|
|
50
|
+
[example]
|
|
51
|
+
====
|
|
52
|
+
[source,liquid]
|
|
53
|
+
----
|
|
54
|
+
# {{ schema.id }} Documentation <1>
|
|
55
|
+
|
|
56
|
+
{% comment %}This is a comment{% endcomment %} <2>
|
|
57
|
+
|
|
58
|
+
{% if schema.version %} <3>
|
|
59
|
+
**Version**: {{ schema.version.value }} <4>
|
|
60
|
+
{% endif %}
|
|
61
|
+
|
|
62
|
+
Entities: {{ schema.entities | size }} <5>
|
|
63
|
+
|
|
64
|
+
{% for entity in schema.entities %} <6>
|
|
65
|
+
- {{ entity.id }}
|
|
66
|
+
{% endfor %}
|
|
67
|
+
----
|
|
68
|
+
<1> Static text with output tag
|
|
69
|
+
<2> Comment (not included in output)
|
|
70
|
+
<3> Conditional logic tag
|
|
71
|
+
<4> Nested output with data access
|
|
72
|
+
<5> Output with filter
|
|
73
|
+
<6> Loop tag
|
|
74
|
+
====
|
|
75
|
+
|
|
76
|
+
== Variables and output
|
|
77
|
+
|
|
78
|
+
=== Output tags
|
|
79
|
+
|
|
80
|
+
Use `{{ }}` to output data:
|
|
81
|
+
|
|
82
|
+
[source,liquid]
|
|
83
|
+
----
|
|
84
|
+
{{ schema.id }}
|
|
85
|
+
{{ entity.attributes.size }}
|
|
86
|
+
{{ attr.type }}
|
|
87
|
+
----
|
|
88
|
+
|
|
89
|
+
=== Dot notation
|
|
90
|
+
|
|
91
|
+
Access nested attributes with dots:
|
|
92
|
+
|
|
93
|
+
[source,liquid]
|
|
94
|
+
----
|
|
95
|
+
{{ repository.schemas.first.id }}
|
|
96
|
+
{{ entity.parent.id }}
|
|
97
|
+
{{ schema.version.value }}
|
|
98
|
+
----
|
|
99
|
+
|
|
100
|
+
=== Array access
|
|
101
|
+
|
|
102
|
+
Access array elements by index or use filters:
|
|
103
|
+
|
|
104
|
+
[source,liquid]
|
|
105
|
+
----
|
|
106
|
+
{{ schema.entities[0].id }}
|
|
107
|
+
{{ schema.entities.first.id }}
|
|
108
|
+
{{ schema.entities.last.id }}
|
|
109
|
+
{{ schema.entities | map: "id" }}
|
|
110
|
+
----
|
|
111
|
+
|
|
112
|
+
.Complete example accessing schema data
|
|
113
|
+
[example]
|
|
114
|
+
====
|
|
115
|
+
[source,liquid]
|
|
116
|
+
----
|
|
117
|
+
Schema: {{ schema.id }}
|
|
118
|
+
File: {{ schema.file }}
|
|
119
|
+
|
|
120
|
+
First entity: {{ schema.entities.first.id }}
|
|
121
|
+
Last entity: {{ schema.entities.last.id }}
|
|
122
|
+
Total entities: {{ schema.entities.size }}
|
|
123
|
+
----
|
|
124
|
+
|
|
125
|
+
Given a schema with entities `person` and `company`:
|
|
126
|
+
|
|
127
|
+
[source]
|
|
128
|
+
----
|
|
129
|
+
Schema: example_schema
|
|
130
|
+
File: schemas/example_schema.exp
|
|
131
|
+
|
|
132
|
+
First entity: person
|
|
133
|
+
Last entity: company
|
|
134
|
+
Total entities: 2
|
|
135
|
+
----
|
|
136
|
+
====
|
|
137
|
+
|
|
138
|
+
== Variable assignment
|
|
139
|
+
|
|
140
|
+
Create your own variables with `assign`:
|
|
141
|
+
|
|
142
|
+
[source,liquid]
|
|
143
|
+
----
|
|
144
|
+
{% assign total = schema.entities.size %}
|
|
145
|
+
{% assign has_types = schema.types.size > 0 %}
|
|
146
|
+
{% assign first_entity = schema.entities.first %}
|
|
147
|
+
|
|
148
|
+
Total entities: {{ total }}
|
|
149
|
+
Has types: {{ has_types }}
|
|
150
|
+
First: {{ first_entity.id }}
|
|
151
|
+
----
|
|
152
|
+
|
|
153
|
+
Variables persist within the template scope:
|
|
154
|
+
|
|
155
|
+
[source,liquid]
|
|
156
|
+
----
|
|
157
|
+
{% assign count = 0 %}
|
|
158
|
+
|
|
159
|
+
{% for entity in schema.entities %}
|
|
160
|
+
{% assign count = count | plus: 1 %}
|
|
161
|
+
{% endfor %}
|
|
162
|
+
|
|
163
|
+
Processed {{ count }} entities
|
|
164
|
+
----
|
|
165
|
+
|
|
166
|
+
== Control flow
|
|
167
|
+
|
|
168
|
+
=== If statements
|
|
169
|
+
|
|
170
|
+
Conditional logic with `if`:
|
|
171
|
+
|
|
172
|
+
[source,liquid]
|
|
173
|
+
----
|
|
174
|
+
{% if entity.abstract %}
|
|
175
|
+
**Abstract Entity** - Cannot be instantiated directly.
|
|
176
|
+
{% endif %}
|
|
177
|
+
|
|
178
|
+
{% if entity.attributes.size > 0 %}
|
|
179
|
+
This entity has attributes.
|
|
180
|
+
{% endif %}
|
|
181
|
+
----
|
|
182
|
+
|
|
183
|
+
=== If-else statements
|
|
184
|
+
|
|
185
|
+
[source,liquid]
|
|
186
|
+
----
|
|
187
|
+
{% if entity.remarks.size > 0 %}
|
|
188
|
+
## Description
|
|
189
|
+
{{ entity.remarks | join: "\n" }}
|
|
190
|
+
{% else %}
|
|
191
|
+
No description available.
|
|
192
|
+
{% endif %}
|
|
193
|
+
----
|
|
194
|
+
|
|
195
|
+
=== Elsif for multiple conditions
|
|
196
|
+
|
|
197
|
+
[source,liquid]
|
|
198
|
+
----
|
|
199
|
+
{% if entity.attributes.size > 10 %}
|
|
200
|
+
Complex entity with many attributes.
|
|
201
|
+
{% elsif entity.attributes.size > 5 %}
|
|
202
|
+
Medium complexity entity.
|
|
203
|
+
{% elsif entity.attributes.size > 0 %}
|
|
204
|
+
Simple entity.
|
|
205
|
+
{% else %}
|
|
206
|
+
Entity without attributes.
|
|
207
|
+
{% endif %}
|
|
208
|
+
----
|
|
209
|
+
|
|
210
|
+
=== Unless (negative condition)
|
|
211
|
+
|
|
212
|
+
`unless` is the opposite of `if`:
|
|
213
|
+
|
|
214
|
+
[source,liquid]
|
|
215
|
+
----
|
|
216
|
+
{% unless entity.abstract %}
|
|
217
|
+
Can be instantiated.
|
|
218
|
+
{% endunless %}
|
|
219
|
+
|
|
220
|
+
{% comment %}Equivalent to:{% endcomment %}
|
|
221
|
+
{% if entity.abstract == false %}
|
|
222
|
+
Can be instantiated.
|
|
223
|
+
{% endif %}
|
|
224
|
+
----
|
|
225
|
+
|
|
226
|
+
=== Case statements
|
|
227
|
+
|
|
228
|
+
Use `case` for multiple value checks:
|
|
229
|
+
|
|
230
|
+
[source,liquid]
|
|
231
|
+
----
|
|
232
|
+
{% case entity.attributes.size %}
|
|
233
|
+
{% when 0 %}
|
|
234
|
+
No attributes
|
|
235
|
+
{% when 1 %}
|
|
236
|
+
One attribute
|
|
237
|
+
{% when 2 %}
|
|
238
|
+
Two attributes
|
|
239
|
+
{% else %}
|
|
240
|
+
{{ entity.attributes.size }} attributes
|
|
241
|
+
{% endcase %}
|
|
242
|
+
----
|
|
243
|
+
|
|
244
|
+
.Complete example with control flow
|
|
245
|
+
[example]
|
|
246
|
+
====
|
|
247
|
+
[source,liquid]
|
|
248
|
+
----
|
|
249
|
+
{% for entity in schema.entities %}
|
|
250
|
+
## {{ entity.id }}
|
|
251
|
+
|
|
252
|
+
{% if entity.abstract %}
|
|
253
|
+
_Abstract entity_
|
|
254
|
+
{% endif %}
|
|
255
|
+
|
|
256
|
+
{% if entity.remarks.size > 0 %}
|
|
257
|
+
{{ entity.remarks | join: " " }}
|
|
258
|
+
{% else %}
|
|
259
|
+
No documentation available.
|
|
260
|
+
{% endif %}
|
|
261
|
+
|
|
262
|
+
{% case entity.attributes.size %}
|
|
263
|
+
{% when 0 %}
|
|
264
|
+
No attributes defined.
|
|
265
|
+
{% when 1 %}
|
|
266
|
+
Has one attribute.
|
|
267
|
+
{% else %}
|
|
268
|
+
Has {{ entity.attributes.size }} attributes.
|
|
269
|
+
{% endcase %}
|
|
270
|
+
|
|
271
|
+
{% endfor %}
|
|
272
|
+
----
|
|
273
|
+
====
|
|
274
|
+
|
|
275
|
+
== Comparison operators
|
|
276
|
+
|
|
277
|
+
Use these operators in conditions:
|
|
278
|
+
|
|
279
|
+
`==`:: Equal to
|
|
280
|
+
`!=`:: Not equal to
|
|
281
|
+
`>`:: Greater than
|
|
282
|
+
`<`:: Less than
|
|
283
|
+
`>=`:: Greater than or equal to
|
|
284
|
+
`<=`:: Less than or equal to
|
|
285
|
+
|
|
286
|
+
[source,liquid]
|
|
287
|
+
----
|
|
288
|
+
{% if entity.attributes.size == 0 %}
|
|
289
|
+
{% if entity.attributes.size != 0 %}
|
|
290
|
+
{% if entity.attributes.size > 5 %}
|
|
291
|
+
{% if entity.attributes.size >= 10 %}
|
|
292
|
+
----
|
|
293
|
+
|
|
294
|
+
== Logical operators
|
|
295
|
+
|
|
296
|
+
Combine conditions with logical operators:
|
|
297
|
+
|
|
298
|
+
`and`:: Both conditions must be true
|
|
299
|
+
`or`:: At least one condition must be true
|
|
300
|
+
`contains`:: Check if string/array contains value
|
|
301
|
+
|
|
302
|
+
[source,liquid]
|
|
303
|
+
----
|
|
304
|
+
{% if entity.attributes.size > 0 and entity.where_rules.size > 0 %}
|
|
305
|
+
Entity has both attributes and constraints.
|
|
306
|
+
{% endif %}
|
|
307
|
+
|
|
308
|
+
{% if entity.abstract or entity.attributes.size == 0 %}
|
|
309
|
+
Abstract or empty entity.
|
|
310
|
+
{% endif %}
|
|
311
|
+
|
|
312
|
+
{% if entity.id contains "person" %}
|
|
313
|
+
Person-related entity.
|
|
314
|
+
{% endif %}
|
|
315
|
+
----
|
|
316
|
+
|
|
317
|
+
== Loops
|
|
318
|
+
|
|
319
|
+
=== For loops
|
|
320
|
+
|
|
321
|
+
Iterate over collections with `for`:
|
|
322
|
+
|
|
323
|
+
[source,liquid]
|
|
324
|
+
----
|
|
325
|
+
{% for entity in schema.entities %}
|
|
326
|
+
- {{ entity.id }}
|
|
327
|
+
{% endfor %}
|
|
328
|
+
----
|
|
329
|
+
|
|
330
|
+
=== Loop variables
|
|
331
|
+
|
|
332
|
+
Special variables available in loops:
|
|
333
|
+
|
|
334
|
+
`forloop.index`:: Current iteration (1-based)
|
|
335
|
+
`forloop.index0`:: Current iteration (0-based)
|
|
336
|
+
`forloop.first`:: True for first iteration
|
|
337
|
+
`forloop.last`:: True for last iteration
|
|
338
|
+
`forloop.length`:: Total iterations
|
|
339
|
+
|
|
340
|
+
[source,liquid]
|
|
341
|
+
----
|
|
342
|
+
{% for entity in schema.entities %}
|
|
343
|
+
{{ forloop.index }}. {{ entity.id }}
|
|
344
|
+
{% if forloop.first %}(first){% endif %}
|
|
345
|
+
{% if forloop.last %}(last){% endif %}
|
|
346
|
+
{% endfor %}
|
|
347
|
+
----
|
|
348
|
+
|
|
349
|
+
.Output example
|
|
350
|
+
[example]
|
|
351
|
+
====
|
|
352
|
+
[source]
|
|
353
|
+
----
|
|
354
|
+
1. person (first)
|
|
355
|
+
2. company (last)
|
|
356
|
+
----
|
|
357
|
+
====
|
|
358
|
+
|
|
359
|
+
=== Loop limits
|
|
360
|
+
|
|
361
|
+
Control iteration with `limit` and `offset`:
|
|
362
|
+
|
|
363
|
+
[source,liquid]
|
|
364
|
+
----
|
|
365
|
+
{% comment %}First 5 entities{% endcomment %}
|
|
366
|
+
{% for entity in schema.entities limit:5 %}
|
|
367
|
+
- {{ entity.id }}
|
|
368
|
+
{% endfor %}
|
|
369
|
+
|
|
370
|
+
{% comment %}Skip first 2, take next 3{% endcomment %}
|
|
371
|
+
{% for entity in schema.entities offset:2 limit:3 %}
|
|
372
|
+
- {{ entity.id }}
|
|
373
|
+
{% endfor %}
|
|
374
|
+
----
|
|
375
|
+
|
|
376
|
+
=== Range loops
|
|
377
|
+
|
|
378
|
+
Iterate over number ranges:
|
|
379
|
+
|
|
380
|
+
[source,liquid]
|
|
381
|
+
----
|
|
382
|
+
{% for i in (1..5) %}
|
|
383
|
+
{{ i }}
|
|
384
|
+
{% endfor %}
|
|
385
|
+
|
|
386
|
+
{% comment %}Output: 1 2 3 4 5{% endcomment %}
|
|
387
|
+
|
|
388
|
+
{% assign max = 10 %}
|
|
389
|
+
{% for i in (1..max) %}
|
|
390
|
+
Item {{ i }}
|
|
391
|
+
{% endfor %}
|
|
392
|
+
----
|
|
393
|
+
|
|
394
|
+
=== Reversed loops
|
|
395
|
+
|
|
396
|
+
Iterate in reverse order:
|
|
397
|
+
|
|
398
|
+
[source,liquid]
|
|
399
|
+
----
|
|
400
|
+
{% for entity in schema.entities reversed %}
|
|
401
|
+
- {{ entity.id }}
|
|
402
|
+
{% endfor %}
|
|
403
|
+
----
|
|
404
|
+
|
|
405
|
+
=== Break and continue
|
|
406
|
+
|
|
407
|
+
Control loop flow:
|
|
408
|
+
|
|
409
|
+
[source,liquid]
|
|
410
|
+
----
|
|
411
|
+
{% comment %}Stop after finding first abstract entity{% endcomment %}
|
|
412
|
+
{% for entity in schema.entities %}
|
|
413
|
+
{% if entity.abstract %}
|
|
414
|
+
Found: {{ entity.id }}
|
|
415
|
+
{% break %}
|
|
416
|
+
{% endif %}
|
|
417
|
+
{% endfor %}
|
|
418
|
+
|
|
419
|
+
{% comment %}Skip non-abstract entities{% endcomment %}
|
|
420
|
+
{% for entity in schema.entities %}
|
|
421
|
+
{% unless entity.abstract %}
|
|
422
|
+
{% continue %}
|
|
423
|
+
{% endunless %}
|
|
424
|
+
Abstract: {{ entity.id }}
|
|
425
|
+
{% endfor %}
|
|
426
|
+
----
|
|
427
|
+
|
|
428
|
+
=== Nested loops
|
|
429
|
+
|
|
430
|
+
Combine loops for hierarchical data:
|
|
431
|
+
|
|
432
|
+
[source,liquid]
|
|
433
|
+
----
|
|
434
|
+
{% for schema in repository.schemas %}
|
|
435
|
+
# {{ schema.id }}
|
|
436
|
+
|
|
437
|
+
{% for entity in schema.entities %}
|
|
438
|
+
## {{ entity.id }}
|
|
439
|
+
|
|
440
|
+
{% for attr in entity.attributes %}
|
|
441
|
+
- {{ attr.id }}: {{ attr.type }}
|
|
442
|
+
{% endfor %}
|
|
443
|
+
{% endfor %}
|
|
444
|
+
{% endfor %}
|
|
445
|
+
----
|
|
446
|
+
|
|
447
|
+
.Complete loop example with features
|
|
448
|
+
[example]
|
|
449
|
+
====
|
|
450
|
+
[source,liquid]
|
|
451
|
+
----
|
|
452
|
+
# Entity Listing
|
|
453
|
+
|
|
454
|
+
{% for entity in schema.entities %}
|
|
455
|
+
{{ forloop.index }}. **{{ entity.id }}**
|
|
456
|
+
{% if entity.abstract %}(Abstract){% endif %}
|
|
457
|
+
|
|
458
|
+
{% if entity.attributes.size > 0 %}
|
|
459
|
+
Attributes:
|
|
460
|
+
{% for attr in entity.attributes limit:3 %}
|
|
461
|
+
- {{ attr.id }}
|
|
462
|
+
{% if forloop.last and entity.attributes.size > 3 %}
|
|
463
|
+
- ... and {{ entity.attributes.size | minus: 3 }} more
|
|
464
|
+
{% endif %}
|
|
465
|
+
{% endfor %}
|
|
466
|
+
{% endif %}
|
|
467
|
+
|
|
468
|
+
{% unless forloop.last %}
|
|
469
|
+
---
|
|
470
|
+
{% endunless %}
|
|
471
|
+
{% endfor %}
|
|
472
|
+
----
|
|
473
|
+
====
|
|
474
|
+
|
|
475
|
+
== Comments
|
|
476
|
+
|
|
477
|
+
Add notes within templates:
|
|
478
|
+
|
|
479
|
+
[source,liquid]
|
|
480
|
+
----
|
|
481
|
+
{% comment %}
|
|
482
|
+
This template generates entity documentation.
|
|
483
|
+
Author: Team Name
|
|
484
|
+
Last updated: 2024-01-15
|
|
485
|
+
{% endcomment %}
|
|
486
|
+
|
|
487
|
+
{% comment %}TODO: Add where rules section{% endcomment %}
|
|
488
|
+
|
|
489
|
+
{% for entity in schema.entities %}
|
|
490
|
+
{% comment %}Process each entity{% endcomment %}
|
|
491
|
+
{{ entity.id }}
|
|
492
|
+
{% endfor %}
|
|
493
|
+
----
|
|
494
|
+
|
|
495
|
+
Single-line comments:
|
|
496
|
+
|
|
497
|
+
[source,liquid]
|
|
498
|
+
----
|
|
499
|
+
{% comment %}This is a single line comment{% endcomment %}
|
|
500
|
+
----
|
|
501
|
+
|
|
502
|
+
Multi-line comments:
|
|
503
|
+
|
|
504
|
+
[source,liquid]
|
|
505
|
+
----
|
|
506
|
+
{% comment %}
|
|
507
|
+
This is a longer comment
|
|
508
|
+
that spans multiple lines
|
|
509
|
+
for detailed explanations.
|
|
510
|
+
{% endcomment %}
|
|
511
|
+
----
|
|
512
|
+
|
|
513
|
+
== Whitespace control
|
|
514
|
+
|
|
515
|
+
Control spacing and blank lines in output.
|
|
516
|
+
|
|
517
|
+
=== Default behavior
|
|
518
|
+
|
|
519
|
+
Liquid preserves whitespace:
|
|
520
|
+
|
|
521
|
+
[source,liquid]
|
|
522
|
+
----
|
|
523
|
+
{% for entity in schema.entities %}
|
|
524
|
+
{{ entity.id }}
|
|
525
|
+
{% endfor %}
|
|
526
|
+
----
|
|
527
|
+
|
|
528
|
+
Creates blank lines from the loop tags.
|
|
529
|
+
|
|
530
|
+
=== Hyphen for whitespace stripping
|
|
531
|
+
|
|
532
|
+
Add `-` to strip whitespace:
|
|
533
|
+
|
|
534
|
+
[source,liquid]
|
|
535
|
+
----
|
|
536
|
+
{%- for entity in schema.entities -%}
|
|
537
|
+
{{ entity.id }}
|
|
538
|
+
{%- endfor -%}
|
|
539
|
+
----
|
|
540
|
+
|
|
541
|
+
`{%-`:: Strip whitespace before tag
|
|
542
|
+
`-%}`:: Strip whitespace after tag
|
|
543
|
+
`{{-`:: Strip whitespace before output
|
|
544
|
+
`-}}`:: Strip whitespace after output
|
|
545
|
+
|
|
546
|
+
.Whitespace comparison
|
|
547
|
+
[example]
|
|
548
|
+
====
|
|
549
|
+
Without stripping:
|
|
550
|
+
[source,liquid]
|
|
551
|
+
----
|
|
552
|
+
{% for entity in schema.entities %}
|
|
553
|
+
{{ entity.id }}
|
|
554
|
+
{% endfor %}
|
|
555
|
+
----
|
|
556
|
+
|
|
557
|
+
Output (with blank lines):
|
|
558
|
+
[source]
|
|
559
|
+
----
|
|
560
|
+
|
|
561
|
+
person
|
|
562
|
+
|
|
563
|
+
company
|
|
564
|
+
|
|
565
|
+
----
|
|
566
|
+
|
|
567
|
+
With stripping:
|
|
568
|
+
[source,liquid]
|
|
569
|
+
----
|
|
570
|
+
{%- for entity in schema.entities %}
|
|
571
|
+
{{ entity.id }}
|
|
572
|
+
{%- endfor %}
|
|
573
|
+
----
|
|
574
|
+
|
|
575
|
+
Output (compact):
|
|
576
|
+
[source]
|
|
577
|
+
----
|
|
578
|
+
person
|
|
579
|
+
company
|
|
580
|
+
----
|
|
581
|
+
====
|
|
582
|
+
|
|
583
|
+
=== Strategic whitespace use
|
|
584
|
+
|
|
585
|
+
[source,liquid]
|
|
586
|
+
----
|
|
587
|
+
# Schema: {{ schema.id }}
|
|
588
|
+
{%- comment %}No blank after title{% endcomment %}
|
|
589
|
+
|
|
590
|
+
## Entities
|
|
591
|
+
{%- comment %}No blank after heading{% endcomment %}
|
|
592
|
+
|
|
593
|
+
{%- for entity in schema.entities %}
|
|
594
|
+
- {{ entity.id }}
|
|
595
|
+
{%- endfor %}
|
|
596
|
+
{%- comment %}Compact list{% endcomment %}
|
|
597
|
+
----
|
|
598
|
+
|
|
599
|
+
== Capture for complex variables
|
|
600
|
+
|
|
601
|
+
Store template output in variables:
|
|
602
|
+
|
|
603
|
+
[source,liquid]
|
|
604
|
+
----
|
|
605
|
+
{% capture entity_list %}
|
|
606
|
+
{% for entity in schema.entities %}
|
|
607
|
+
{{ entity.id }}{% unless forloop.last %}, {% endunless %}
|
|
608
|
+
{% endfor %}
|
|
609
|
+
{% endcapture %}
|
|
610
|
+
|
|
611
|
+
Entities: {{ entity_list }}
|
|
612
|
+
----
|
|
613
|
+
|
|
614
|
+
Useful for:
|
|
615
|
+
|
|
616
|
+
* Reusing generated content
|
|
617
|
+
* Building complex strings
|
|
618
|
+
* Conditional output assembly
|
|
619
|
+
|
|
620
|
+
[source,liquid]
|
|
621
|
+
----
|
|
622
|
+
{% capture description %}
|
|
623
|
+
{% if entity.remarks.size > 0 %}
|
|
624
|
+
{{ entity.remarks | join: " " }}
|
|
625
|
+
{% else %}
|
|
626
|
+
{{ entity.id | capitalize }} entity
|
|
627
|
+
{% endif %}
|
|
628
|
+
{% endcapture %}
|
|
629
|
+
|
|
630
|
+
Description: {{ description | strip }}
|
|
631
|
+
----
|
|
632
|
+
|
|
633
|
+
== Template organization best practices
|
|
634
|
+
|
|
635
|
+
=== Use descriptive variable names
|
|
636
|
+
|
|
637
|
+
[source,liquid]
|
|
638
|
+
----
|
|
639
|
+
{% comment %}❌ Poor{% endcomment %}
|
|
640
|
+
{% assign t = schema.types.size %}
|
|
641
|
+
{% assign e = schema.entities.size %}
|
|
642
|
+
|
|
643
|
+
{% comment %}✅ Good{% endcomment %}
|
|
644
|
+
{% assign type_count = schema.types.size %}
|
|
645
|
+
{% assign entity_count = schema.entities.size %}
|
|
646
|
+
----
|
|
647
|
+
|
|
648
|
+
=== Group related logic
|
|
649
|
+
|
|
650
|
+
[source,liquid]
|
|
651
|
+
----
|
|
652
|
+
{% comment %}=== Statistics Section ==={% endcomment %}
|
|
653
|
+
{% assign entity_count = schema.entities.size %}
|
|
654
|
+
{% assign type_count = schema.types.size %}
|
|
655
|
+
{% assign total = entity_count | plus: type_count %}
|
|
656
|
+
|
|
657
|
+
{% comment %}=== Output Section ==={% endcomment %}
|
|
658
|
+
Entities: {{ entity_count }}
|
|
659
|
+
Types: {{ type_count }}
|
|
660
|
+
Total: {{ total }}
|
|
661
|
+
----
|
|
662
|
+
|
|
663
|
+
=== Keep conditions simple
|
|
664
|
+
|
|
665
|
+
[source,liquid]
|
|
666
|
+
----
|
|
667
|
+
{% comment %}❌ Complex{% endcomment %}
|
|
668
|
+
{% if entity.attributes.size > 0 and entity.where_rules.size > 0
|
|
669
|
+
and entity.remarks.size > 0 %}
|
|
670
|
+
|
|
671
|
+
{% comment %}✅ Better - break down{% endcomment %}
|
|
672
|
+
{% assign has_attributes = entity.attributes.size > 0 %}
|
|
673
|
+
{% assign has_rules = entity.where_rules.size > 0 %}
|
|
674
|
+
{% assign has_docs = entity.remarks.size > 0 %}
|
|
675
|
+
|
|
676
|
+
{% if has_attributes and has_rules and has_docs %}
|
|
677
|
+
----
|
|
678
|
+
|
|
679
|
+
=== Use consistent formatting
|
|
680
|
+
|
|
681
|
+
[source,liquid]
|
|
682
|
+
----
|
|
683
|
+
{% comment %}Consistent indentation{% endcomment %}
|
|
684
|
+
{% for schema in repository.schemas %}
|
|
685
|
+
{% for entity in schema.entities %}
|
|
686
|
+
{% for attr in entity.attributes %}
|
|
687
|
+
{{ attr.id }}
|
|
688
|
+
{% endfor %}
|
|
689
|
+
{% endfor %}
|
|
690
|
+
{% endfor %}
|
|
691
|
+
|
|
692
|
+
{% comment %}Consistent tag spacing{% endcomment %}
|
|
693
|
+
{% if condition %}
|
|
694
|
+
content
|
|
695
|
+
{% endif %}
|
|
696
|
+
|
|
697
|
+
{% for item in items %}
|
|
698
|
+
{{ item }}
|
|
699
|
+
{% endfor %}
|
|
700
|
+
----
|
|
701
|
+
|
|
702
|
+
=== Comment complex logic
|
|
703
|
+
|
|
704
|
+
[source,liquid]
|
|
705
|
+
----
|
|
706
|
+
{% comment %}
|
|
707
|
+
Build entity hierarchy showing inheritance relationships.
|
|
708
|
+
First pass: identify root entities (no supertypes).
|
|
709
|
+
Second pass: recursively show children.
|
|
710
|
+
{% endcomment %}
|
|
711
|
+
|
|
712
|
+
{% assign root_entities = schema.entities
|
|
713
|
+
| where: "subtype_of", empty %}
|
|
714
|
+
|
|
715
|
+
{% for entity in root_entities %}
|
|
716
|
+
{% comment %}Recursively process children{% endcomment %}
|
|
717
|
+
...
|
|
718
|
+
{% endfor %}
|
|
719
|
+
----
|
|
720
|
+
|
|
721
|
+
== Common patterns
|
|
722
|
+
|
|
723
|
+
=== Conditional sections
|
|
724
|
+
|
|
725
|
+
[source,liquid]
|
|
726
|
+
----
|
|
727
|
+
{% if entity.where_rules.size > 0 %}
|
|
728
|
+
## Constraints
|
|
729
|
+
|
|
730
|
+
{% for rule in entity.where_rules %}
|
|
731
|
+
### {{ rule.id }}
|
|
732
|
+
{{ rule.expression }}
|
|
733
|
+
{% endfor %}
|
|
734
|
+
{% endif %}
|
|
735
|
+
----
|
|
736
|
+
|
|
737
|
+
=== Fallback content
|
|
738
|
+
|
|
739
|
+
[source,liquid]
|
|
740
|
+
----
|
|
741
|
+
{% if entity.remarks.size > 0 %}
|
|
742
|
+
{{ entity.remarks | join: " " }}
|
|
743
|
+
{% else %}
|
|
744
|
+
_No documentation available._
|
|
745
|
+
{% endif %}
|
|
746
|
+
----
|
|
747
|
+
|
|
748
|
+
=== Sorted output
|
|
749
|
+
|
|
750
|
+
[source,liquid]
|
|
751
|
+
----
|
|
752
|
+
{% assign sorted_entities = schema.entities | sort: "id" %}
|
|
753
|
+
|
|
754
|
+
{% for entity in sorted_entities %}
|
|
755
|
+
- {{ entity.id }}
|
|
756
|
+
{% endfor %}
|
|
757
|
+
----
|
|
758
|
+
|
|
759
|
+
=== Filtered lists
|
|
760
|
+
|
|
761
|
+
[source,liquid]
|
|
762
|
+
----
|
|
763
|
+
{% comment %}Show only abstract entities{% endcomment %}
|
|
764
|
+
{% for entity in schema.entities %}
|
|
765
|
+
{% if entity.abstract %}
|
|
766
|
+
- {{ entity.id }} (abstract)
|
|
767
|
+
{% endif %}
|
|
768
|
+
{% endfor %}
|
|
769
|
+
----
|
|
770
|
+
|
|
771
|
+
=== Numbered lists
|
|
772
|
+
|
|
773
|
+
[source,liquid]
|
|
774
|
+
----
|
|
775
|
+
{% for entity in schema.entities %}
|
|
776
|
+
{{ forloop.index }}. {{ entity.id }}
|
|
777
|
+
{% if entity.abstract %}
|
|
778
|
+
_Abstract entity_
|
|
779
|
+
{% endif %}
|
|
780
|
+
{% endfor %}
|
|
781
|
+
----
|
|
782
|
+
|
|
783
|
+
== Next steps
|
|
784
|
+
|
|
785
|
+
Build on these basics:
|
|
786
|
+
|
|
787
|
+
* link:drops-reference.html[Drops Reference] - Explore available data
|
|
788
|
+
* link:filters-and-tags.html[Filters and Tags] - Transform and operate
|
|
789
|
+
on data
|
|
790
|
+
* link:documentation-generation.html[Documentation Generation] -
|
|
791
|
+
Complete workflows
|
|
792
|
+
|
|
793
|
+
**Practice**:
|
|
794
|
+
|
|
795
|
+
* link:../../_tutorials/liquid-templates.html[Liquid Templates
|
|
796
|
+
Tutorial] - Hands-on examples
|
|
797
|
+
|
|
798
|
+
== Summary
|
|
799
|
+
|
|
800
|
+
Liquid template basics include:
|
|
801
|
+
|
|
802
|
+
* ✅ Output tags `{{ }}` for displaying data
|
|
803
|
+
* ✅ Logic tags `{% %}` for control flow
|
|
804
|
+
* ✅ Variables with `assign` and `capture`
|
|
805
|
+
* ✅ Conditionals: `if`, `elsif`, `else`, `unless`, `case`
|
|
806
|
+
* ✅ Loops: `for`, `break`, `continue`, `reversed`
|
|
807
|
+
* ✅ Loop variables: `forloop.index`, `forloop.first`, etc.
|
|
808
|
+
* ✅ Whitespace control with `-` hyphens
|
|
809
|
+
* ✅ Comments for documentation
|
|
810
|
+
* ✅ Organization best practices
|
|
811
|
+
|
|
812
|
+
Master these fundamentals to create effective, maintainable templates
|
|
813
|
+
for EXPRESS schema documentation.
|