expressir 2.1.30 → 2.2.0

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 (165) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/docs.yml +99 -0
  3. data/.github/workflows/links.yml +100 -0
  4. data/.github/workflows/rake.yml +4 -0
  5. data/.github/workflows/release.yml +11 -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 +267 -53
  10. data/Gemfile +2 -1
  11. data/README.adoc +993 -55
  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/formatter/formatter-architecture.adoc +401 -0
  27. data/docs/_guides/index.adoc +165 -0
  28. data/docs/_guides/ler/creating-packages.adoc +664 -0
  29. data/docs/_guides/ler/index.adoc +305 -0
  30. data/docs/_guides/ler/loading-packages.adoc +707 -0
  31. data/docs/_guides/ler/package-formats.adoc +748 -0
  32. data/docs/_guides/ler/querying-packages.adoc +826 -0
  33. data/docs/_guides/ler/validating-packages.adoc +750 -0
  34. data/docs/_guides/liquid/basic-templates.adoc +813 -0
  35. data/docs/_guides/liquid/documentation-generation.adoc +1042 -0
  36. data/docs/_guides/liquid/drops-reference.adoc +829 -0
  37. data/docs/_guides/liquid/filters-and-tags.adoc +912 -0
  38. data/docs/_guides/liquid/index.adoc +468 -0
  39. data/docs/_guides/manifests/creating-manifests.adoc +483 -0
  40. data/docs/_guides/manifests/index.adoc +307 -0
  41. data/docs/_guides/manifests/resolving-manifests.adoc +557 -0
  42. data/docs/_guides/manifests/validating-manifests.adoc +713 -0
  43. data/docs/_guides/ruby-api/formatting-schemas.adoc +605 -0
  44. data/docs/_guides/ruby-api/index.adoc +257 -0
  45. data/docs/_guides/ruby-api/parsing-files.adoc +421 -0
  46. data/docs/_guides/ruby-api/search-engine.adoc +609 -0
  47. data/docs/_guides/ruby-api/working-with-repository.adoc +577 -0
  48. data/docs/_pages/data-model.adoc +665 -0
  49. data/docs/_pages/express-language.adoc +506 -0
  50. data/docs/_pages/getting-started.adoc +414 -0
  51. data/docs/_pages/index.adoc +116 -0
  52. data/docs/_pages/introduction.adoc +256 -0
  53. data/docs/_pages/ler-packages.adoc +837 -0
  54. data/docs/_pages/parsers.adoc +709 -0
  55. data/docs/_pages/schema-manifests.adoc +431 -0
  56. data/docs/_references/index.adoc +228 -0
  57. data/docs/_tutorials/creating-ler-package.adoc +735 -0
  58. data/docs/_tutorials/documentation-coverage.adoc +795 -0
  59. data/docs/_tutorials/index.adoc +221 -0
  60. data/docs/_tutorials/liquid-templates.adoc +806 -0
  61. data/docs/_tutorials/parsing-your-first-schema.adoc +522 -0
  62. data/docs/_tutorials/querying-schemas.adoc +751 -0
  63. data/docs/_tutorials/working-with-multiple-schemas.adoc +676 -0
  64. data/docs/index.adoc +242 -0
  65. data/docs/lychee.toml +87 -0
  66. data/examples/demo_ler_usage.sh +86 -0
  67. data/examples/ler/README.md +111 -0
  68. data/examples/ler/simple_example.ler +0 -0
  69. data/examples/ler/simple_schema.exp +33 -0
  70. data/examples/ler_build.rb +75 -0
  71. data/examples/ler_cli.rb +79 -0
  72. data/examples/ler_demo_complete.rb +276 -0
  73. data/examples/ler_query.rb +91 -0
  74. data/examples/ler_query_examples.rb +305 -0
  75. data/examples/ler_stats.rb +81 -0
  76. data/examples/phase3_demo.rb +159 -0
  77. data/examples/query_demo_simple.rb +131 -0
  78. data/expressir.gemspec +4 -2
  79. data/lib/expressir/benchmark.rb +6 -6
  80. data/lib/expressir/cli.rb +21 -4
  81. data/lib/expressir/commands/format.rb +28 -0
  82. data/lib/expressir/commands/manifest.rb +427 -0
  83. data/lib/expressir/commands/package.rb +1274 -0
  84. data/lib/expressir/commands/validate.rb +70 -37
  85. data/lib/expressir/commands/validate_ascii.rb +607 -0
  86. data/lib/expressir/commands/validate_load.rb +88 -0
  87. data/lib/expressir/coverage.rb +15 -11
  88. data/lib/expressir/express/builder.rb +350 -0
  89. data/lib/expressir/express/builders/attribute_decl_builder.rb +38 -0
  90. data/lib/expressir/express/builders/built_in_builder.rb +88 -0
  91. data/lib/expressir/express/builders/constant_builder.rb +115 -0
  92. data/lib/expressir/express/builders/declaration_builder.rb +24 -0
  93. data/lib/expressir/express/builders/derive_clause_builder.rb +16 -0
  94. data/lib/expressir/express/builders/derived_attr_builder.rb +28 -0
  95. data/lib/expressir/express/builders/domain_rule_builder.rb +21 -0
  96. data/lib/expressir/express/builders/entity_decl_builder.rb +108 -0
  97. data/lib/expressir/express/builders/explicit_attr_builder.rb +52 -0
  98. data/lib/expressir/express/builders/expression_builder.rb +453 -0
  99. data/lib/expressir/express/builders/function_decl_builder.rb +84 -0
  100. data/lib/expressir/express/builders/helpers.rb +148 -0
  101. data/lib/expressir/express/builders/interface_builder.rb +171 -0
  102. data/lib/expressir/express/builders/inverse_attr_builder.rb +45 -0
  103. data/lib/expressir/express/builders/inverse_attr_type_builder.rb +36 -0
  104. data/lib/expressir/express/builders/inverse_clause_builder.rb +16 -0
  105. data/lib/expressir/express/builders/literal_builder.rb +107 -0
  106. data/lib/expressir/express/builders/procedure_decl_builder.rb +80 -0
  107. data/lib/expressir/express/builders/qualifier_builder.rb +128 -0
  108. data/lib/expressir/express/builders/reference_builder.rb +27 -0
  109. data/lib/expressir/express/builders/rule_decl_builder.rb +95 -0
  110. data/lib/expressir/express/builders/schema_body_decl_builder.rb +22 -0
  111. data/lib/expressir/express/builders/schema_decl_builder.rb +62 -0
  112. data/lib/expressir/express/builders/schema_version_builder.rb +40 -0
  113. data/lib/expressir/express/builders/simple_id_builder.rb +26 -0
  114. data/lib/expressir/express/builders/statement_builder.rb +250 -0
  115. data/lib/expressir/express/builders/subtype_constraint_builder.rb +188 -0
  116. data/lib/expressir/express/builders/syntax_builder.rb +19 -0
  117. data/lib/expressir/express/builders/token_builder.rb +15 -0
  118. data/lib/expressir/express/builders/type_builder.rb +264 -0
  119. data/lib/expressir/express/builders/type_decl_builder.rb +32 -0
  120. data/lib/expressir/express/builders/unique_clause_builder.rb +22 -0
  121. data/lib/expressir/express/builders/unique_rule_builder.rb +36 -0
  122. data/lib/expressir/express/builders/where_clause_builder.rb +22 -0
  123. data/lib/expressir/express/builders.rb +43 -0
  124. data/lib/expressir/express/error.rb +18 -2
  125. data/lib/expressir/express/formatter.rb +23 -1509
  126. data/lib/expressir/express/formatters/data_types_formatter.rb +317 -0
  127. data/lib/expressir/express/formatters/declarations_formatter.rb +689 -0
  128. data/lib/expressir/express/formatters/expressions_formatter.rb +160 -0
  129. data/lib/expressir/express/formatters/literals_formatter.rb +46 -0
  130. data/lib/expressir/express/formatters/references_formatter.rb +42 -0
  131. data/lib/expressir/express/formatters/remark_formatter.rb +296 -0
  132. data/lib/expressir/express/formatters/remark_item_formatter.rb +25 -0
  133. data/lib/expressir/express/formatters/statements_formatter.rb +224 -0
  134. data/lib/expressir/express/formatters/supertype_expressions_formatter.rb +48 -0
  135. data/lib/expressir/express/parser.rb +155 -7
  136. data/lib/expressir/express/pretty_formatter.rb +624 -0
  137. data/lib/expressir/express/remark_attacher.rb +1155 -0
  138. data/lib/expressir/express/resolve_references_model_visitor.rb +1 -0
  139. data/lib/expressir/express/streaming_builder.rb +467 -0
  140. data/lib/expressir/express/transformer/remark_handling.rb +196 -0
  141. data/lib/expressir/manifest/resolver.rb +213 -0
  142. data/lib/expressir/manifest/validator.rb +195 -0
  143. data/lib/expressir/model/declarations/entity.rb +6 -0
  144. data/lib/expressir/model/dependency_resolver.rb +270 -0
  145. data/lib/expressir/model/identifier.rb +1 -1
  146. data/lib/expressir/model/indexes/entity_index.rb +103 -0
  147. data/lib/expressir/model/indexes/reference_index.rb +148 -0
  148. data/lib/expressir/model/indexes/type_index.rb +149 -0
  149. data/lib/expressir/model/interface_validator.rb +384 -0
  150. data/lib/expressir/model/model_element.rb +30 -2
  151. data/lib/expressir/model/remark_info.rb +51 -0
  152. data/lib/expressir/model/repository.rb +400 -5
  153. data/lib/expressir/model/repository_validator.rb +295 -0
  154. data/lib/expressir/model/search_engine.rb +574 -0
  155. data/lib/expressir/model.rb +4 -94
  156. data/lib/expressir/package/builder.rb +200 -0
  157. data/lib/expressir/package/metadata.rb +81 -0
  158. data/lib/expressir/package/reader.rb +165 -0
  159. data/lib/expressir/schema_manifest.rb +11 -1
  160. data/lib/expressir/version.rb +1 -1
  161. data/lib/expressir.rb +20 -3
  162. metadata +168 -9
  163. data/docs/benchmarking.adoc +0 -107
  164. data/docs/liquid_drops.adoc +0 -1547
  165. data/lib/expressir/express/visitor.rb +0 -2815
data/README.adoc CHANGED
@@ -30,6 +30,132 @@ Expressir consists of 3 parts:
30
30
  // ** OMG UML 2 for Eclipse (XMI 2.1)
31
31
 
32
32
 
33
+ == Features
34
+
35
+ === Remark preservation
36
+
37
+ Expressir fully preserves EXPRESS remarks (comments) during parsing and formatting, maintaining them in their original positions:
38
+
39
+ ==== Preamble remarks
40
+
41
+ Remarks between a scope declaration and its first child are preserved as preamble remarks:
42
+
43
+ [source,express]
44
+ ----
45
+ SCHEMA example;
46
+ -- This is a preamble remark
47
+ -- It appears after SCHEMA but before declarations
48
+
49
+ ENTITY person;
50
+ -- Entity preamble remark
51
+ name : STRING;
52
+ END_ENTITY;
53
+
54
+ END_SCHEMA;
55
+ ----
56
+
57
+ ==== Inline tail remarks
58
+
59
+ Remarks on the same line as attribute or enumeration item declarations:
60
+
61
+ [source,express]
62
+ ----
63
+ ENTITY person;
64
+ name : STRING; -- Inline remark for name attribute
65
+ age : INTEGER; -- Inline remark for age attribute
66
+ END_ENTITY;
67
+
68
+ TYPE status = ENUMERATION OF
69
+ (active, -- Active status
70
+ inactive, -- Inactive status
71
+ pending); -- Pending status
72
+ END_TYPE;
73
+ ----
74
+
75
+ ==== END_* scope remarks
76
+
77
+ Remarks on END_TYPE, END_ENTITY, END_SCHEMA, etc. lines:
78
+
79
+ [source,express]
80
+ ----
81
+ TYPE status = ENUMERATION OF
82
+ (active,
83
+ inactive);
84
+ END_TYPE; -- Status enumeration type
85
+
86
+ ENTITY person;
87
+ name : STRING;
88
+ END_ENTITY; -- Person entity
89
+
90
+ END_SCHEMA; -- schema_name
91
+ ----
92
+
93
+ ==== Unicode support
94
+
95
+ All remark types support full Unicode content:
96
+
97
+ [source,express]
98
+ ----
99
+ SCHEMA test;
100
+ -- 日本語、中文、한글 in remarks
101
+
102
+ ENTITY person;
103
+ name : STRING; -- Name in Japanese: 名前
104
+ END_ENTITY;
105
+
106
+ END_SCHEMA; -- test
107
+ ----
108
+
109
+ For implementation details, see link:docs/ARCHITECTURE.md#remark-attachment-system[Remark Attachment System].
110
+
111
+
112
+ == Performance: Parsanol Integration
113
+
114
+ Expressir uses the link:https://github.com/parsanol/parsanol-ruby[Parsanol] gem for high-performance parsing when available.
115
+
116
+ === Performance Comparison
117
+
118
+ [cols="3,2,2,3"]
119
+ |===
120
+ | Mode | Time | Speedup | Notes
121
+
122
+ | Ruby (Parsanol) | 3036 ms | 1x (baseline) | Pure Ruby parsing
123
+ | Native Batch (Parsanol) | 153 ms | 19.9x faster | AST via u64 array transfer
124
+ | Native ZeroCopy (Parsanol) | 106 ms | 28.7x faster | Zero-copy with source positions
125
+ |===
126
+
127
+ === Features
128
+
129
+ When Parsanol is installed:
130
+
131
+ * **18-44x faster parsing** - Rust native backend
132
+ * **99.5% fewer allocations** - Arena-based AST construction
133
+ * **Source position tracking** - Slice objects for error reporting
134
+ * **Streaming Builder API** - Zero-allocation custom parsing
135
+
136
+ === Usage
137
+
138
+ Expressir automatically uses Parsanol when available:
139
+
140
+ [source,ruby]
141
+ ----
142
+ # Automatically uses Parsanol native parser when available
143
+ repo = Expressir::Express::Parser.from_file("geometry.exp")
144
+
145
+ # Check if native parser is being used
146
+ if Parsanol::Native.available?
147
+ puts "Using Parsanol (Rust parser)"
148
+ end
149
+ ----
150
+
151
+ For maximum performance, ensure the Parsanol gem is installed:
152
+
153
+ [source,sh]
154
+ ----
155
+ gem install parsanol
156
+ ----
157
+
158
+
33
159
  == Installation
34
160
 
35
161
  Add this line to your application's `Gemfile`:
@@ -80,7 +206,8 @@ Commands:
80
206
  expressir clean PATH # Strip remarks and prettify EXPRESS schema at PATH
81
207
  expressir format PATH # pretty print EXPRESS schema located at PATH
82
208
  expressir help [COMMAND] # Describe available commands or one specific command
83
- expressir validate *PATH # validate EXPRESS schema located at PATH
209
+ expressir validate load *PATH # validate EXPRESS schema located at PATH
210
+ expressir validate ascii PATH # Validate EXPRESS files for ASCII-only content (excluding remarks)
84
211
  expressir coverage *PATH # List EXPRESS entities and check documentation coverage
85
212
  expressir version # Expressir Version
86
213
  ----
@@ -97,9 +224,255 @@ expressir format schemas/resources/action_schema/action_schema.exp
97
224
  ----
98
225
 
99
226
  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
227
+
228
+ . Parses the EXPRESS schema
229
+ . Formats it with consistent indentation and spacing
230
+ . Outputs the formatted schema to stdout
231
+
232
+ === Pretty print with ELF compliance
233
+
234
+ The `PrettyFormatter` class provides ELF (EXPRESS Language Foundation) compliant
235
+ pretty printing with configurable formatting options. This formatter follows the
236
+ https://www.express-language-foundation.org/pretty-print-spec/[ELF Pretty Print specification].
237
+
238
+ ==== Using PrettyFormatter in Ruby
239
+
240
+ [source,ruby]
241
+ ----
242
+ # Basic usage - formats with default settings
243
+ repository = Expressir::Express::Parser.from_file("schema.exp")
244
+ formatter = Expressir::Express::PrettyFormatter.new
245
+ formatted = formatter.format(repository)
246
+ puts formatted
247
+ ----
248
+
249
+ ==== Configuration options
250
+
251
+ The PrettyFormatter supports several configuration options to customize the output.
252
+
253
+ [source,ruby]
254
+ ----
255
+ formatter = Expressir::Express::PrettyFormatter.new(
256
+ indent: 4, # Spaces per indentation level (default: 4)
257
+ line_length: 80, # Maximum line length (default: nil)
258
+ provenance: true, # Include provenance info (default: true)
259
+ provenance_name: "MyTool", # Tool name (default: "Expressir")
260
+ provenance_version: "1.0.0", # Tool version (default: Expressir::VERSION)
261
+ no_remarks: false # Suppress remarks (default: false)
262
+ )
263
+ ----
264
+
265
+ [options="header"]
266
+ |===
267
+ | Option | Type | Default | Description
268
+
269
+ | `indent`
270
+ | Integer
271
+ | `4`
272
+ | Number of spaces per indentation level
273
+
274
+ | `line_length`
275
+ | Integer or nil
276
+ | `nil`
277
+ | Maximum line length (not yet enforced)
278
+
279
+ | `provenance`
280
+ | Boolean
281
+ | `true`
282
+ | Include provenance information in output
283
+
284
+ | `provenance_name`
285
+ | String
286
+ | `"Expressir"`
287
+ | Tool name for provenance
288
+
289
+ | `provenance_version`
290
+ | String
291
+ | `Expressir::VERSION`
292
+ | Tool version for provenance
293
+
294
+ | `no_remarks`
295
+ | Boolean
296
+ | `false`
297
+ | Suppress remarks from source schema
298
+ |===
299
+
300
+ ==== Environment variable configuration
301
+
302
+ Configuration can be overridden using environment variables. Environment variables
303
+ take precedence over defaults but are overridden by explicit options:
304
+
305
+ [source,sh]
306
+ ----
307
+ # Set environment variables
308
+ export EXPRESSIR_INDENT=2
309
+ export EXPRESSIR_LINE_LENGTH=100
310
+ export EXPRESSIR_PROVENANCE=false
311
+ export EXPRESSIR_PROVENANCE_NAME="CustomTool"
312
+ export EXPRESSIR_PROVENANCE_VERSION="2.0.0"
313
+
314
+ # These will be used unless overridden by options
315
+ ruby my_formatter.rb
316
+ ----
317
+
318
+ [options="header"]
319
+ |===
320
+ | Environment Variable | Description
321
+
322
+ | `EXPRESSIR_INDENT`
323
+ | Indentation width (spaces)
324
+
325
+ | `EXPRESSIR_LINE_LENGTH`
326
+ | Maximum line length
327
+
328
+ | `EXPRESSIR_PROVENANCE`
329
+ | Enable/disable provenance (`true`/`false`)
330
+
331
+ | `EXPRESSIR_PROVENANCE_NAME`
332
+ | Tool name for provenance
333
+
334
+ | `EXPRESSIR_PROVENANCE_VERSION`
335
+ | Tool version for provenance
336
+ |===
337
+
338
+ The configuration follows a MECE (Mutually Exclusive, Collectively Exhaustive)
339
+ hierarchy: **Options > ENV > Defaults**
340
+
341
+ ==== Key features
342
+
343
+ The PrettyFormatter provides several enhancements over the standard formatter:
344
+
345
+ CONSTANT alignment:: Constants in CONSTANT blocks are aligned at both the colon
346
+ and assignment operator positions for improved readability.
347
+ +
348
+ [example]
349
+ ====
350
+ [source]
351
+ ----
352
+ CONSTANT
353
+ short_name : INTEGER := 1;
354
+ longer_name : STRING := 'test';
355
+ x : REAL := 3.14;
356
+ END_CONSTANT;
357
+ ----
358
+ ====
359
+
360
+ Provenance information:: Automatically includes metadata about the formatting
361
+ tool and parameters used, aiding in reproducibility.
362
+ +
363
+ [example]
364
+ ====
365
+ [source]
366
+ ----
367
+ (*
368
+ Generated by: Expressir version 2.1.31
369
+ Format parameters: indent: 4
370
+ *)
371
+ ----
372
+ ====
373
+
374
+ Configurable indentation:: Supports custom indentation width (2, 4, 8 spaces, etc.)
375
+ to match project coding standards.
376
+
377
+ Preamble support:: Preserves and formats source-level remarks that appear before
378
+ the first SCHEMA declaration.
379
+
380
+ ==== Comparison with standard Formatter
381
+
382
+ [options="header"]
383
+ |===
384
+ | Feature | Formatter | PrettyFormatter
385
+
386
+ | Indentation
387
+ | 2 spaces (fixed)
388
+ | Configurable (default: 4)
389
+
390
+ | CONSTANT alignment
391
+ | No
392
+ | Yes (colons and assignments)
393
+
394
+ | Provenance
395
+ | No
396
+ | Yes (configurable)
397
+
398
+ | Preamble formatting
399
+ | No
400
+ | Yes
401
+
402
+ | Line length enforcement
403
+ | No
404
+ | Planned (not yet implemented)
405
+
406
+ | ELF compliant
407
+ | No
408
+ | Yes
409
+
410
+ | Configuration via ENV
411
+ | No
412
+ | Yes
413
+ |===
414
+
415
+ ==== Example usage
416
+
417
+ .Formatting with custom settings
418
+ [example]
419
+ ====
420
+ [source,ruby]
421
+ ----
422
+ # Parse schema
423
+ repository = Expressir::Express::Parser.from_file("examples/ler/simple_schema.exp")
424
+
425
+ # Format with custom indentation and provenance
426
+ formatter = Expressir::Express::PrettyFormatter.new(
427
+ indent: 2,
428
+ provenance_name: "MyFormatter",
429
+ provenance_version: "1.0.0"
430
+ )
431
+
432
+ formatted = formatter.format(repository)
433
+
434
+ # Save to file
435
+ File.write("formatted_schema.exp", formatted)
436
+ ----
437
+ ====
438
+
439
+ .Formatting without provenance
440
+ [example]
441
+ ====
442
+ [source,ruby]
443
+ ----
444
+ # Format without provenance information
445
+ formatter = Expressir::Express::PrettyFormatter.new(provenance: false)
446
+ repository = Expressir::Express::Parser.from_file("schema.exp")
447
+ formatted = formatter.format(repository)
448
+
449
+ # Output is clean without metadata comments
450
+ puts formatted
451
+ ----
452
+ ====
453
+
454
+ .Round-trip formatting verification
455
+ [example]
456
+ ====
457
+ [source,ruby]
458
+ ----
459
+ # Format a schema
460
+ original = Expressir::Express::Parser.from_file("schema.exp")
461
+ formatter = Expressir::Express::PrettyFormatter.new
462
+
463
+ # Format once
464
+ formatted1 = formatter.format(original)
465
+
466
+ # Parse the formatted output
467
+ File.write("temp.exp", formatted1)
468
+ reparsed = Expressir::Express::Parser.from_file("temp.exp")
469
+
470
+ # Format again - should be identical (stable formatting)
471
+ formatted2 = formatter.format(reparsed)
472
+
473
+ puts "Formatting is stable" if formatted1 == formatted2
474
+ ----
475
+ ====
103
476
 
104
477
  === Clean schema
105
478
 
@@ -124,29 +497,136 @@ expressir clean schemas/resources/action_schema/action_schema.exp --output clean
124
497
 
125
498
  === Validate schema
126
499
 
127
- The `validate` command performs validation checks on EXPRESS schema files.
500
+ The `validate load` command performs validation checks on EXPRESS schema files.
128
501
 
129
502
  It verifies:
130
503
 
131
- . That the schema can be parsed correctly
504
+ . That the schema can be parsed correctly into the EXPRESS data model
132
505
  . That the schema includes a version string
133
506
 
134
507
  [source, sh]
135
508
  ----
136
509
  # Validate a single schema
137
- expressir validate schemas/resources/action_schema/action_schema.exp
510
+ expressir validate load schemas/resources/action_schema/action_schema.exp
138
511
 
139
512
  # Validate multiple schemas
140
- expressir validate schemas/resources/action_schema/action_schema.exp schemas/resources/approval_schema/approval_schema.exp
513
+ expressir validate load schemas/resources/action_schema/action_schema.exp schemas/resources/approval_schema/approval_schema.exp
514
+
515
+ # Validate schemas from a schema manifest YAML
516
+ expressir validate load schemas.yml
141
517
  ----
142
518
 
143
519
  The command reports any schemas that:
144
520
 
145
- * Failed to parse
521
+ * Failed to parse into the EXPRESS data model
146
522
  * Are missing a version string
147
523
 
148
524
  If all validations pass, it will display "Validation passed for all EXPRESS schemas."
149
525
 
526
+ === Validate ASCII content
527
+
528
+ The `validate ascii` command validates that EXPRESS schema files contain only
529
+ ASCII characters outside of remarks. This ensures compatibility with systems
530
+ that don't support Unicode, while allowing Unicode in documentation comments.
531
+
532
+ [source, sh]
533
+ ----
534
+ # Validate a single file
535
+ expressir validate ascii schema.exp
536
+
537
+ # Validate schema manifest YAML
538
+ expressir validate ascii schemas.yml
539
+
540
+ # Validate directory (non-recursive)
541
+ expressir validate ascii schemas/
542
+
543
+ # Validate directory recursively
544
+ expressir validate ascii schemas/ --recursive
545
+
546
+ # Output in YAML format
547
+ expressir validate ascii schemas/ --yaml
548
+
549
+ # Check remarks as well (include remarks in validation)
550
+ expressir validate ascii schema.exp --check-remarks
551
+ ----
552
+
553
+ The command checks that all EXPRESS code (excluding remarks) contains only
554
+ 7-bit ASCII characters. Tagged remarks (both embedded `(* ... *)` and tail
555
+ `-- ...` comments) are excluded from validation, allowing documentation to
556
+ contain Unicode without triggering errors.
557
+
558
+ [options="header"]
559
+ |===
560
+ | Option | Description
561
+
562
+ | `--recursive`, `-r`
563
+ | Validate EXPRESS files under the specified path recursively
564
+
565
+ | `--yaml`, `-y`
566
+ | Output results in YAML format for programmatic processing
567
+
568
+ | `--check-remarks`
569
+ | Include remarks in ASCII validation (default: false, remarks are excluded)
570
+ |===
571
+
572
+ The validator provides:
573
+
574
+ * Detailed violation reports with line and column numbers
575
+ * Replacement suggestions (AsciiMath for math symbols, ISO 10303-11 encoding for others)
576
+ * Summary statistics
577
+ * Visual indicators for non-ASCII sequences
578
+
579
+ This command is particularly useful before exporting schemas to formats that
580
+ don't support Unicode, such as EEP (Express Engine Parser) and eengine (Express
581
+ Engine).
582
+
583
+
584
+ [example]
585
+ ====
586
+ [source, sh]
587
+ ----
588
+ $ expressir validate ascii spec/fixtures/validate_ascii/non_ascii_in_code.exp
589
+
590
+ spec/fixtures/validate_ascii/non_ascii_in_code.exp:
591
+ Line 3, Column 9:
592
+ ENTITY 製品;
593
+ ^^ Non-ASCII sequence
594
+ "製" - Hex: 0x88fd, UTF-8 bytes: 0xe8 0xa3 0xbd
595
+ Replacement: ISO 10303-11: "000088FD"
596
+ "品" - Hex: 0x54c1, UTF-8 bytes: 0xe5 0x93 0x81
597
+ Replacement: ISO 10303-11: "000054C1"
598
+
599
+ ...
600
+ Line 10, Column 24:
601
+ symbol : STRING := 'μ';
602
+ ^ Non-ASCII sequence
603
+ "μ" - Hex: 0x3bc, UTF-8 bytes: 0xce 0xbc
604
+ Replacement: AsciiMath: mu
605
+
606
+ ...
607
+
608
+ Found 7 non-ASCII sequence(s) in non_ascii_in_code.exp
609
+
610
+ Summary:
611
+ Scanned 1 EXPRESS file(s)
612
+ Found 7 non-ASCII sequence(s) in 1 file(s)
613
+
614
+ ╭──────────────────────────────────────────────────────────────────────────╮
615
+ │ Non-ASCII Characters Summary │
616
+ ├──────────────────────────┬─────────────┬────────────────────┬────────────┤
617
+ │ File │ Symbol │ Replacement │ Occurrenc… │
618
+ ├──────────────────────────┼─────────────┼────────────────────┼────────────┤
619
+ │ validate_ascii/non_asci… │ "製" (0x88… │ ISO 10303-11: "00… │ 1 │
620
+ │ validate_ascii/non_asci… │ "品" (0x54… │ ISO 10303-11: "00… │ 1 │
621
+ │ ... │ │ │ │
622
+ │ validate_ascii/non_asci… │ "μ" (0x3bc) │ AsciiMath: mu │ 1 │
623
+ │ ... │ │ │ │
624
+ │ TOTAL │ 10 unique │ — │ 11 │
625
+ ╰──────────────────────────┴─────────────┴────────────────────┴────────────╯
626
+ ----
627
+ ====
628
+
629
+
150
630
  === Version
151
631
 
152
632
  The `version` command displays the current version of the Expressir gem.
@@ -1026,9 +1506,10 @@ all_entities = Expressir::Coverage.find_entities(schema)
1026
1506
  puts "Found #{all_entities.size} entities in schema #{schema.id}"
1027
1507
  ----
1028
1508
 
1029
- === EXPRESS schema manifest
1030
1509
 
1031
- ==== General
1510
+ == EXPRESS schema manifests
1511
+
1512
+ === General
1032
1513
 
1033
1514
  The EXPRESS schema manifest is a file format defined by ELF at
1034
1515
  https://www.expresslang.org/docs[EXPRESS schema manifest specification].
@@ -1045,8 +1526,30 @@ The `SchemaManifest` class allows you to:
1045
1526
  * Save manifest configurations to files
1046
1527
 
1047
1528
 
1529
+ === File format
1530
+
1531
+ The schema manifest uses a structured YAML format:
1532
+
1533
+ [source,yaml]
1534
+ ----
1535
+ schemas:
1536
+ - path: schemas/resources/action_schema/action_schema.exp
1537
+ id: action_schema
1538
+ - path: schemas/resources/approval_schema/approval_schema.exp
1539
+ id: approval_schema
1540
+ - path: schemas/resources/date_time_schema/date_time_schema.exp
1541
+ id: date_time_schema
1542
+ ----
1543
+
1544
+ Each schema entry in the manifest can have the following attributes:
1545
+
1546
+ `path`:: (Required) The file path to the EXPRESS schema file
1547
+ `id`:: (Optional) A unique identifier for the schema
1548
+ `container_path`:: (Optional) Container path information
1549
+
1550
+
1048
1551
  [example]
1049
- .Example project structure with schema manifest:
1552
+ .Example project structure with schema manifest
1050
1553
  ====
1051
1554
  [source]
1052
1555
  ----
@@ -1073,9 +1576,362 @@ schemas:
1073
1576
  ----
1074
1577
  ====
1075
1578
 
1076
- ==== Creating a schema manifest
1077
1579
 
1078
- ===== From a YAML file
1580
+ === Commands for schema manifests
1581
+
1582
+ ==== Creating a manifest from a root schema
1583
+
1584
+ The `manifest create` command generates a schema manifest YAML file by
1585
+ resolving all referenced schemas starting from a specified root schema file.
1586
+
1587
+ .`manifest create` - Generate schema manifest
1588
+ [source,sh]
1589
+ ----
1590
+ Usage:
1591
+ expressir manifest create ROOT_SCHEMA [MORE_SCHEMAS...] -o, --output=OUTPUT
1592
+
1593
+ Options:
1594
+ -o, --output=OUTPUT # Output YAML file path
1595
+ [--base-dirs=BASE_DIRS] # Comma-separated base directories for schema resolution
1596
+ [--verbose], [--no-verbose], [--skip-verbose] # Show detailed output
1597
+ # Default: false
1598
+
1599
+ Description:
1600
+ Generate a YAML manifest of all schemas required for packaging.
1601
+
1602
+ The manifest uses the existing SchemaManifest format: schemas: schema_id: path:
1603
+ /path/to/schema.exp
1604
+
1605
+ Workflow: 1. Create manifest from root schema 2. Edit manifest to add paths for
1606
+ schemas with null paths 3. Validate manifest 4. Build package using manifest
1607
+
1608
+ Example: expressir manifest create schemas/activity/mim.exp \ -o
1609
+ activity_manifest.yaml \ --base-dirs /path/to/schemas
1610
+ ----
1611
+
1612
+ Options:
1613
+
1614
+ `--output, -o FILE`:: (Required) Output YAML file path
1615
+
1616
+ `--base-dirs DIRS`:: Base directories for schema resolution (space-separated). Also supports comma-separated for backward compatibility.
1617
+ +
1618
+ Searches for schema files using these patterns:
1619
+ schema files named according to schema ID::: `<SCHEMA_ID>.exp`
1620
+ schema files named in the STEP module pattern::: `<LOWERCASE_SCHEMA_WO_MIMARM>/{mim,arm}.exp`
1621
+ +
1622
+ [source,sh]
1623
+ ----
1624
+ # Space-separated (preferred)
1625
+ --base-dirs /path/to/schemas /another/path
1626
+
1627
+ # Comma-separated (backward compatible)
1628
+ --base-dirs /path/to/schemas,/another/path
1629
+ ----
1630
+
1631
+ `--verbose`:: Show detailed output
1632
+
1633
+ Base directories can be provided to help locate schema files:
1634
+
1635
+ * During the resolving process, Expressir will search these directories for
1636
+ schema files matching known naming patterns.
1637
+ * Once a referenced schema is found, it will indicate from which source they
1638
+ were resolved.
1639
+ * If multiple matches are found, the first one encountered will be used, and a
1640
+ warning will be displayed for the user to manually edit the manifest if a
1641
+ different path is desired.
1642
+
1643
+ In the case of unresolved schemas, the created manifest will include entries
1644
+ without the `path:` field. The manifest can then be edited manually to add the
1645
+ correct paths.
1646
+
1647
+
1648
+ .Creating a manifest from a root schema
1649
+ [example]
1650
+ ====
1651
+ The following command creates a manifest starting from the
1652
+ `schemas/modules/activity/mim.exp` root schema, searching for referenced schemas
1653
+ in the `schemas/resources` and `schemas/modules` base directories.
1654
+
1655
+ [source,sh]
1656
+ ----
1657
+ $ expressir manifest create \
1658
+ schemas/modules/activity/mim.exp \
1659
+ -o new.yaml \
1660
+ --base-dirs schemas/modules schemas/resources/ \
1661
+ --verbose
1662
+
1663
+ Creating manifest from 1 root schema(s)...
1664
+ Base directories:
1665
+ - [source 1]: ~/src/mn/iso-10303/schemas/modules
1666
+ - [source 2]: ~/src/mn/iso-10303/schemas/resources/
1667
+ Resolving dependencies...
1668
+ USE FROM action_schema (in mim): ✓ [source 2] action_schema/action_schema.exp
1669
+ REFERENCE FROM basic_attribute_schema (in action_schema): ✓ [source 2] basic_attribute_schema/basic_attribute_schema.exp
1670
+ REFERENCE FROM support_resource_schema (in basic_attribute_schema): ✓ [source 2] support_resource_schema/support_resource_schema.exp
1671
+ REFERENCE FROM support_resource_schema (in action_schema): ✓ [source 2] support_resource_schema/support_resource_schema.exp
1672
+ USE FROM Activity_method_mim (in mim): ✓ [source 1] activity_method/mim.exp
1673
+ ...
1674
+ REFERENCE FROM support_resource_schema (in management_resources_schema): ✓ [source 2] support_resource_schema/support_resource_schema.exp
1675
+ ✓ Manifest created: new.yaml
1676
+ Resolved schemas: 42
1677
+ All schemas resolved successfully!
1678
+ ----
1679
+ ====
1680
+
1681
+ .Creating a manifest from a root schema with unresolved schemas
1682
+ [example]
1683
+ ====
1684
+ The following command creates a manifest starting from the
1685
+ `schemas/modules/activity/mim.exp` root schema, searching for referenced schemas
1686
+ in the `schemas/resources` base directory only (i.e. it will miss schemas
1687
+ in `schemas/modules`).
1688
+
1689
+ [source,sh]
1690
+ ----
1691
+ $ expressir manifest create \
1692
+ -o manifest.yaml \
1693
+ --base-dirs schemas/resources \
1694
+ --verbose \
1695
+ schemas/modules/activity/mim.exp
1696
+
1697
+ Creating manifest from 1 root schema(s)...
1698
+ Base directories:
1699
+ - [source 1]: ~/src/mn/iso-10303/schemas/resources
1700
+ Resolving dependencies...
1701
+ USE FROM action_schema (in mim): ✓ [source 1] action_schema/action_schema.exp
1702
+ REFERENCE FROM basic_attribute_schema (in action_schema): ✓ [source 1] basic_attribute_schema/basic_attribute_schema.exp
1703
+ REFERENCE FROM support_resource_schema (in basic_attribute_schema): ✓ [source 1] support_resource_schema/support_resource_schema.exp
1704
+ REFERENCE FROM support_resource_schema (in action_schema): ✓ [source 1] support_resource_schema/support_resource_schema.exp
1705
+ USE FROM Activity_method_mim (in mim): ✗ not found
1706
+ ...
1707
+ REFERENCE FROM support_resource_schema (in management_resources_schema): ✓ [source 2] support_resource_schema/support_resource_schema.exp
1708
+ ✓ Manifest created: manifest.yaml
1709
+ Resolved schemas: 41
1710
+
1711
+ ⚠ Unresolved schemas (1):
1712
+ - Activity_method_mim
1713
+
1714
+ Please edit manifest.yaml and set 'path:' for unresolved schemas
1715
+ Then validate with: expressir manifest validate manifest.yaml
1716
+ ----
1717
+ ====
1718
+
1719
+
1720
+
1721
+ ==== Resolving schemas from a manifest
1722
+
1723
+ A schema manifest can be used as input to resolve and load all referenced
1724
+ schemas into a new manifest.
1725
+
1726
+
1727
+ [source,sh]
1728
+ ----
1729
+ expressir manifest resolve MANIFEST -o, --output=OUTPUT
1730
+ ----
1731
+
1732
+ [source,sh]
1733
+ ----
1734
+ Usage:
1735
+ expressir manifest resolve MANIFEST -o, --output=OUTPUT
1736
+
1737
+ Options:
1738
+ -o, --output=OUTPUT # Output file path for resolved manifest
1739
+ [--base-dirs=one two three] # Base directories for schema search (can be specified multiple times)
1740
+ [--verbose], [--no-verbose], [--skip-verbose] # Show detailed resolution progress
1741
+ # Default: false
1742
+
1743
+ Description:
1744
+ Resolve missing or incomplete schema paths in a manifest file.
1745
+
1746
+ This command attempts to find file paths for schemas with missing or empty
1747
+ paths by searching in base directories using naming patterns:
1748
+
1749
+ Supported patterns:
1750
+ - Resource schemas: {schema_name}.exp
1751
+ - Module ARM/MIM: {module_name}/{arm|mim}.exp
1752
+ Example: Activity_method_mim -> activity_method/mim.exp
1753
+
1754
+ The resolved manifest is written to the output file, leaving the original
1755
+ unchanged.
1756
+
1757
+ Use this command after 'expressir manifest validate --check-references' fails
1758
+ to automatically resolve missing schema paths.
1759
+
1760
+ Examples: # Resolve paths using manifest's existing base directories expressir
1761
+ manifest resolve manifest.yaml -o resolved_manifest.yaml
1762
+ # Resolve with explicit base directories
1763
+ expressir manifest resolve manifest.yaml -o resolved.yaml \
1764
+ --base-dirs /path/to/schemas,/another/path
1765
+ # With verbose output
1766
+ expressir manifest resolve manifest.yaml -o resolved.yaml --verbose
1767
+ ----
1768
+
1769
+ Options:
1770
+
1771
+ `--output, -o FILE`:: (Required) Output file path for resolved manifest
1772
+
1773
+ `--base-dirs DIRS`:: Base directories for schema search (space-separated). Also
1774
+ supports comma-separated for backward compatibility.
1775
+ +
1776
+ Searches for schema files using these patterns:
1777
+ schema files named according to schema ID::: `<SCHEMA_ID>.exp`
1778
+ schema files named in the STEP module pattern::: `<LOWERCASE_SCHEMA_WO_MIMARM>/{mim,arm}.exp`
1779
+ +
1780
+ [source,sh]
1781
+ ----
1782
+ # Space-separated (preferred)
1783
+ --base-dirs /path/to/schemas /another/path
1784
+
1785
+ # Comma-separated (backward compatible)
1786
+ --base-dirs /path/to/schemas,/another/path
1787
+ ----
1788
+
1789
+ `--verbose`:: Show detailed resolution progress
1790
+
1791
+ .Fully resolving a schema manifest
1792
+ [example]
1793
+ ====
1794
+ The following command resolves all schemas in the `manifest.yaml` file and writes the
1795
+ fully resolved manifest to `resolved_manifest.yaml`.
1796
+
1797
+ [source,sh]
1798
+ ----
1799
+ $ expressir manifest resolve manifest.yaml -o resolved.yaml --verbose
1800
+
1801
+ Resolving schema paths in: manifest.yaml...
1802
+ Using base directories:
1803
+ - [source 1] ~/src/mn/iso-10303/schemas/
1804
+ Attempting to resolve paths...
1805
+ Resolving dependencies from 1 root schema(s)...
1806
+ USE FROM action_schema (in mim): ✓ [source 1] resources/action_schema/action_schema.exp
1807
+ REFERENCE FROM basic_attribute_schema (in action_schema): ✓ [source 1] resources/basic_attribute_schema/basic_attribute_schema.exp
1808
+ REFERENCE FROM support_resource_schema (in basic_attribute_schema): ✓ [source 1] resources/support_resource_schema/support_resource_schema.exp
1809
+ REFERENCE FROM support_resource_schema (in action_schema): ✓ [source 1] resources/support_resource_schema/support_resource_schema.exp
1810
+ USE FROM Activity_method_mim (in mim): ✗ not found
1811
+ USE FROM basic_attribute_schema (in mim): ✓ [source 1] resources/basic_attribute_schema/basic_attribute_schema.exp
1812
+ USE FROM management_resources_schema (in mim): ✓ [source 1] resources/management_resources_schema/management_resources_schema.exp
1813
+ ...
1814
+ REFERENCE FROM support_resource_schema (in management_resources_schema): ✓ [source 1] resources/support_resource_schema/support_resource_schema.exp
1815
+ ✓ Manifest resolved: resolved.yaml
1816
+ Total schemas: 42
1817
+ Resolved schemas: 41
1818
+
1819
+ ⚠ Unresolved schemas (1):
1820
+ - Activity_method_mim
1821
+
1822
+ These schemas could not be found in the search directories.
1823
+ You may need to:
1824
+ 1. Add more base directories with --base-dirs
1825
+ 2. Manually edit resolved.yaml and set their paths
1826
+ ----
1827
+ ====
1828
+
1829
+ .Resolving a manifest with multiple base directories
1830
+ [example]
1831
+ ====
1832
+ [source,sh]
1833
+ ----
1834
+ $ expressir manifest resolve manifest.yaml \
1835
+ -o resolved.yaml \
1836
+ --base-dirs ~/src/mn/iso-10303/schemas/modules \
1837
+ ~/src/mn/iso-10303/schemas/resources/ --verbose
1838
+
1839
+ Resolving schema paths in: manifest.yaml...
1840
+ Using base directories:
1841
+ - [source 1]: ~/src/mn/iso-10303/schemas/modules
1842
+ - [source 2]: ~/src/mn/iso-10303/schemas/resources/
1843
+ Attempting to resolve paths...
1844
+ Resolving dependencies from 1 root schema(s)...
1845
+ Using base directories:
1846
+ - [source 1]: ~/src/mn/iso-10303/schemas/modules
1847
+ - [source 2]: ~/src/mn/iso-10303/schemas/resources
1848
+ USE FROM action_schema (in mim): ✓ [source 2] action_schema/action_schema.exp
1849
+ REFERENCE FROM basic_attribute_schema (in action_schema): ✓ [source 2] basic_attribute_schema/basic_attribute_schema.exp
1850
+ REFERENCE FROM support_resource_schema (in basic_attribute_schema): ✓ [source 2] support_resource_schema/support_resource_schema.exp
1851
+ REFERENCE FROM support_resource_schema (in action_schema): ✓ [source 2] support_resource_schema/support_resource_schema.exp
1852
+ USE FROM Activity_method_mim (in mim): ✓ [source 1] activity_method/mim.exp
1853
+ ...
1854
+ REFERENCE FROM support_resource_schema (in management_resources_schema): ✓ [source 2] support_resource_schema/support_resource_schema.exp
1855
+ ✓ Manifest resolved: resolved.yaml
1856
+ Total schemas: 42
1857
+ Resolved schemas: 42
1858
+ All schema paths resolved successfully!
1859
+ ----
1860
+ ====
1861
+
1862
+
1863
+ ==== Validating a manifest
1864
+
1865
+ A schema manifest can be validated to ensure all referenced schemas are fully
1866
+ resolvable and correctly defined.
1867
+
1868
+ .`manifest validate` - Validate manifest
1869
+ [source,sh]
1870
+ ----
1871
+ expressir manifest validate MANIFEST.yaml [OPTIONS]
1872
+ ----
1873
+
1874
+ [source,sh]
1875
+ ----
1876
+ Usage:
1877
+ expressir manifest validate MANIFEST
1878
+
1879
+ Options:
1880
+ [--verbose], [--no-verbose], [--skip-verbose] # Show detailed validation results
1881
+ # Default: false
1882
+ [--check-references], [--no-check-references], [--skip-check-references] # Validate referential integrity using dependency resolver
1883
+ # Default: false
1884
+
1885
+ Description:
1886
+ Validate a schema manifest file.
1887
+
1888
+ Validation types: - File existence: All schema paths exist on disk - Path
1889
+ completeness: All schemas have paths specified (warnings) - Referential integrity
1890
+ (--check-references): All USE/REFERENCE FROM resolve
1891
+
1892
+ Examples: # Basic validation (file existence and path completeness) expressir manifest
1893
+ validate activity_manifest.yaml # With referential integrity checking expressir
1894
+ manifest validate activity_manifest.yaml --check-references # With verbose output
1895
+ expressir manifest validate activity_manifest.yaml --check-references --verbose
1896
+ ----
1897
+
1898
+ Options:
1899
+
1900
+ `--verbose`:: Show detailed validation results
1901
+
1902
+ `--check-references`:: Validate referential integrity using dependency resolver
1903
+
1904
+ .Validating a manifest to ensure all dependencies are defined
1905
+ [example]
1906
+ ====
1907
+ Checking `REFERENCE FROM` and `USE FROM` references to ensure all dependencies
1908
+ are defined in EXPRESS schemas included in the manifest:
1909
+
1910
+ [source,sh]
1911
+ ----
1912
+ $ expressir manifest validate manifest.yaml --check-references --verbose
1913
+
1914
+ Validating manifest: manifest.yaml...
1915
+ Checking referential integrity...
1916
+ Validating referential integrity for 42 schemas...
1917
+
1918
+ USE FROM action_schema (in Activity_method_mim): ✓ action_schema.exp
1919
+ REFERENCE FROM basic_attribute_schema (in action_schema): ✓ basic_attribute_schema.exp
1920
+ ...
1921
+ USE FROM action_schema (in mim): ✓ action_schema.exp
1922
+ ...
1923
+ REFERENCE FROM support_resource_schema (in topology_schema): ✓ support_resource_schema.exp
1924
+ ✓ Manifest is valid
1925
+ Total schemas: 42
1926
+ Resolved schemas: 42
1927
+ ----
1928
+ ====
1929
+
1930
+
1931
+
1932
+ === Ruby API for schema manifests
1933
+
1934
+ ==== Loading manifests
1079
1935
 
1080
1936
  Load an existing schema manifest from a YAML file:
1081
1937
 
@@ -1094,7 +1950,7 @@ end
1094
1950
  schema_paths = manifest.schemas.map(&:path)
1095
1951
  ----
1096
1952
 
1097
- ===== Programmatically
1953
+ ==== Creating manifests
1098
1954
 
1099
1955
  Create a new schema manifest programmatically:
1100
1956
 
@@ -1117,32 +1973,7 @@ manifest.schemas << Expressir::SchemaManifestEntry.new(
1117
1973
  manifest.base_path = "/path/to/schemas"
1118
1974
  ----
1119
1975
 
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
1976
+ ==== Saving manifests
1146
1977
 
1147
1978
  Save a manifest to a file:
1148
1979
 
@@ -1155,7 +1986,7 @@ manifest.to_file("output_schemas.yml")
1155
1986
  manifest.save_to_path("/path/to/output/")
1156
1987
  ----
1157
1988
 
1158
- ===== Concatenating manifests
1989
+ ==== Concatenating manifests
1159
1990
 
1160
1991
  Combine multiple manifests:
1161
1992
 
@@ -1171,7 +2002,7 @@ combined_manifest = manifest1.concat(manifest2)
1171
2002
  combined_manifest = manifest1 + manifest2
1172
2003
  ----
1173
2004
 
1174
- ===== Using manifests with parsers
2005
+ ==== Using manifests with parsers
1175
2006
 
1176
2007
  Parse all schemas from a manifest:
1177
2008
 
@@ -1196,11 +2027,110 @@ repository = Expressir::Express::Parser.from_files(schema_paths) do |filename, s
1196
2027
  end
1197
2028
  ----
1198
2029
 
1199
- ==== Integration with CLI commands
1200
2030
 
1201
- Schema manifests are supported by several CLI commands:
1202
2031
 
1203
- ===== Benchmarking with manifests
2032
+ == LER packages
2033
+
2034
+ === General
2035
+
2036
+ LER (LutaML EXPRESS Repository) is a package format for distributing EXPRESS
2037
+ schemas and related resources in a single binary file.
2038
+
2039
+ EXPRESS schemas often utilize `REFERENCE FROM` or `USE FROM` statements to
2040
+ import definitions from other schemas, and those referenced schemas
2041
+ can deviate across different versions. Managing these dependencies
2042
+ is crucial for maintaining compatibility.
2043
+
2044
+ The LER package format helps encapsulate these dependencies, ensuring that all
2045
+ required schemas are included and versioned correctly, allowing the package
2046
+ to be used reliably in different environments.
2047
+
2048
+ LER packages have the `.ler` file extension and are essentially ZIP archives
2049
+ containing:
2050
+
2051
+ * EXPRESS schema files (`.exp`)
2052
+ * Metadata files (`metadata.yaml`)
2053
+ * pre-parsed model cache (serialized Ruby objects)
2054
+
2055
+
2056
+ === Creating a package
2057
+
2058
+ Expressir provides a command-line interface for creating LER packages from
2059
+ an EXPRESS manifest.
2060
+
2061
+ Expressir supports building LER packages from EXPRESS schemas using a
2062
+ manifest-based workflow.
2063
+
2064
+ **Using a manifest (recommended for production)**::
2065
+
2066
+ [source,sh]
2067
+ ----
2068
+ # Build from validated manifest
2069
+ expressir package build --manifest activity_manifest.yaml activity.ler \
2070
+ --name "Activity Module" \
2071
+ --validate
2072
+ ----
2073
+
2074
+ **Using auto-resolution (quick prototyping)**:
2075
+
2076
+ [source,sh]
2077
+ ----
2078
+ # Build from root schema with auto-resolution
2079
+ expressir package build schemas/activity/mim.exp activity.ler \
2080
+ --base-dirs ~/schemas/resources ~/schemas/modules \
2081
+ --name "Activity Module" \
2082
+ --validate
2083
+ ----
2084
+
2085
+ Complete manifest workflow:
2086
+
2087
+ [source,sh]
2088
+ ----
2089
+ # 1. Create manifest from root schema
2090
+ expressir manifest create schemas/activity/mim.exp \
2091
+ -o activity_manifest.yaml \
2092
+ --base-dirs ~/iso-10303/schemas \
2093
+ --name "Activity Module"
2094
+
2095
+ # 2. Edit manifest to add missing schema paths
2096
+
2097
+ # 3. Validate manifest
2098
+ expressir manifest validate activity_manifest.yaml
2099
+
2100
+ # 4. Build package from manifest
2101
+ expressir package build --manifest activity_manifest.yaml activity.ler
2102
+ ----
2103
+
2104
+
2105
+ Unresolved schemas appear without `path:` field. Edit the manifest to add missing paths.
2106
+
2107
+ [source,yaml]
2108
+ ----
2109
+ schemas:
2110
+ - name: action_schema
2111
+ path: /path/to/action_schema.exp
2112
+ - name: Activity_method_mim # Unresolved - no path
2113
+ ----
2114
+
2115
+
2116
+ .`package build --manifest` - Build from manifest
2117
+ [source,sh]
2118
+ ----
2119
+ expressir package build --manifest MANIFEST.yaml OUTPUT.ler [OPTIONS]
2120
+ ----
2121
+
2122
+ See link:docs/_pages/ler-packages#manifest-workflow[LER Packages documentation] for complete details.
2123
+
2124
+
2125
+
2126
+ == Benchmarking
2127
+
2128
+ === General
2129
+
2130
+ Expressir includes benchmarking tools to measure the performance of parsing and
2131
+ processing EXPRESS schemas.
2132
+
2133
+ === Benchmarking with manifests
1204
2134
 
1205
2135
  [source,sh]
1206
2136
  ----
@@ -1211,7 +2141,15 @@ expressir benchmark schemas.yml --verbose
1211
2141
  expressir benchmark-cache schemas.yml --cache_path /tmp/cache.bin
1212
2142
  ----
1213
2143
 
1214
- ===== Coverage analysis with manifests
2144
+
2145
+ == Coverage reporting
2146
+
2147
+ === General
2148
+
2149
+ Expressir provides coverage analysis tools to evaluate the documentation
2150
+ coverage of EXPRESS schemas.
2151
+
2152
+ === Coverage analysis with manifests
1215
2153
 
1216
2154
  [source,sh]
1217
2155
  ----
@@ -1224,7 +2162,7 @@ expressir coverage schemas.yml --format json --exclude=TYPE:SELECT
1224
2162
 
1225
2163
 
1226
2164
 
1227
- == Working with EXPRESS Changes
2165
+ == EXPRESS Changes
1228
2166
 
1229
2167
  === General
1230
2168
 
@@ -1287,9 +2225,9 @@ end
1287
2225
  change_schema.to_file("output.changes.yaml")
1288
2226
  ----
1289
2227
 
1290
- ==== Compare modes
2228
+ === Compare modes
1291
2229
 
1292
- ===== General
2230
+ ==== General
1293
2231
 
1294
2232
  Expressir automatically detects and parses all three Eengine XML modes.
1295
2233
 
@@ -1305,7 +2243,7 @@ puts mim_report.mode # => "mim"
1305
2243
  puts schema_report.mode # => "schema"
1306
2244
  ----
1307
2245
 
1308
- ===== Schema mode
2246
+ ==== Schema mode
1309
2247
 
1310
2248
  `<schema.changes>` with `<schema.additions>`, `<schema.modifications>`, `<schema.deletions>`
1311
2249
 
@@ -1327,7 +2265,7 @@ puts schema_report.mode # => "schema"
1327
2265
  ----
1328
2266
  ====
1329
2267
 
1330
- ===== ARM mode
2268
+ ==== ARM mode
1331
2269
 
1332
2270
  `<arm.changes>` root element with `<arm.additions>`,
1333
2271
  `<arm.modifications>`, and `<arm.deletions>` sections
@@ -1345,7 +2283,7 @@ puts schema_report.mode # => "schema"
1345
2283
  ====
1346
2284
 
1347
2285
 
1348
- ===== MIM mode
2286
+ ==== MIM mode
1349
2287
 
1350
2288
  `<mim.changes>` root element with `<mim.additions>`,
1351
2289
  `<mim.modifications>`, and `<mim.deletions>` sections
@@ -1362,7 +2300,7 @@ puts schema_report.mode # => "schema"
1362
2300
  ----
1363
2301
  ====
1364
2302
 
1365
- ==== Interface changes
2303
+ === Interface changes
1366
2304
 
1367
2305
  The eengine XML format tracks interface changes (USE_FROM, REFERENCE_FROM) with
1368
2306
  the `interfaced.items` attribute. This attribute lists the specific items being
@@ -1425,7 +2363,7 @@ end
1425
2363
  ----
1426
2364
 
1427
2365
 
1428
- ==== Supported change types
2366
+ === Supported change types
1429
2367
 
1430
2368
  The import command recognizes all standard EXPRESS construct types:
1431
2369