expressir 2.3.6 → 2.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +1 -1
  3. data/.gitignore +2 -0
  4. data/.rubocop_todo.yml +17 -12
  5. data/CHANGELOG.md +159 -0
  6. data/docs/_guides/ler/step-packages.adoc +385 -0
  7. data/lib/expressir/coverage.rb +4 -4
  8. data/lib/expressir/express/builder_registry.rb +3 -1
  9. data/lib/expressir/express/builders/expression_builder.rb +2 -2
  10. data/lib/expressir/express/builders/helpers.rb +2 -8
  11. data/lib/expressir/express/builders/qualifier_builder.rb +2 -1
  12. data/lib/expressir/express/formatter.rb +32 -164
  13. data/lib/expressir/express/formatters/data_types_formatter.rb +39 -6
  14. data/lib/expressir/express/formatters/declarations_formatter.rb +47 -8
  15. data/lib/expressir/express/formatters/expressions_formatter.rb +20 -5
  16. data/lib/expressir/express/formatters/literals_formatter.rb +11 -1
  17. data/lib/expressir/express/formatters/references_formatter.rb +10 -1
  18. data/lib/expressir/express/formatters/remark_formatter.rb +1 -89
  19. data/lib/expressir/express/formatters/remark_item_formatter.rb +5 -4
  20. data/lib/expressir/express/formatters/statements_formatter.rb +32 -9
  21. data/lib/expressir/express/formatters/supertype_expressions_formatter.rb +7 -3
  22. data/lib/expressir/express/hyperlink_formatter.rb +1 -3
  23. data/lib/expressir/express/model_visitor.rb +1 -1
  24. data/lib/expressir/express/pretty_formatter.rb +31 -108
  25. data/lib/expressir/express/remark_attacher.rb +118 -88
  26. data/lib/expressir/express/schema_head_formatter.rb +1 -3
  27. data/lib/expressir/model/concerns.rb +6 -0
  28. data/lib/expressir/model/declarations/interface_item.rb +2 -0
  29. data/lib/expressir/model/declarations/interfaced_item.rb +3 -0
  30. data/lib/expressir/model/declarations/remark_item.rb +3 -0
  31. data/lib/expressir/model/declarations/schema.rb +7 -5
  32. data/lib/expressir/model/exp_file.rb +1 -0
  33. data/lib/expressir/model/identifier.rb +3 -1
  34. data/lib/expressir/model/model_element.rb +3 -3
  35. data/lib/expressir/model/repository.rb +8 -0
  36. data/lib/expressir/model/search_engine.rb +1 -1
  37. data/lib/expressir/package/reader.rb +9 -24
  38. data/lib/expressir/version.rb +1 -1
  39. metadata +4 -2
@@ -11,16 +11,39 @@ module Expressir
11
11
  # 2. Proximity-based matching for simple tags
12
12
  # 3. NOT creating spurious schema-level items for ambiguous tags
13
13
  class RemarkAttacher
14
- # Child collection attributes to walk when traversing model elements.
15
- # These are the named collections on model elements (e.g., entity.attributes,
16
- # schema.entities, function.parameters). Extracted to a constant to avoid
17
- # duplication between calculate_children_end_line and collect_children.
18
- CHILD_COLLECTION_ATTRIBUTES = %i[
19
- schemas types entities functions procedures rules constants
20
- attributes derived_attributes inverse_attributes
21
- where_rules unique_rules informal_propositions
22
- parameters variables statements items remark_items
23
- ].freeze
14
+ # Type-driven registry: maps each model class to its collection attributes.
15
+ # Replaces runtime method probing (method_defined?) with explicit type declarations.
16
+ COLLECTION_REGISTRY = {
17
+ Model::Declarations::Schema => %i[
18
+ constants types entities subtype_constraints
19
+ functions rules procedures remark_items
20
+ ],
21
+ Model::Declarations::Entity => %i[
22
+ attributes derived_attributes inverse_attributes
23
+ unique_rules where_rules informal_propositions remark_items
24
+ ],
25
+ Model::Declarations::Function => %i[
26
+ parameters types entities subtype_constraints
27
+ functions procedures constants variables statements remark_items
28
+ ],
29
+ Model::Declarations::Procedure => %i[
30
+ parameters types entities subtype_constraints
31
+ functions procedures constants variables statements remark_items
32
+ ],
33
+ Model::Declarations::Rule => %i[
34
+ applies_to types entities subtype_constraints
35
+ functions procedures constants variables statements
36
+ where_rules informal_propositions remark_items
37
+ ],
38
+ Model::Declarations::Type => %i[
39
+ where_rules informal_propositions remark_items
40
+ ],
41
+ Model::ExpFile => %i[schemas],
42
+ Model::Statements::Compound => %i[statements],
43
+ Model::Statements::If => %i[statements],
44
+ Model::Statements::Alias => %i[statements],
45
+ Model::Statements::Repeat => %i[statements],
46
+ }.freeze
24
47
 
25
48
  def initialize(source)
26
49
  @source = source
@@ -376,7 +399,7 @@ module Expressir
376
399
  return schema if schema.id == scope_name
377
400
 
378
401
  %i[functions procedures rules entities types].each do |decl_type|
379
- collection = schema.send(decl_type)
402
+ collection = schema.public_send(decl_type)
380
403
  next unless collection.is_a?(Array)
381
404
 
382
405
  found = collection.find { |n| n.id == scope_name }
@@ -390,30 +413,22 @@ module Expressir
390
413
  def find_node_in_scope(scope, tag)
391
414
  return nil unless scope
392
415
 
393
- # Search within the scope for a node with the given tag/id
394
- # Check all collections that might contain nodes with ids
395
- %i[constants types variables parameters statements
396
- attributes derived_attributes inverse_attributes
397
- where_rules unique_rules informal_propositions].each do |attr|
398
- collection = safe_get_collection(scope, attr)
399
- next unless collection
400
-
416
+ collections_on(scope).each do |collection|
401
417
  collection.each do |item|
418
+ next unless item.is_a?(Model::HasRemarks)
402
419
  return item if item.id == tag
403
- rescue NoMethodError
404
- next
405
420
  end
406
421
  end
407
422
 
408
423
  # Search inside types for enumeration items
409
- types = safe_get_collection(scope, :types)
424
+ types = get_collection(scope, :types)
410
425
  types&.each do |type|
411
426
  result = find_enumeration_item_in_type(type, tag)
412
427
  return result if result
413
428
  end
414
429
 
415
430
  # Search inside statements for nested items (alias, repeat, query)
416
- statements = safe_get_collection(scope, :statements)
431
+ statements = get_collection(scope, :statements)
417
432
  statements&.each do |stmt|
418
433
  result = find_node_in_statement(stmt, tag)
419
434
  return result if result
@@ -448,34 +463,51 @@ module Expressir
448
463
  nil
449
464
  end
450
465
 
466
+ # Expression and statement child attributes for QueryExpression search.
467
+ # Targeted traversal prevents over-matching on unrelated model attributes.
468
+ EXPRESSION_CHILDREN = {
469
+ Model::Expressions::BinaryExpression => %i[operand1 operand2],
470
+ Model::Expressions::UnaryExpression => %i[operand],
471
+ Model::Expressions::QueryExpression => %i[expression aggregate_source],
472
+ Model::Expressions::AggregateInitializerItem => %i[expression
473
+ repetition],
474
+ Model::Expressions::Interval => %i[low item high],
475
+ Model::Expressions::FunctionCall => %i[parameters],
476
+ Model::Expressions::EntityConstructor => %i[parameters],
477
+ Model::Expressions::AggregateInitializer => %i[items],
478
+ Model::Statements::Assignment => %i[expression],
479
+ Model::Statements::If => %i[expression],
480
+ Model::Statements::Case => %i[expression],
481
+ Model::Statements::CaseAction => %i[expression],
482
+ Model::Statements::Repeat => %i[while_expression until_expression],
483
+ }.freeze
484
+
451
485
  def find_query_in_expression(node, tag, visited = Set.new)
452
486
  return nil unless node
487
+ return nil unless node.is_a?(Model::ModelElement)
453
488
  return nil if visited.include?(node.object_id)
454
489
 
455
490
  visited.add(node.object_id)
456
491
 
457
- # Check if this node is a QueryExpression with matching id
458
492
  if node.is_a?(Model::Expressions::QueryExpression) && node.id == tag
459
493
  return node
460
494
  end
461
495
 
462
- # Recursively search expression attributes
463
- %i[expression operand left right condition aggregate
464
- query_expression repeat_control].each do |attr|
465
- child = safe_send(node, attr)
466
- next unless child
467
-
468
- result = find_query_in_expression(child, tag, visited)
469
- return result if result
470
- end
496
+ attrs = EXPRESSION_CHILDREN[node.class]
497
+ return nil unless attrs
471
498
 
472
- # Search in arrays
473
- %i[expressions operands parameters arguments].each do |attr|
474
- children = safe_send(node, attr)
475
- next unless children.is_a?(Array)
499
+ attrs.each do |attr|
500
+ value = node.public_send(attr)
501
+ case value
502
+ when Array
503
+ value.each do |val|
504
+ next unless val.is_a?(Model::ModelElement)
476
505
 
477
- children.each do |child|
478
- result = find_query_in_expression(child, tag, visited)
506
+ result = find_query_in_expression(val, tag, visited)
507
+ return result if result
508
+ end
509
+ when Model::ModelElement
510
+ result = find_query_in_expression(value, tag, visited)
479
511
  return result if result
480
512
  end
481
513
  end
@@ -505,7 +537,7 @@ module Expressir
505
537
  return nil unless collection_attr
506
538
 
507
539
  # First try to find in containing scope
508
- collection = safe_get_collection(containing_scope, collection_attr)
540
+ collection = get_collection(containing_scope, collection_attr)
509
541
  if collection
510
542
  found = collection.find { |item| item.is_a?(Model::ModelElement) && item.id == id }
511
543
  return found if found
@@ -525,7 +557,7 @@ module Expressir
525
557
  def find_target_in_where_clause(scope, tag, remark_line)
526
558
  return nil unless supports_where_rules?(scope)
527
559
 
528
- where_rules = safe_get_collection(scope, :where_rules)
560
+ where_rules = get_collection(scope, :where_rules)
529
561
  return nil unless where_rules&.any?
530
562
 
531
563
  # Search source text for WHERE clause containing this remark
@@ -652,24 +684,21 @@ module Expressir
652
684
  nil
653
685
  end
654
686
 
687
+ COLLECTION_ACCESSOR = {
688
+ Expressir::Model::Declarations::Entity => lambda(&:entities),
689
+ Expressir::Model::Declarations::Type => lambda(&:types),
690
+ Expressir::Model::Declarations::Rule => lambda(&:rules),
691
+ }.freeze
692
+
655
693
  def find_node_by_type_and_name(node_class, name)
656
694
  return nil unless @model && name
657
695
 
658
- # Search through all schemas
696
+ accessor = COLLECTION_ACCESSOR[node_class]
697
+ return nil unless accessor
698
+
659
699
  @model.schemas.each do |schema|
660
- collection = case node_class.name
661
- when "Expressir::Model::Declarations::Entity"
662
- schema.entities
663
- when "Expressir::Model::Declarations::Type"
664
- schema.types
665
- when "Expressir::Model::Declarations::Rule"
666
- schema.rules
667
- end
668
-
669
- if collection
670
- found = collection.find { |n| n.id == name }
671
- return found if found
672
- end
700
+ found = accessor.call(schema)&.find { |n| n.id == name }
701
+ return found if found
673
702
  end
674
703
 
675
704
  nil
@@ -872,7 +901,7 @@ module Expressir
872
901
  # Only add remarks to nodes that support them
873
902
  if supports_remarks?(node)
874
903
  # Always add to remarks attribute (for types that have it)
875
- if node.respond_to?(:remarks) && node.respond_to?(:remarks=)
904
+ if node_has_remarks?(node)
876
905
  node.remarks ||= []
877
906
  node.remarks << text
878
907
  end
@@ -891,6 +920,10 @@ module Expressir
891
920
  obj.is_a?(Model::ModelElement)
892
921
  end
893
922
 
923
+ def node_has_remarks?(obj)
924
+ obj.is_a?(Model::HasRemarks)
925
+ end
926
+
894
927
  # Types that include HasRemarkItems can have remark_items
895
928
  def supports_remark_items?(obj)
896
929
  obj.is_a?(Model::HasRemarkItems)
@@ -959,22 +992,20 @@ module Expressir
959
992
  def calculate_children_end_line(node)
960
993
  children_end_lines = []
961
994
 
962
- # Check standard children attribute
963
- children = safe_get_collection(node, :children)
964
- children&.each do |child|
965
- if child.is_a?(Model::ModelElement) && child.source_offset && child.source
966
- child_end_line = get_line_number(child.source_offset + child.source.length)
967
- children_end_lines << child_end_line
995
+ # Check computed children (Schema, ExpFile have a children method)
996
+ if node.is_a?(Model::Declarations::Schema)
997
+ Array(node.children).each do |child|
998
+ if child.is_a?(Model::ModelElement) && child.source_offset && child.source
999
+ children_end_lines << get_line_number(child.source_offset + child.source.length)
1000
+ end
968
1001
  end
969
1002
  end
970
1003
 
971
- # Check specific child collections
972
- CHILD_COLLECTION_ATTRIBUTES.each do |attr|
973
- collection = safe_get_collection(node, attr)
974
- collection&.each do |child|
1004
+ # Visit declared collections from type registry
1005
+ collections_on(node).each do |collection|
1006
+ collection.each do |child|
975
1007
  if child.is_a?(Model::ModelElement) && child.source_offset && child.source
976
- child_end_line = get_line_number(child.source_offset + child.source.length)
977
- children_end_lines << child_end_line
1008
+ children_end_lines << get_line_number(child.source_offset + child.source.length)
978
1009
  end
979
1010
  end
980
1011
  end
@@ -983,14 +1014,14 @@ module Expressir
983
1014
  end
984
1015
 
985
1016
  def collect_children(node, result, visited)
986
- children = safe_get_collection(node, :children)
987
- children&.each do |child|
988
- collect_nodes_with_positions(child, result, visited)
1017
+ if node.is_a?(Model::Declarations::Schema)
1018
+ Array(node.children).each do |child|
1019
+ collect_nodes_with_positions(child, result, visited)
1020
+ end
989
1021
  end
990
1022
 
991
- CHILD_COLLECTION_ATTRIBUTES.each do |attr|
992
- collection = safe_get_collection(node, attr)
993
- collection&.each do |item|
1023
+ collections_on(node).each do |collection|
1024
+ collection.each do |item|
994
1025
  collect_nodes_with_positions(item, result, visited)
995
1026
  end
996
1027
  end
@@ -1089,23 +1120,23 @@ module Expressir
1089
1120
  obj.is_a?(Model::HasWhereRules)
1090
1121
  end
1091
1122
 
1092
- # Safe accessor methods that return nil instead of NoMethodError
1123
+ # Type-driven collection access returns all collections for a node's type.
1124
+ def collections_on(node)
1125
+ attrs = COLLECTION_REGISTRY[node.class]
1126
+ return [] unless attrs
1093
1127
 
1094
- def safe_send(obj, method)
1095
- return nil unless obj
1096
-
1097
- obj.send(method)
1098
- rescue NoMethodError
1099
- nil
1128
+ attrs.filter_map do |attr|
1129
+ col = node.public_send(attr)
1130
+ col if col.is_a?(Array)
1131
+ end
1100
1132
  end
1101
1133
 
1102
- def safe_get_collection(obj, attr)
1103
- return nil unless obj
1134
+ # Type-driven single collection access — returns one named collection if the type has it.
1135
+ def get_collection(node, attr_name)
1136
+ return nil unless COLLECTION_REGISTRY[node.class]&.include?(attr_name)
1104
1137
 
1105
- collection = obj.send(attr)
1138
+ collection = node.public_send(attr_name)
1106
1139
  collection if collection.is_a?(Array)
1107
- rescue NoMethodError
1108
- nil
1109
1140
  end
1110
1141
 
1111
1142
  def safe_find(model, path)
@@ -1118,10 +1149,9 @@ module Expressir
1118
1149
 
1119
1150
  def safe_reset_children_by_id(obj)
1120
1151
  return unless obj
1152
+ return unless obj.is_a?(Model::ScopeContainer)
1121
1153
 
1122
1154
  obj.reset_children_by_id
1123
- rescue NoMethodError
1124
- nil
1125
1155
  end
1126
1156
  end
1127
1157
  end
@@ -8,14 +8,12 @@ module Expressir
8
8
  module SchemaHeadFormatter
9
9
  # @!visibility private
10
10
  def self.included(mod)
11
- if !mod.superclass.private_method_defined?(:format_declarations_schema) || !mod.superclass.private_method_defined?(:format_declarations_schema_head)
11
+ unless mod.superclass <= Expressir::Express::Formatter
12
12
  raise Error::FormatterMethodMissingError.new("SchemaHeadFormatter",
13
13
  "format_declarations_schema/format_declarations_schema_head")
14
14
  end
15
15
  end
16
16
 
17
- private
18
-
19
17
  def format_declarations_schema(node)
20
18
  format_declarations_schema_head(node)
21
19
  end
@@ -2,10 +2,16 @@
2
2
 
3
3
  module Expressir
4
4
  module Model
5
+ # Marker for types that have an id attribute
6
+ module HasId; end
7
+
5
8
  # Marker for types that can have remark_items children
6
9
  # These are types where RemarkItem children can be created
7
10
  module HasRemarkItems; end
8
11
 
12
+ # Marker for types that have a `remarks` string collection
13
+ module HasRemarks; end
14
+
9
15
  # Marker for scope containers (can contain declarations)
10
16
  # Includes schemas, functions, procedures, rules, entities, types, and files
11
17
  module ScopeContainer; end
@@ -4,6 +4,8 @@ module Expressir
4
4
  # Specified in ISO 10303-11:2004
5
5
  # - section 11 Interface specification
6
6
  class InterfaceItem < ModelElement
7
+ include HasId
8
+
7
9
  attribute :ref, ModelElement
8
10
  attribute :id, :string
9
11
  attribute :_class, :string, default: -> { self.class.name }
@@ -4,6 +4,9 @@ module Expressir
4
4
  # Specified in ISO 10303-11:2004
5
5
  # - section 11 Interface specification
6
6
  class InterfacedItem < ModelElement
7
+ include HasId
8
+ include HasRemarks
9
+
7
10
  attribute :id, :string
8
11
  attribute :remarks, :string, collection: true
9
12
  attribute :remark_items, RemarkItem, collection: true
@@ -3,6 +3,9 @@ module Expressir
3
3
  module Declarations
4
4
  # Implicit item with remarks
5
5
  class RemarkItem < ModelElement
6
+ include HasId
7
+ include HasRemarks
8
+
6
9
  attribute :id, :string
7
10
  attribute :remarks, :string, collection: true
8
11
  attribute :_class, :string, default: -> { self.class.name }
@@ -70,7 +70,7 @@ module Expressir
70
70
  end
71
71
 
72
72
  def full_source
73
- Expressir::Express::Formatter.format(self)
73
+ @full_source ||= Expressir::Express::Formatter.format(self)
74
74
  end
75
75
 
76
76
  def formatted
@@ -78,11 +78,13 @@ module Expressir
78
78
  end
79
79
 
80
80
  def source
81
- formatter = Class.new(Expressir::Express::Formatter) do
82
- include Expressir::Express::SchemaHeadFormatter
83
- include Expressir::Express::HyperlinkFormatter
81
+ @source ||= begin
82
+ formatter = Class.new(Expressir::Express::Formatter) do
83
+ include Expressir::Express::SchemaHeadFormatter
84
+ include Expressir::Express::HyperlinkFormatter
85
+ end
86
+ formatter.format(self)
84
87
  end
85
- formatter.format(self)
86
88
  end
87
89
 
88
90
  private
@@ -11,6 +11,7 @@ module Expressir
11
11
  # A Repository contains multiple ExpFile instances when parsing multiple files,
12
12
  # or a single ExpFile when parsing a single file.
13
13
  class ExpFile < ModelElement
14
+ include HasId
14
15
  include ScopeContainer
15
16
 
16
17
  attribute :path, :string
@@ -2,8 +2,10 @@ module Expressir
2
2
  module Model
3
3
  module Identifier
4
4
  def self.included(mod)
5
- # Auto-include marker - all Identifier types can have remark_items
5
+ # Auto-include markers - all Identifier types have id and can have remark_items and remarks
6
+ mod.include(HasId)
6
7
  mod.include(HasRemarkItems)
8
+ mod.include(HasRemarks)
7
9
 
8
10
  mod.attribute :id, :string
9
11
  mod.attribute :remarks, :string, collection: true
@@ -120,7 +120,7 @@ module Expressir
120
120
  loop do
121
121
  # Skip adding the id if this is a RemarkItem that belongs to an InformalPropositionRule
122
122
  # and has the same id as its parent
123
- if !(current_node.is_a? References::SimpleReference) && current_node.class.method_defined?(:id) &&
123
+ if !(current_node.is_a? References::SimpleReference) && current_node.is_a?(HasId) &&
124
124
  !(is_a?(Declarations::RemarkItem) &&
125
125
  parent.is_a?(Declarations::InformalPropositionRule) &&
126
126
  id == parent.id)
@@ -200,7 +200,7 @@ module Expressir
200
200
  self.untagged_remarks ||= []
201
201
  return unless remark_info.is_a?(RemarkInfo)
202
202
 
203
- self.untagged_remarks << remark_info
203
+ untagged_remarks << remark_info
204
204
  end
205
205
 
206
206
  private
@@ -208,7 +208,7 @@ module Expressir
208
208
  # @return [nil]
209
209
  def attach_parent_to_children
210
210
  self.class.attributes.each_pair do |symbol, _lutaml_attr|
211
- value = send(symbol)
211
+ value = public_send(symbol)
212
212
 
213
213
  case value
214
214
  when Array
@@ -24,6 +24,14 @@ module Expressir
24
24
  # Index instances (lazy-loaded)
25
25
  attr_reader :entity_index, :type_index, :reference_index
26
26
 
27
+ # Restore deserialized indexes (used by Package::Reader)
28
+ def restore_indexes(entity_index: nil, type_index: nil,
29
+ reference_index: nil)
30
+ @entity_index = entity_index if entity_index
31
+ @type_index = type_index if type_index
32
+ @reference_index = reference_index if reference_index
33
+ end
34
+
27
35
  # Internal schema storage for direct manipulation
28
36
  attr_reader :_schemas
29
37
 
@@ -327,7 +327,7 @@ module Expressir
327
327
  # Guard against nil schemas array
328
328
  return [] unless schemas
329
329
 
330
- schemas.flat_map { |s| s.send(method) || [] }
330
+ schemas.flat_map { |s| s.public_send(method) || [] }
331
331
  end
332
332
 
333
333
  # Collect all attributes from entities
@@ -132,32 +132,17 @@ module Expressir
132
132
  # @param repository [Model::Repository] Repository instance
133
133
  # @return [void]
134
134
  def load_indexes(zip, repository)
135
- # Load entity index
136
- entity_index_entry = zip.find_entry("entity_index.marshal")
137
- if entity_index_entry
138
- repository.instance_variable_set(
139
- :@entity_index,
140
- Marshal.load(entity_index_entry.get_input_stream.read),
141
- )
135
+ indexes = {}
136
+
137
+ %w[entity_index type_index reference_index].each do |name|
138
+ entry = zip.find_entry("#{name}.marshal")
139
+ if entry
140
+ indexes[name.to_sym] =
141
+ Marshal.load(entry.get_input_stream.read)
142
+ end
142
143
  end
143
144
 
144
- # Load type index
145
- type_index_entry = zip.find_entry("type_index.marshal")
146
- if type_index_entry
147
- repository.instance_variable_set(
148
- :@type_index,
149
- Marshal.load(type_index_entry.get_input_stream.read),
150
- )
151
- end
152
-
153
- # Load reference index
154
- reference_index_entry = zip.find_entry("reference_index.marshal")
155
- if reference_index_entry
156
- repository.instance_variable_set(
157
- :@reference_index,
158
- Marshal.load(reference_index_entry.get_input_stream.read),
159
- )
160
- end
145
+ repository.restore_indexes(**indexes) unless indexes.empty?
161
146
  end
162
147
  end
163
148
  end
@@ -1,3 +1,3 @@
1
1
  module Expressir
2
- VERSION = "2.3.6".freeze
2
+ VERSION = "2.3.7".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: expressir
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.6
4
+ version: 2.3.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-05-14 00:00:00.000000000 Z
11
+ date: 2026-06-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -233,6 +233,7 @@ files:
233
233
  - ".rspec"
234
234
  - ".rubocop.yml"
235
235
  - ".rubocop_todo.yml"
236
+ - CHANGELOG.md
236
237
  - Gemfile
237
238
  - README.adoc
238
239
  - Rakefile
@@ -263,6 +264,7 @@ files:
263
264
  - docs/_guides/ler/loading-packages.adoc
264
265
  - docs/_guides/ler/package-formats.adoc
265
266
  - docs/_guides/ler/querying-packages.adoc
267
+ - docs/_guides/ler/step-packages.adoc
266
268
  - docs/_guides/ler/validating-packages.adoc
267
269
  - docs/_guides/liquid/basic-templates.adoc
268
270
  - docs/_guides/liquid/documentation-generation.adoc