expressir 2.1.29 → 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.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/docs.yml +98 -0
  3. data/.github/workflows/links.yml +100 -0
  4. data/.github/workflows/rake.yml +4 -0
  5. data/.github/workflows/release.yml +5 -0
  6. data/.github/workflows/validate_schemas.yml +1 -1
  7. data/.gitignore +3 -0
  8. data/.rubocop.yml +1 -1
  9. data/.rubocop_todo.yml +209 -55
  10. data/Gemfile +2 -1
  11. data/README.adoc +650 -83
  12. data/docs/Gemfile +12 -0
  13. data/docs/_config.yml +141 -0
  14. data/docs/_guides/changes/changes-format.adoc +778 -0
  15. data/docs/_guides/changes/importing-eengine.adoc +898 -0
  16. data/docs/_guides/changes/index.adoc +396 -0
  17. data/docs/_guides/changes/programmatic-usage.adoc +1038 -0
  18. data/docs/_guides/changes/validating-changes.adoc +681 -0
  19. data/docs/_guides/cli/benchmark-performance.adoc +834 -0
  20. data/docs/_guides/cli/coverage-analysis.adoc +921 -0
  21. data/docs/_guides/cli/format-schemas.adoc +547 -0
  22. data/docs/_guides/cli/index.adoc +8 -0
  23. data/docs/_guides/cli/managing-changes.adoc +927 -0
  24. data/docs/_guides/cli/validate-ascii.adoc +645 -0
  25. data/docs/_guides/cli/validate-schemas.adoc +534 -0
  26. data/docs/_guides/index.adoc +165 -0
  27. data/docs/_guides/ler/creating-packages.adoc +664 -0
  28. data/docs/_guides/ler/index.adoc +305 -0
  29. data/docs/_guides/ler/loading-packages.adoc +707 -0
  30. data/docs/_guides/ler/package-formats.adoc +748 -0
  31. data/docs/_guides/ler/querying-packages.adoc +826 -0
  32. data/docs/_guides/ler/validating-packages.adoc +750 -0
  33. data/docs/_guides/liquid/basic-templates.adoc +813 -0
  34. data/docs/_guides/liquid/documentation-generation.adoc +1042 -0
  35. data/docs/_guides/liquid/drops-reference.adoc +829 -0
  36. data/docs/_guides/liquid/filters-and-tags.adoc +912 -0
  37. data/docs/_guides/liquid/index.adoc +468 -0
  38. data/docs/_guides/manifests/creating-manifests.adoc +483 -0
  39. data/docs/_guides/manifests/index.adoc +307 -0
  40. data/docs/_guides/manifests/resolving-manifests.adoc +557 -0
  41. data/docs/_guides/manifests/validating-manifests.adoc +713 -0
  42. data/docs/_guides/ruby-api/formatting-schemas.adoc +605 -0
  43. data/docs/_guides/ruby-api/index.adoc +257 -0
  44. data/docs/_guides/ruby-api/parsing-files.adoc +421 -0
  45. data/docs/_guides/ruby-api/search-engine.adoc +609 -0
  46. data/docs/_guides/ruby-api/working-with-repository.adoc +577 -0
  47. data/docs/_pages/data-model.adoc +665 -0
  48. data/docs/_pages/express-language.adoc +506 -0
  49. data/docs/_pages/getting-started.adoc +414 -0
  50. data/docs/_pages/index.adoc +116 -0
  51. data/docs/_pages/introduction.adoc +256 -0
  52. data/docs/_pages/ler-packages.adoc +837 -0
  53. data/docs/_pages/parsers.adoc +683 -0
  54. data/docs/_pages/schema-manifests.adoc +431 -0
  55. data/docs/_references/index.adoc +228 -0
  56. data/docs/_tutorials/creating-ler-package.adoc +735 -0
  57. data/docs/_tutorials/documentation-coverage.adoc +795 -0
  58. data/docs/_tutorials/index.adoc +221 -0
  59. data/docs/_tutorials/liquid-templates.adoc +806 -0
  60. data/docs/_tutorials/parsing-your-first-schema.adoc +522 -0
  61. data/docs/_tutorials/querying-schemas.adoc +751 -0
  62. data/docs/_tutorials/working-with-multiple-schemas.adoc +676 -0
  63. data/docs/index.adoc +242 -0
  64. data/docs/lychee.toml +84 -0
  65. data/examples/demo_ler_usage.sh +86 -0
  66. data/examples/ler/README.md +111 -0
  67. data/examples/ler/simple_example.ler +0 -0
  68. data/examples/ler/simple_schema.exp +33 -0
  69. data/examples/ler_build.rb +75 -0
  70. data/examples/ler_cli.rb +79 -0
  71. data/examples/ler_demo_complete.rb +276 -0
  72. data/examples/ler_query.rb +91 -0
  73. data/examples/ler_query_examples.rb +305 -0
  74. data/examples/ler_stats.rb +81 -0
  75. data/examples/phase3_demo.rb +159 -0
  76. data/examples/query_demo_simple.rb +131 -0
  77. data/expressir.gemspec +2 -0
  78. data/lib/expressir/changes/schema_change.rb +32 -22
  79. data/lib/expressir/changes/{edition_change.rb → version_change.rb} +3 -3
  80. data/lib/expressir/cli.rb +12 -4
  81. data/lib/expressir/commands/changes_import_eengine.rb +2 -2
  82. data/lib/expressir/commands/changes_validate.rb +1 -1
  83. data/lib/expressir/commands/manifest.rb +427 -0
  84. data/lib/expressir/commands/package.rb +1274 -0
  85. data/lib/expressir/commands/validate.rb +70 -37
  86. data/lib/expressir/commands/validate_ascii.rb +607 -0
  87. data/lib/expressir/commands/validate_load.rb +88 -0
  88. data/lib/expressir/express/formatter.rb +5 -1
  89. data/lib/expressir/express/formatters/remark_item_formatter.rb +25 -0
  90. data/lib/expressir/express/parser.rb +33 -0
  91. data/lib/expressir/manifest/resolver.rb +213 -0
  92. data/lib/expressir/manifest/validator.rb +195 -0
  93. data/lib/expressir/model/declarations/entity.rb +6 -0
  94. data/lib/expressir/model/dependency_resolver.rb +270 -0
  95. data/lib/expressir/model/indexes/entity_index.rb +103 -0
  96. data/lib/expressir/model/indexes/reference_index.rb +148 -0
  97. data/lib/expressir/model/indexes/type_index.rb +149 -0
  98. data/lib/expressir/model/interface_validator.rb +384 -0
  99. data/lib/expressir/model/repository.rb +400 -5
  100. data/lib/expressir/model/repository_validator.rb +295 -0
  101. data/lib/expressir/model/search_engine.rb +525 -0
  102. data/lib/expressir/model.rb +4 -94
  103. data/lib/expressir/package/builder.rb +200 -0
  104. data/lib/expressir/package/metadata.rb +81 -0
  105. data/lib/expressir/package/reader.rb +165 -0
  106. data/lib/expressir/schema_manifest.rb +11 -1
  107. data/lib/expressir/version.rb +1 -1
  108. data/lib/expressir.rb +16 -3
  109. metadata +115 -5
  110. data/docs/benchmarking.adoc +0 -107
  111. data/docs/liquid_drops.adoc +0 -1547
data/README.adoc CHANGED
@@ -81,6 +81,7 @@ Commands:
81
81
  expressir format PATH # pretty print EXPRESS schema located at PATH
82
82
  expressir help [COMMAND] # Describe available commands or one specific command
83
83
  expressir validate *PATH # validate EXPRESS schema located at PATH
84
+ expressir validate ascii PATH # Validate EXPRESS files for ASCII-only content (excluding remarks)
84
85
  expressir coverage *PATH # List EXPRESS entities and check documentation coverage
85
86
  expressir version # Expressir Version
86
87
  ----
@@ -97,9 +98,10 @@ expressir format schemas/resources/action_schema/action_schema.exp
97
98
  ----
98
99
 
99
100
  This command:
100
- 1. Parses the EXPRESS schema
101
- 2. Formats it with consistent indentation and spacing
102
- 3. Outputs the formatted schema to stdout
101
+
102
+ . Parses the EXPRESS schema
103
+ . Formats it with consistent indentation and spacing
104
+ . Outputs the formatted schema to stdout
103
105
 
104
106
  === Clean schema
105
107
 
@@ -124,29 +126,136 @@ expressir clean schemas/resources/action_schema/action_schema.exp --output clean
124
126
 
125
127
  === Validate schema
126
128
 
127
- The `validate` command performs validation checks on EXPRESS schema files.
129
+ The `validate load` command performs validation checks on EXPRESS schema files.
128
130
 
129
131
  It verifies:
130
132
 
131
- . That the schema can be parsed correctly
133
+ . That the schema can be parsed correctly into the EXPRESS data model
132
134
  . That the schema includes a version string
133
135
 
134
136
  [source, sh]
135
137
  ----
136
138
  # Validate a single schema
137
- expressir validate schemas/resources/action_schema/action_schema.exp
139
+ expressir validate load schemas/resources/action_schema/action_schema.exp
138
140
 
139
141
  # Validate multiple schemas
140
- expressir validate schemas/resources/action_schema/action_schema.exp schemas/resources/approval_schema/approval_schema.exp
142
+ expressir validate load schemas/resources/action_schema/action_schema.exp schemas/resources/approval_schema/approval_schema.exp
143
+
144
+ # Validate schemas from a schema manifest YAML
145
+ expressir validate load schemas.yml
141
146
  ----
142
147
 
143
148
  The command reports any schemas that:
144
149
 
145
- * Failed to parse
150
+ * Failed to parse into the EXPRESS data model
146
151
  * Are missing a version string
147
152
 
148
153
  If all validations pass, it will display "Validation passed for all EXPRESS schemas."
149
154
 
155
+ === Validate ASCII content
156
+
157
+ The `validate ascii` command validates that EXPRESS schema files contain only
158
+ ASCII characters outside of remarks. This ensures compatibility with systems
159
+ that don't support Unicode, while allowing Unicode in documentation comments.
160
+
161
+ [source, sh]
162
+ ----
163
+ # Validate a single file
164
+ expressir validate ascii schema.exp
165
+
166
+ # Validate schema manifest YAML
167
+ expressir validate ascii schemas.yml
168
+
169
+ # Validate directory (non-recursive)
170
+ expressir validate ascii schemas/
171
+
172
+ # Validate directory recursively
173
+ expressir validate ascii schemas/ --recursive
174
+
175
+ # Output in YAML format
176
+ expressir validate ascii schemas/ --yaml
177
+
178
+ # Check remarks as well (include remarks in validation)
179
+ expressir validate ascii schema.exp --check-remarks
180
+ ----
181
+
182
+ The command checks that all EXPRESS code (excluding remarks) contains only
183
+ 7-bit ASCII characters. Tagged remarks (both embedded `(* ... *)` and tail
184
+ `-- ...` comments) are excluded from validation, allowing documentation to
185
+ contain Unicode without triggering errors.
186
+
187
+ [options="header"]
188
+ |===
189
+ | Option | Description
190
+
191
+ | `--recursive`, `-r`
192
+ | Validate EXPRESS files under the specified path recursively
193
+
194
+ | `--yaml`, `-y`
195
+ | Output results in YAML format for programmatic processing
196
+
197
+ | `--check-remarks`
198
+ | Include remarks in ASCII validation (default: false, remarks are excluded)
199
+ |===
200
+
201
+ The validator provides:
202
+
203
+ * Detailed violation reports with line and column numbers
204
+ * Replacement suggestions (AsciiMath for math symbols, ISO 10303-11 encoding for others)
205
+ * Summary statistics
206
+ * Visual indicators for non-ASCII sequences
207
+
208
+ This command is particularly useful before exporting schemas to formats that
209
+ don't support Unicode, such as EEP (Express Engine Parser) and eengine (Express
210
+ Engine).
211
+
212
+
213
+ [example]
214
+ ====
215
+ [source, sh]
216
+ ----
217
+ $ expressir validate ascii spec/fixtures/validate_ascii/non_ascii_in_code.exp
218
+
219
+ spec/fixtures/validate_ascii/non_ascii_in_code.exp:
220
+ Line 3, Column 9:
221
+ ENTITY 製品;
222
+ ^^ Non-ASCII sequence
223
+ "製" - Hex: 0x88fd, UTF-8 bytes: 0xe8 0xa3 0xbd
224
+ Replacement: ISO 10303-11: "000088FD"
225
+ "品" - Hex: 0x54c1, UTF-8 bytes: 0xe5 0x93 0x81
226
+ Replacement: ISO 10303-11: "000054C1"
227
+
228
+ ...
229
+ Line 10, Column 24:
230
+ symbol : STRING := 'μ';
231
+ ^ Non-ASCII sequence
232
+ "μ" - Hex: 0x3bc, UTF-8 bytes: 0xce 0xbc
233
+ Replacement: AsciiMath: mu
234
+
235
+ ...
236
+
237
+ Found 7 non-ASCII sequence(s) in non_ascii_in_code.exp
238
+
239
+ Summary:
240
+ Scanned 1 EXPRESS file(s)
241
+ Found 7 non-ASCII sequence(s) in 1 file(s)
242
+
243
+ ╭──────────────────────────────────────────────────────────────────────────╮
244
+ │ Non-ASCII Characters Summary │
245
+ ├──────────────────────────┬─────────────┬────────────────────┬────────────┤
246
+ │ File │ Symbol │ Replacement │ Occurrenc… │
247
+ ├──────────────────────────┼─────────────┼────────────────────┼────────────┤
248
+ │ validate_ascii/non_asci… │ "製" (0x88… │ ISO 10303-11: "00… │ 1 │
249
+ │ validate_ascii/non_asci… │ "品" (0x54… │ ISO 10303-11: "00… │ 1 │
250
+ │ ... │ │ │ │
251
+ │ validate_ascii/non_asci… │ "μ" (0x3bc) │ AsciiMath: mu │ 1 │
252
+ │ ... │ │ │ │
253
+ │ TOTAL │ 10 unique │ — │ 11 │
254
+ ╰──────────────────────────┴─────────────┴────────────────────┴────────────╯
255
+ ----
256
+ ====
257
+
258
+
150
259
  === Version
151
260
 
152
261
  The `version` command displays the current version of the Expressir gem.
@@ -745,8 +854,8 @@ The import command:
745
854
 
746
855
  When the output file already exists:
747
856
 
748
- * **Same version**: Replaces the existing edition with that version
749
- * **New version**: Adds a new edition to the file
857
+ * **Same version**: Replaces the existing version with that version
858
+ * **New version**: Adds a new version to the file
750
859
 
751
860
  This allows you to build up a complete change history incrementally across
752
861
  multiple schema versions.
@@ -816,14 +925,14 @@ This creates a single YAML file tracking changes across all three versions:
816
925
  [source,yaml]
817
926
  ----
818
927
  schema: action_schema
819
- editions:
820
- - version: '2'
928
+ versions:
929
+ - version: 2
821
930
  description: Changes from eengine comparison
822
931
  additions: [...]
823
- - version: '3'
932
+ - version: 3
824
933
  description: Changes from eengine comparison
825
934
  additions: [...]
826
- - version: '4'
935
+ - version: 4
827
936
  description: Changes from eengine comparison
828
937
  additions: [...]
829
938
  ----
@@ -1026,9 +1135,10 @@ all_entities = Expressir::Coverage.find_entities(schema)
1026
1135
  puts "Found #{all_entities.size} entities in schema #{schema.id}"
1027
1136
  ----
1028
1137
 
1029
- === EXPRESS schema manifest
1030
1138
 
1031
- ==== General
1139
+ == EXPRESS schema manifests
1140
+
1141
+ === General
1032
1142
 
1033
1143
  The EXPRESS schema manifest is a file format defined by ELF at
1034
1144
  https://www.expresslang.org/docs[EXPRESS schema manifest specification].
@@ -1045,8 +1155,30 @@ The `SchemaManifest` class allows you to:
1045
1155
  * Save manifest configurations to files
1046
1156
 
1047
1157
 
1158
+ === File format
1159
+
1160
+ The schema manifest uses a structured YAML format:
1161
+
1162
+ [source,yaml]
1163
+ ----
1164
+ schemas:
1165
+ - path: schemas/resources/action_schema/action_schema.exp
1166
+ id: action_schema
1167
+ - path: schemas/resources/approval_schema/approval_schema.exp
1168
+ id: approval_schema
1169
+ - path: schemas/resources/date_time_schema/date_time_schema.exp
1170
+ id: date_time_schema
1171
+ ----
1172
+
1173
+ Each schema entry in the manifest can have the following attributes:
1174
+
1175
+ `path`:: (Required) The file path to the EXPRESS schema file
1176
+ `id`:: (Optional) A unique identifier for the schema
1177
+ `container_path`:: (Optional) Container path information
1178
+
1179
+
1048
1180
  [example]
1049
- .Example project structure with schema manifest:
1181
+ .Example project structure with schema manifest
1050
1182
  ====
1051
1183
  [source]
1052
1184
  ----
@@ -1073,9 +1205,362 @@ schemas:
1073
1205
  ----
1074
1206
  ====
1075
1207
 
1076
- ==== Creating a schema manifest
1077
1208
 
1078
- ===== From a YAML file
1209
+ === Commands for schema manifests
1210
+
1211
+ ==== Creating a manifest from a root schema
1212
+
1213
+ The `manifest create` command generates a schema manifest YAML file by
1214
+ resolving all referenced schemas starting from a specified root schema file.
1215
+
1216
+ .`manifest create` - Generate schema manifest
1217
+ [source,sh]
1218
+ ----
1219
+ Usage:
1220
+ expressir manifest create ROOT_SCHEMA [MORE_SCHEMAS...] -o, --output=OUTPUT
1221
+
1222
+ Options:
1223
+ -o, --output=OUTPUT # Output YAML file path
1224
+ [--base-dirs=BASE_DIRS] # Comma-separated base directories for schema resolution
1225
+ [--verbose], [--no-verbose], [--skip-verbose] # Show detailed output
1226
+ # Default: false
1227
+
1228
+ Description:
1229
+ Generate a YAML manifest of all schemas required for packaging.
1230
+
1231
+ The manifest uses the existing SchemaManifest format: schemas: schema_id: path:
1232
+ /path/to/schema.exp
1233
+
1234
+ Workflow: 1. Create manifest from root schema 2. Edit manifest to add paths for
1235
+ schemas with null paths 3. Validate manifest 4. Build package using manifest
1236
+
1237
+ Example: expressir manifest create schemas/activity/mim.exp \ -o
1238
+ activity_manifest.yaml \ --base-dirs /path/to/schemas
1239
+ ----
1240
+
1241
+ Options:
1242
+
1243
+ `--output, -o FILE`:: (Required) Output YAML file path
1244
+
1245
+ `--base-dirs DIRS`:: Base directories for schema resolution (space-separated). Also supports comma-separated for backward compatibility.
1246
+ +
1247
+ Searches for schema files using these patterns:
1248
+ schema files named according to schema ID::: `<SCHEMA_ID>.exp`
1249
+ schema files named in the STEP module pattern::: `<LOWERCASE_SCHEMA_WO_MIMARM>/{mim,arm}.exp`
1250
+ +
1251
+ [source,sh]
1252
+ ----
1253
+ # Space-separated (preferred)
1254
+ --base-dirs /path/to/schemas /another/path
1255
+
1256
+ # Comma-separated (backward compatible)
1257
+ --base-dirs /path/to/schemas,/another/path
1258
+ ----
1259
+
1260
+ `--verbose`:: Show detailed output
1261
+
1262
+ Base directories can be provided to help locate schema files:
1263
+
1264
+ * During the resolving process, Expressir will search these directories for
1265
+ schema files matching known naming patterns.
1266
+ * Once a referenced schema is found, it will indicate from which source they
1267
+ were resolved.
1268
+ * If multiple matches are found, the first one encountered will be used, and a
1269
+ warning will be displayed for the user to manually edit the manifest if a
1270
+ different path is desired.
1271
+
1272
+ In the case of unresolved schemas, the created manifest will include entries
1273
+ without the `path:` field. The manifest can then be edited manually to add the
1274
+ correct paths.
1275
+
1276
+
1277
+ .Creating a manifest from a root schema
1278
+ [example]
1279
+ ====
1280
+ The following command creates a manifest starting from the
1281
+ `schemas/modules/activity/mim.exp` root schema, searching for referenced schemas
1282
+ in the `schemas/resources` and `schemas/modules` base directories.
1283
+
1284
+ [source,sh]
1285
+ ----
1286
+ $ expressir manifest create \
1287
+ schemas/modules/activity/mim.exp \
1288
+ -o new.yaml \
1289
+ --base-dirs schemas/modules schemas/resources/ \
1290
+ --verbose
1291
+
1292
+ Creating manifest from 1 root schema(s)...
1293
+ Base directories:
1294
+ - [source 1]: ~/src/mn/iso-10303/schemas/modules
1295
+ - [source 2]: ~/src/mn/iso-10303/schemas/resources/
1296
+ Resolving dependencies...
1297
+ USE FROM action_schema (in mim): ✓ [source 2] action_schema/action_schema.exp
1298
+ REFERENCE FROM basic_attribute_schema (in action_schema): ✓ [source 2] basic_attribute_schema/basic_attribute_schema.exp
1299
+ REFERENCE FROM support_resource_schema (in basic_attribute_schema): ✓ [source 2] support_resource_schema/support_resource_schema.exp
1300
+ REFERENCE FROM support_resource_schema (in action_schema): ✓ [source 2] support_resource_schema/support_resource_schema.exp
1301
+ USE FROM Activity_method_mim (in mim): ✓ [source 1] activity_method/mim.exp
1302
+ ...
1303
+ REFERENCE FROM support_resource_schema (in management_resources_schema): ✓ [source 2] support_resource_schema/support_resource_schema.exp
1304
+ ✓ Manifest created: new.yaml
1305
+ Resolved schemas: 42
1306
+ All schemas resolved successfully!
1307
+ ----
1308
+ ====
1309
+
1310
+ .Creating a manifest from a root schema with unresolved schemas
1311
+ [example]
1312
+ ====
1313
+ The following command creates a manifest starting from the
1314
+ `schemas/modules/activity/mim.exp` root schema, searching for referenced schemas
1315
+ in the `schemas/resources` base directory only (i.e. it will miss schemas
1316
+ in `schemas/modules`).
1317
+
1318
+ [source,sh]
1319
+ ----
1320
+ $ expressir manifest create \
1321
+ -o manifest.yaml \
1322
+ --base-dirs schemas/resources \
1323
+ --verbose \
1324
+ schemas/modules/activity/mim.exp
1325
+
1326
+ Creating manifest from 1 root schema(s)...
1327
+ Base directories:
1328
+ - [source 1]: ~/src/mn/iso-10303/schemas/resources
1329
+ Resolving dependencies...
1330
+ USE FROM action_schema (in mim): ✓ [source 1] action_schema/action_schema.exp
1331
+ REFERENCE FROM basic_attribute_schema (in action_schema): ✓ [source 1] basic_attribute_schema/basic_attribute_schema.exp
1332
+ REFERENCE FROM support_resource_schema (in basic_attribute_schema): ✓ [source 1] support_resource_schema/support_resource_schema.exp
1333
+ REFERENCE FROM support_resource_schema (in action_schema): ✓ [source 1] support_resource_schema/support_resource_schema.exp
1334
+ USE FROM Activity_method_mim (in mim): ✗ not found
1335
+ ...
1336
+ REFERENCE FROM support_resource_schema (in management_resources_schema): ✓ [source 2] support_resource_schema/support_resource_schema.exp
1337
+ ✓ Manifest created: manifest.yaml
1338
+ Resolved schemas: 41
1339
+
1340
+ ⚠ Unresolved schemas (1):
1341
+ - Activity_method_mim
1342
+
1343
+ Please edit manifest.yaml and set 'path:' for unresolved schemas
1344
+ Then validate with: expressir manifest validate manifest.yaml
1345
+ ----
1346
+ ====
1347
+
1348
+
1349
+
1350
+ ==== Resolving schemas from a manifest
1351
+
1352
+ A schema manifest can be used as input to resolve and load all referenced
1353
+ schemas into a new manifest.
1354
+
1355
+
1356
+ [source,sh]
1357
+ ----
1358
+ expressir manifest resolve MANIFEST -o, --output=OUTPUT
1359
+ ----
1360
+
1361
+ [source,sh]
1362
+ ----
1363
+ Usage:
1364
+ expressir manifest resolve MANIFEST -o, --output=OUTPUT
1365
+
1366
+ Options:
1367
+ -o, --output=OUTPUT # Output file path for resolved manifest
1368
+ [--base-dirs=one two three] # Base directories for schema search (can be specified multiple times)
1369
+ [--verbose], [--no-verbose], [--skip-verbose] # Show detailed resolution progress
1370
+ # Default: false
1371
+
1372
+ Description:
1373
+ Resolve missing or incomplete schema paths in a manifest file.
1374
+
1375
+ This command attempts to find file paths for schemas with missing or empty
1376
+ paths by searching in base directories using naming patterns:
1377
+
1378
+ Supported patterns:
1379
+ - Resource schemas: {schema_name}.exp
1380
+ - Module ARM/MIM: {module_name}/{arm|mim}.exp
1381
+ Example: Activity_method_mim -> activity_method/mim.exp
1382
+
1383
+ The resolved manifest is written to the output file, leaving the original
1384
+ unchanged.
1385
+
1386
+ Use this command after 'expressir manifest validate --check-references' fails
1387
+ to automatically resolve missing schema paths.
1388
+
1389
+ Examples: # Resolve paths using manifest's existing base directories expressir
1390
+ manifest resolve manifest.yaml -o resolved_manifest.yaml
1391
+ # Resolve with explicit base directories
1392
+ expressir manifest resolve manifest.yaml -o resolved.yaml \
1393
+ --base-dirs /path/to/schemas,/another/path
1394
+ # With verbose output
1395
+ expressir manifest resolve manifest.yaml -o resolved.yaml --verbose
1396
+ ----
1397
+
1398
+ Options:
1399
+
1400
+ `--output, -o FILE`:: (Required) Output file path for resolved manifest
1401
+
1402
+ `--base-dirs DIRS`:: Base directories for schema search (space-separated). Also
1403
+ supports comma-separated for backward compatibility.
1404
+ +
1405
+ Searches for schema files using these patterns:
1406
+ schema files named according to schema ID::: `<SCHEMA_ID>.exp`
1407
+ schema files named in the STEP module pattern::: `<LOWERCASE_SCHEMA_WO_MIMARM>/{mim,arm}.exp`
1408
+ +
1409
+ [source,sh]
1410
+ ----
1411
+ # Space-separated (preferred)
1412
+ --base-dirs /path/to/schemas /another/path
1413
+
1414
+ # Comma-separated (backward compatible)
1415
+ --base-dirs /path/to/schemas,/another/path
1416
+ ----
1417
+
1418
+ `--verbose`:: Show detailed resolution progress
1419
+
1420
+ .Fully resolving a schema manifest
1421
+ [example]
1422
+ ====
1423
+ The following command resolves all schemas in the `manifest.yaml` file and writes the
1424
+ fully resolved manifest to `resolved_manifest.yaml`.
1425
+
1426
+ [source,sh]
1427
+ ----
1428
+ $ expressir manifest resolve manifest.yaml -o resolved.yaml --verbose
1429
+
1430
+ Resolving schema paths in: manifest.yaml...
1431
+ Using base directories:
1432
+ - [source 1] ~/src/mn/iso-10303/schemas/
1433
+ Attempting to resolve paths...
1434
+ Resolving dependencies from 1 root schema(s)...
1435
+ USE FROM action_schema (in mim): ✓ [source 1] resources/action_schema/action_schema.exp
1436
+ REFERENCE FROM basic_attribute_schema (in action_schema): ✓ [source 1] resources/basic_attribute_schema/basic_attribute_schema.exp
1437
+ REFERENCE FROM support_resource_schema (in basic_attribute_schema): ✓ [source 1] resources/support_resource_schema/support_resource_schema.exp
1438
+ REFERENCE FROM support_resource_schema (in action_schema): ✓ [source 1] resources/support_resource_schema/support_resource_schema.exp
1439
+ USE FROM Activity_method_mim (in mim): ✗ not found
1440
+ USE FROM basic_attribute_schema (in mim): ✓ [source 1] resources/basic_attribute_schema/basic_attribute_schema.exp
1441
+ USE FROM management_resources_schema (in mim): ✓ [source 1] resources/management_resources_schema/management_resources_schema.exp
1442
+ ...
1443
+ REFERENCE FROM support_resource_schema (in management_resources_schema): ✓ [source 1] resources/support_resource_schema/support_resource_schema.exp
1444
+ ✓ Manifest resolved: resolved.yaml
1445
+ Total schemas: 42
1446
+ Resolved schemas: 41
1447
+
1448
+ ⚠ Unresolved schemas (1):
1449
+ - Activity_method_mim
1450
+
1451
+ These schemas could not be found in the search directories.
1452
+ You may need to:
1453
+ 1. Add more base directories with --base-dirs
1454
+ 2. Manually edit resolved.yaml and set their paths
1455
+ ----
1456
+ ====
1457
+
1458
+ .Resolving a manifest with multiple base directories
1459
+ [example]
1460
+ ====
1461
+ [source,sh]
1462
+ ----
1463
+ $ expressir manifest resolve manifest.yaml \
1464
+ -o resolved.yaml \
1465
+ --base-dirs ~/src/mn/iso-10303/schemas/modules \
1466
+ ~/src/mn/iso-10303/schemas/resources/ --verbose
1467
+
1468
+ Resolving schema paths in: manifest.yaml...
1469
+ Using base directories:
1470
+ - [source 1]: ~/src/mn/iso-10303/schemas/modules
1471
+ - [source 2]: ~/src/mn/iso-10303/schemas/resources/
1472
+ Attempting to resolve paths...
1473
+ Resolving dependencies from 1 root schema(s)...
1474
+ Using base directories:
1475
+ - [source 1]: ~/src/mn/iso-10303/schemas/modules
1476
+ - [source 2]: ~/src/mn/iso-10303/schemas/resources
1477
+ USE FROM action_schema (in mim): ✓ [source 2] action_schema/action_schema.exp
1478
+ REFERENCE FROM basic_attribute_schema (in action_schema): ✓ [source 2] basic_attribute_schema/basic_attribute_schema.exp
1479
+ REFERENCE FROM support_resource_schema (in basic_attribute_schema): ✓ [source 2] support_resource_schema/support_resource_schema.exp
1480
+ REFERENCE FROM support_resource_schema (in action_schema): ✓ [source 2] support_resource_schema/support_resource_schema.exp
1481
+ USE FROM Activity_method_mim (in mim): ✓ [source 1] activity_method/mim.exp
1482
+ ...
1483
+ REFERENCE FROM support_resource_schema (in management_resources_schema): ✓ [source 2] support_resource_schema/support_resource_schema.exp
1484
+ ✓ Manifest resolved: resolved.yaml
1485
+ Total schemas: 42
1486
+ Resolved schemas: 42
1487
+ All schema paths resolved successfully!
1488
+ ----
1489
+ ====
1490
+
1491
+
1492
+ ==== Validating a manifest
1493
+
1494
+ A schema manifest can be validated to ensure all referenced schemas are fully
1495
+ resolvable and correctly defined.
1496
+
1497
+ .`manifest validate` - Validate manifest
1498
+ [source,sh]
1499
+ ----
1500
+ expressir manifest validate MANIFEST.yaml [OPTIONS]
1501
+ ----
1502
+
1503
+ [source,sh]
1504
+ ----
1505
+ Usage:
1506
+ expressir manifest validate MANIFEST
1507
+
1508
+ Options:
1509
+ [--verbose], [--no-verbose], [--skip-verbose] # Show detailed validation results
1510
+ # Default: false
1511
+ [--check-references], [--no-check-references], [--skip-check-references] # Validate referential integrity using dependency resolver
1512
+ # Default: false
1513
+
1514
+ Description:
1515
+ Validate a schema manifest file.
1516
+
1517
+ Validation types: - File existence: All schema paths exist on disk - Path
1518
+ completeness: All schemas have paths specified (warnings) - Referential integrity
1519
+ (--check-references): All USE/REFERENCE FROM resolve
1520
+
1521
+ Examples: # Basic validation (file existence and path completeness) expressir manifest
1522
+ validate activity_manifest.yaml # With referential integrity checking expressir
1523
+ manifest validate activity_manifest.yaml --check-references # With verbose output
1524
+ expressir manifest validate activity_manifest.yaml --check-references --verbose
1525
+ ----
1526
+
1527
+ Options:
1528
+
1529
+ `--verbose`:: Show detailed validation results
1530
+
1531
+ `--check-references`:: Validate referential integrity using dependency resolver
1532
+
1533
+ .Validating a manifest to ensure all dependencies are defined
1534
+ [example]
1535
+ ====
1536
+ Checking `REFERENCE FROM` and `USE FROM` references to ensure all dependencies
1537
+ are defined in EXPRESS schemas included in the manifest:
1538
+
1539
+ [source,sh]
1540
+ ----
1541
+ $ expressir manifest validate manifest.yaml --check-references --verbose
1542
+
1543
+ Validating manifest: manifest.yaml...
1544
+ Checking referential integrity...
1545
+ Validating referential integrity for 42 schemas...
1546
+
1547
+ USE FROM action_schema (in Activity_method_mim): ✓ action_schema.exp
1548
+ REFERENCE FROM basic_attribute_schema (in action_schema): ✓ basic_attribute_schema.exp
1549
+ ...
1550
+ USE FROM action_schema (in mim): ✓ action_schema.exp
1551
+ ...
1552
+ REFERENCE FROM support_resource_schema (in topology_schema): ✓ support_resource_schema.exp
1553
+ ✓ Manifest is valid
1554
+ Total schemas: 42
1555
+ Resolved schemas: 42
1556
+ ----
1557
+ ====
1558
+
1559
+
1560
+
1561
+ === Ruby API for schema manifests
1562
+
1563
+ ==== Loading manifests
1079
1564
 
1080
1565
  Load an existing schema manifest from a YAML file:
1081
1566
 
@@ -1094,7 +1579,7 @@ end
1094
1579
  schema_paths = manifest.schemas.map(&:path)
1095
1580
  ----
1096
1581
 
1097
- ===== Programmatically
1582
+ ==== Creating manifests
1098
1583
 
1099
1584
  Create a new schema manifest programmatically:
1100
1585
 
@@ -1117,32 +1602,7 @@ manifest.schemas << Expressir::SchemaManifestEntry.new(
1117
1602
  manifest.base_path = "/path/to/schemas"
1118
1603
  ----
1119
1604
 
1120
- ==== Schema manifest YAML format
1121
-
1122
- The schema manifest uses a structured YAML format:
1123
-
1124
- [source,yaml]
1125
- ----
1126
- schemas:
1127
- - path: schemas/resources/action_schema/action_schema.exp
1128
- id: action_schema
1129
- - path: schemas/resources/approval_schema/approval_schema.exp
1130
- id: approval_schema
1131
- - path: schemas/resources/date_time_schema/date_time_schema.exp
1132
- ----
1133
-
1134
- ===== Schema entry attributes
1135
-
1136
- Each schema entry in the manifest can have the following attributes:
1137
-
1138
- `path`:: (Required) The file path to the EXPRESS schema file
1139
- `id`:: (Optional) A unique identifier for the schema
1140
- `container_path`:: (Optional) Container path information
1141
-
1142
-
1143
- ==== Working with schema manifests
1144
-
1145
- ===== Saving manifests
1605
+ ==== Saving manifests
1146
1606
 
1147
1607
  Save a manifest to a file:
1148
1608
 
@@ -1155,7 +1615,7 @@ manifest.to_file("output_schemas.yml")
1155
1615
  manifest.save_to_path("/path/to/output/")
1156
1616
  ----
1157
1617
 
1158
- ===== Concatenating manifests
1618
+ ==== Concatenating manifests
1159
1619
 
1160
1620
  Combine multiple manifests:
1161
1621
 
@@ -1171,7 +1631,7 @@ combined_manifest = manifest1.concat(manifest2)
1171
1631
  combined_manifest = manifest1 + manifest2
1172
1632
  ----
1173
1633
 
1174
- ===== Using manifests with parsers
1634
+ ==== Using manifests with parsers
1175
1635
 
1176
1636
  Parse all schemas from a manifest:
1177
1637
 
@@ -1196,11 +1656,110 @@ repository = Expressir::Express::Parser.from_files(schema_paths) do |filename, s
1196
1656
  end
1197
1657
  ----
1198
1658
 
1199
- ==== Integration with CLI commands
1200
1659
 
1201
- Schema manifests are supported by several CLI commands:
1202
1660
 
1203
- ===== Benchmarking with manifests
1661
+ == LER packages
1662
+
1663
+ === General
1664
+
1665
+ LER (LutaML EXPRESS Repository) is a package format for distributing EXPRESS
1666
+ schemas and related resources in a single binary file.
1667
+
1668
+ EXPRESS schemas often utilize `REFERENCE FROM` or `USE FROM` statements to
1669
+ import definitions from other schemas, and those referenced schemas
1670
+ can deviate across different versions. Managing these dependencies
1671
+ is crucial for maintaining compatibility.
1672
+
1673
+ The LER package format helps encapsulate these dependencies, ensuring that all
1674
+ required schemas are included and versioned correctly, allowing the package
1675
+ to be used reliably in different environments.
1676
+
1677
+ LER packages have the `.ler` file extension and are essentially ZIP archives
1678
+ containing:
1679
+
1680
+ * EXPRESS schema files (`.exp`)
1681
+ * Metadata files (`metadata.yaml`)
1682
+ * pre-parsed model cache (serialized Ruby objects)
1683
+
1684
+
1685
+ === Creating a package
1686
+
1687
+ Expressir provides a command-line interface for creating LER packages from
1688
+ an EXPRESS manifest.
1689
+
1690
+ Expressir supports building LER packages from EXPRESS schemas using a
1691
+ manifest-based workflow.
1692
+
1693
+ **Using a manifest (recommended for production)**::
1694
+
1695
+ [source,sh]
1696
+ ----
1697
+ # Build from validated manifest
1698
+ expressir package build --manifest activity_manifest.yaml activity.ler \
1699
+ --name "Activity Module" \
1700
+ --validate
1701
+ ----
1702
+
1703
+ **Using auto-resolution (quick prototyping)**:
1704
+
1705
+ [source,sh]
1706
+ ----
1707
+ # Build from root schema with auto-resolution
1708
+ expressir package build schemas/activity/mim.exp activity.ler \
1709
+ --base-dirs ~/schemas/resources ~/schemas/modules \
1710
+ --name "Activity Module" \
1711
+ --validate
1712
+ ----
1713
+
1714
+ Complete manifest workflow:
1715
+
1716
+ [source,sh]
1717
+ ----
1718
+ # 1. Create manifest from root schema
1719
+ expressir manifest create schemas/activity/mim.exp \
1720
+ -o activity_manifest.yaml \
1721
+ --base-dirs ~/iso-10303/schemas \
1722
+ --name "Activity Module"
1723
+
1724
+ # 2. Edit manifest to add missing schema paths
1725
+
1726
+ # 3. Validate manifest
1727
+ expressir manifest validate activity_manifest.yaml
1728
+
1729
+ # 4. Build package from manifest
1730
+ expressir package build --manifest activity_manifest.yaml activity.ler
1731
+ ----
1732
+
1733
+
1734
+ Unresolved schemas appear without `path:` field. Edit the manifest to add missing paths.
1735
+
1736
+ [source,yaml]
1737
+ ----
1738
+ schemas:
1739
+ - name: action_schema
1740
+ path: /path/to/action_schema.exp
1741
+ - name: Activity_method_mim # Unresolved - no path
1742
+ ----
1743
+
1744
+
1745
+ .`package build --manifest` - Build from manifest
1746
+ [source,sh]
1747
+ ----
1748
+ expressir package build --manifest MANIFEST.yaml OUTPUT.ler [OPTIONS]
1749
+ ----
1750
+
1751
+ See link:docs/_pages/ler-packages#manifest-workflow[LER Packages documentation] for complete details.
1752
+
1753
+
1754
+
1755
+ == Benchmarking
1756
+
1757
+ === General
1758
+
1759
+ Expressir includes benchmarking tools to measure the performance of parsing and
1760
+ processing EXPRESS schemas.
1761
+
1762
+ === Benchmarking with manifests
1204
1763
 
1205
1764
  [source,sh]
1206
1765
  ----
@@ -1211,7 +1770,15 @@ expressir benchmark schemas.yml --verbose
1211
1770
  expressir benchmark-cache schemas.yml --cache_path /tmp/cache.bin
1212
1771
  ----
1213
1772
 
1214
- ===== Coverage analysis with manifests
1773
+
1774
+ == Coverage reporting
1775
+
1776
+ === General
1777
+
1778
+ Expressir provides coverage analysis tools to evaluate the documentation
1779
+ coverage of EXPRESS schemas.
1780
+
1781
+ === Coverage analysis with manifests
1215
1782
 
1216
1783
  [source,sh]
1217
1784
  ----
@@ -1224,7 +1791,7 @@ expressir coverage schemas.yml --format json --exclude=TYPE:SELECT
1224
1791
 
1225
1792
 
1226
1793
 
1227
- == Working with EXPRESS Changes
1794
+ == EXPRESS Changes
1228
1795
 
1229
1796
  === General
1230
1797
 
@@ -1236,7 +1803,7 @@ The Changes module enables:
1236
1803
 
1237
1804
  * Loading and saving schema change records from/to YAML files
1238
1805
  * Programmatic creation and manipulation of change records
1239
- * Smart edition handling (replace same version, add new version)
1806
+ * Smart version handling (replace same version, add new version)
1240
1807
  * Support for all change types: additions, modifications, deletions
1241
1808
  * Support for mapping changes in ARM/MIM schemas
1242
1809
  * Programmatic import from Express Engine comparison XML files
@@ -1278,7 +1845,7 @@ change_schema = Expressir::Commands::ChangesImportEengine.from_xml(
1278
1845
  )
1279
1846
 
1280
1847
  # Use the SchemaChange object
1281
- change_schema.editions.first.additions.each do |item|
1848
+ change_schema.versions.first.additions.each do |item|
1282
1849
  puts "#{item.type}: #{item.name}"
1283
1850
  puts " interfaced_items: #{item.interfaced_items}" if item.interfaced_items
1284
1851
  end
@@ -1287,9 +1854,9 @@ end
1287
1854
  change_schema.to_file("output.changes.yaml")
1288
1855
  ----
1289
1856
 
1290
- ==== Compare modes
1857
+ === Compare modes
1291
1858
 
1292
- ===== General
1859
+ ==== General
1293
1860
 
1294
1861
  Expressir automatically detects and parses all three Eengine XML modes.
1295
1862
 
@@ -1305,7 +1872,7 @@ puts mim_report.mode # => "mim"
1305
1872
  puts schema_report.mode # => "schema"
1306
1873
  ----
1307
1874
 
1308
- ===== Schema mode
1875
+ ==== Schema mode
1309
1876
 
1310
1877
  `<schema.changes>` with `<schema.additions>`, `<schema.modifications>`, `<schema.deletions>`
1311
1878
 
@@ -1327,7 +1894,7 @@ puts schema_report.mode # => "schema"
1327
1894
  ----
1328
1895
  ====
1329
1896
 
1330
- ===== ARM mode
1897
+ ==== ARM mode
1331
1898
 
1332
1899
  `<arm.changes>` root element with `<arm.additions>`,
1333
1900
  `<arm.modifications>`, and `<arm.deletions>` sections
@@ -1345,7 +1912,7 @@ puts schema_report.mode # => "schema"
1345
1912
  ====
1346
1913
 
1347
1914
 
1348
- ===== MIM mode
1915
+ ==== MIM mode
1349
1916
 
1350
1917
  `<mim.changes>` root element with `<mim.additions>`,
1351
1918
  `<mim.modifications>`, and `<mim.deletions>` sections
@@ -1362,7 +1929,7 @@ puts schema_report.mode # => "schema"
1362
1929
  ----
1363
1930
  ====
1364
1931
 
1365
- ==== Interface changes
1932
+ === Interface changes
1366
1933
 
1367
1934
  The eengine XML format tracks interface changes (USE_FROM, REFERENCE_FROM) with
1368
1935
  the `interfaced.items` attribute. This attribute lists the specific items being
@@ -1392,8 +1959,8 @@ This will be converted to EXPRESS Changes YAML as:
1392
1959
  [source,yaml]
1393
1960
  ----
1394
1961
  schema: aic_csg
1395
- editions:
1396
- - version: '2'
1962
+ versions:
1963
+ - version: 2
1397
1964
  description: Changes from eengine comparison
1398
1965
  additions:
1399
1966
  - type: USE_FROM
@@ -1425,7 +1992,7 @@ end
1425
1992
  ----
1426
1993
 
1427
1994
 
1428
- ==== Supported change types
1995
+ === Supported change types
1429
1996
 
1430
1997
  The import command recognizes all standard EXPRESS construct types:
1431
1998
 
@@ -1453,14 +2020,14 @@ change_schema = Expressir::Changes::SchemaChange.from_file("schema.changes.yaml"
1453
2020
  # Access schema name
1454
2021
  puts "Schema: #{change_schema.schema}"
1455
2022
 
1456
- # Iterate through change editions
1457
- change_schema.editions.each do |edition|
1458
- puts "Version #{edition.version}: #{edition.description}"
2023
+ # Iterate through change versions
2024
+ change_schema.versions.each do |version|
2025
+ puts "Version #{version.version}: #{version.description}"
1459
2026
 
1460
2027
  # Access changes by type
1461
- puts " Additions: #{edition.additions.size}" if edition.additions
1462
- puts " Modifications: #{edition.modifications.size}" if edition.modifications
1463
- puts " Deletions: #{edition.deletions.size}" if edition.deletions
2028
+ puts " Additions: #{version.additions.size}" if version.additions
2029
+ puts " Modifications: #{version.modifications.size}" if version.modifications
2030
+ puts " Deletions: #{version.deletions.size}" if version.deletions
1464
2031
  end
1465
2032
  ----
1466
2033
 
@@ -1485,14 +2052,14 @@ modified_function = Expressir::Changes::ItemChange.new(
1485
2052
  description: "Updated parameters"
1486
2053
  )
1487
2054
 
1488
- # Add a change edition
2055
+ # Add a change version
1489
2056
  changes = {
1490
2057
  additions: [new_entity],
1491
2058
  modifications: [modified_function],
1492
2059
  deletions: []
1493
2060
  }
1494
2061
 
1495
- change_schema.add_or_update_edition(
2062
+ change_schema.add_or_update_version(
1496
2063
  "2",
1497
2064
  "Added new entity and modified function",
1498
2065
  changes
@@ -1504,10 +2071,10 @@ change_schema.to_file("my_schema.changes.yaml")
1504
2071
 
1505
2072
  === Updating existing change files
1506
2073
 
1507
- The `add_or_update_edition` method provides smart handling:
2074
+ The `add_or_update_version` method provides smart handling:
1508
2075
 
1509
- * **Same version**: Replaces the existing edition
1510
- * **Different version**: Adds a new edition
2076
+ * **Same version**: Replaces the existing version
2077
+ * **Different version**: Adds a new version
1511
2078
 
1512
2079
  [source,ruby]
1513
2080
  ----
@@ -1520,10 +2087,10 @@ changes = {
1520
2087
  Expressir::Changes::ItemChange.new(type: "TYPE", name: "updated_type")
1521
2088
  ]
1522
2089
  }
1523
- change_schema.add_or_update_edition("3", "Modified type definition", changes)
2090
+ change_schema.add_or_update_version("3", "Modified type definition", changes)
1524
2091
 
1525
2092
  # Or replace existing version
1526
- change_schema.add_or_update_edition("2", "Revised description", changes)
2093
+ change_schema.add_or_update_version("2", "Revised description", changes)
1527
2094
 
1528
2095
  # Save changes
1529
2096
  change_schema.to_file("schema.changes.yaml")
@@ -1547,9 +2114,9 @@ item = Expressir::Changes::ItemChange.new(
1547
2114
  )
1548
2115
  ----
1549
2116
 
1550
- === Change edition fields
2117
+ === Change version fields
1551
2118
 
1552
- Change editions support categorizing changes into:
2119
+ Change versions support categorizing changes into:
1553
2120
 
1554
2121
  `additions`:: New elements added to the schema
1555
2122
  `modifications`:: Existing elements that were modified
@@ -1559,7 +2126,7 @@ Change editions support categorizing changes into:
1559
2126
 
1560
2127
  [source,ruby]
1561
2128
  ----
1562
- edition = Expressir::Changes::EditionChange.new(
2129
+ version = Expressir::Changes::VersionChange.new(
1563
2130
  version: "2",
1564
2131
  description: "Added support for new functionality",
1565
2132
  additions: [item1, item2],
@@ -1586,8 +2153,8 @@ mapping_change = Expressir::Changes::MappingChange.new(
1586
2153
  ----
1587
2154
  ---
1588
2155
  schema: support_resource_schema
1589
- editions:
1590
- - version: '2'
2156
+ versions:
2157
+ - version: 2
1591
2158
  description: |-
1592
2159
  The definitions of the following EXPRESS entity data types were modified:
1593
2160
 
@@ -1600,7 +2167,7 @@ editions:
1600
2167
  modifications:
1601
2168
  - type: FUNCTION
1602
2169
  name: bag_to_set
1603
- - version: '4'
2170
+ - version: 4
1604
2171
  description: |-
1605
2172
  Added support for external element references.
1606
2173
  additions: