ea 0.2.5 → 0.3.1

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 (102) hide show
  1. checksums.yaml +4 -4
  2. data/TODO.refactor/01-ea-model-domain-layer.md +64 -0
  3. data/TODO.refactor/02-ea-model-qea-source-adapter.md +58 -0
  4. data/TODO.refactor/03-ea-model-xmi-source-adapter.md +33 -0
  5. data/TODO.refactor/04-ea-model-annotations-tagged-values.md +34 -0
  6. data/TODO.refactor/05-ea-model-diagrams-coordinates.md +37 -0
  7. data/TODO.refactor/06-spa-projection-layer.md +45 -0
  8. data/TODO.refactor/07-spa-sharded-output-strategy.md +28 -0
  9. data/TODO.refactor/08-spa-build-time-search-index.md +24 -0
  10. data/TODO.refactor/09-spa-frontend-data-contract.md +25 -0
  11. data/TODO.refactor/10-spa-cli-command-rework.md +34 -0
  12. data/TODO.refactor/11-spa-perf-benchmark.md +23 -0
  13. data/TODO.refactor/12-lutaml-uml-static-site-deprecation.md +28 -0
  14. data/lib/ea/cli/app.rb +13 -7
  15. data/lib/ea/cli/command/spa.rb +33 -48
  16. data/lib/ea/cli/command/svg.rb +68 -0
  17. data/lib/ea/cli/command.rb +1 -0
  18. data/lib/ea/model/annotation.rb +29 -0
  19. data/lib/ea/model/association.rb +40 -0
  20. data/lib/ea/model/base.rb +27 -0
  21. data/lib/ea/model/bounds.rb +22 -0
  22. data/lib/ea/model/classifier.rb +41 -0
  23. data/lib/ea/model/data_type.rb +9 -0
  24. data/lib/ea/model/dependency.rb +19 -0
  25. data/lib/ea/model/diagram.rb +28 -0
  26. data/lib/ea/model/diagram_connector.rb +30 -0
  27. data/lib/ea/model/diagram_element.rb +23 -0
  28. data/lib/ea/model/document.rb +107 -0
  29. data/lib/ea/model/enumeration.rb +15 -0
  30. data/lib/ea/model/enumeration_literal.rb +16 -0
  31. data/lib/ea/model/generalization.rb +19 -0
  32. data/lib/ea/model/interface.rb +9 -0
  33. data/lib/ea/model/klass.rb +16 -0
  34. data/lib/ea/model/metadata.rb +31 -0
  35. data/lib/ea/model/operation.rb +33 -0
  36. data/lib/ea/model/package.rb +36 -0
  37. data/lib/ea/model/parameter.rb +24 -0
  38. data/lib/ea/model/point.rb +16 -0
  39. data/lib/ea/model/polymorphic_maps.rb +30 -0
  40. data/lib/ea/model/primitive_type.rb +9 -0
  41. data/lib/ea/model/property.rb +49 -0
  42. data/lib/ea/model/realization.rb +19 -0
  43. data/lib/ea/model/relationship.rb +21 -0
  44. data/lib/ea/model/stereotype.rb +24 -0
  45. data/lib/ea/model/tagged_value.rb +20 -0
  46. data/lib/ea/model/waypoint.rb +19 -0
  47. data/lib/ea/model.rb +48 -0
  48. data/lib/ea/sources/qea/adapter.rb +63 -0
  49. data/lib/ea/sources/qea/annotation_builder.rb +36 -0
  50. data/lib/ea/sources/qea/classifier_builder.rb +119 -0
  51. data/lib/ea/sources/qea/connector_relationship_map.rb +42 -0
  52. data/lib/ea/sources/qea/diagram_builder.rb +214 -0
  53. data/lib/ea/sources/qea/diagram_style_parser.rb +43 -0
  54. data/lib/ea/sources/qea/id_normalizer.rb +24 -0
  55. data/lib/ea/sources/qea/metadata_builder.rb +42 -0
  56. data/lib/ea/sources/qea/object_classifier_map.rb +36 -0
  57. data/lib/ea/sources/qea/operation_builder.rb +79 -0
  58. data/lib/ea/sources/qea/package_builder.rb +44 -0
  59. data/lib/ea/sources/qea/property_builder.rb +86 -0
  60. data/lib/ea/sources/qea/relationship_builder.rb +113 -0
  61. data/lib/ea/sources/qea/stereotype_builder.rb +44 -0
  62. data/lib/ea/sources/qea/tagged_value_builder.rb +39 -0
  63. data/lib/ea/sources/qea.rb +31 -0
  64. data/lib/ea/sources/xmi/adapter.rb +62 -0
  65. data/lib/ea/sources/xmi/annotation_builder.rb +49 -0
  66. data/lib/ea/sources/xmi/classifier_builder.rb +89 -0
  67. data/lib/ea/sources/xmi/diagram_builder.rb +82 -0
  68. data/lib/ea/sources/xmi/id_normalizer.rb +27 -0
  69. data/lib/ea/sources/xmi/metadata_builder.rb +32 -0
  70. data/lib/ea/sources/xmi/operation_builder.rb +59 -0
  71. data/lib/ea/sources/xmi/package_builder.rb +73 -0
  72. data/lib/ea/sources/xmi/property_builder.rb +77 -0
  73. data/lib/ea/sources/xmi/relationship_builder.rb +142 -0
  74. data/lib/ea/sources/xmi/relationship_type_map.rb +34 -0
  75. data/lib/ea/sources/xmi/type_classifier_map.rb +33 -0
  76. data/lib/ea/sources/xmi.rb +29 -0
  77. data/lib/ea/sources.rb +15 -0
  78. data/lib/ea/spa/configuration.rb +110 -0
  79. data/lib/ea/spa/generator.rb +45 -0
  80. data/lib/ea/spa/lazy_ref.rb +18 -0
  81. data/lib/ea/spa/output/sharded_multi_file_strategy.rb +71 -0
  82. data/lib/ea/spa/output/single_file_strategy.rb +56 -0
  83. data/lib/ea/spa/output/strategy.rb +36 -0
  84. data/lib/ea/spa/output.rb +11 -0
  85. data/lib/ea/spa/package_tree.rb +15 -0
  86. data/lib/ea/spa/package_tree_node.rb +26 -0
  87. data/lib/ea/spa/projector.rb +199 -0
  88. data/lib/ea/spa/search_entry.rb +28 -0
  89. data/lib/ea/spa/search_index.rb +18 -0
  90. data/lib/ea/spa/shard.rb +19 -0
  91. data/lib/ea/spa/skeleton.rb +22 -0
  92. data/lib/ea/spa/skeleton_entry.rb +27 -0
  93. data/lib/ea/spa.rb +31 -0
  94. data/lib/ea/svg/bounds_calculator.rb +74 -0
  95. data/lib/ea/svg/connector_path.rb +138 -0
  96. data/lib/ea/svg/element_box.rb +256 -0
  97. data/lib/ea/svg/renderer.rb +77 -0
  98. data/lib/ea/svg/style_resolver.rb +72 -0
  99. data/lib/ea/svg.rb +21 -0
  100. data/lib/ea/version.rb +1 -1
  101. data/lib/ea.rb +4 -0
  102. metadata +97 -2
@@ -0,0 +1,256 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ostruct"
4
+
5
+ module Ea
6
+ module Svg
7
+ # Renders one DiagramElement as a 3-compartment UML class box,
8
+ # matching EA's drawing convention:
9
+ #
10
+ # ┌─────────────────────────┐
11
+ # │ «Stereotype» │ ← header (stereotype + name)
12
+ # │ qualified::Name │
13
+ # ├─────────────────────────┤
14
+ # │ + attr1: Type [0..1] │ ← attributes
15
+ # │ + attr2: Type [0..*] │
16
+ # ├─────────────────────────┤
17
+ # │ + op1(arg: T): T │ ← operations
18
+ # └─────────────────────────┘
19
+ #
20
+ # The stored element bounds are honored as the outer rectangle;
21
+ # internal layout (header / attrs / ops heights) is computed
22
+ # proportionally based on line count.
23
+ class ElementBox
24
+ HEADER_LINE_HEIGHT = 17
25
+ ATTR_LINE_HEIGHT = 17
26
+ OP_LINE_HEIGHT = 17
27
+ TOP_PADDING = 17
28
+
29
+ STEREOTYPE_COLORS = {
30
+ "featuretype" => "#FFFFCC", # yellow
31
+ "feature" => "#FFFFCC",
32
+ "type" => "#CCFFCC", # green
33
+ "datatype" => "#FFCCFF", # pink
34
+ "basictype" => "#FFCCFF",
35
+ "codelist" => "#FFCCFF",
36
+ "enumeration" => "#FFCCFF",
37
+ "union" => "#F0E68C", # khaki
38
+ "adeelement" => "#F5F5DC" # beige
39
+ }.freeze
40
+ DEFAULT_FILL = "#FFFFFF"
41
+
42
+ attr_reader :element, :model_index
43
+
44
+ def initialize(element, model_index:)
45
+ @element = element
46
+ @model_index = model_index
47
+ end
48
+
49
+ def render
50
+ return "" unless element.bounds
51
+
52
+ b = normalize_bounds(element.bounds)
53
+ classifier = bound_classifier
54
+ return render_simple_box(b) unless classifier
55
+
56
+ render_class_box(b, classifier)
57
+ end
58
+
59
+ private
60
+
61
+ def bound_classifier
62
+ ref = element.model_element_ref
63
+ return nil unless ref
64
+
65
+ candidate = model_index[ref]
66
+ return nil unless candidate.is_a?(Ea::Model::Classifier)
67
+
68
+ candidate
69
+ end
70
+
71
+ def render_simple_box(bounds)
72
+ style = StyleResolver.new(element.style)
73
+ <<~SVG.chomp
74
+ <g class="element" data-element-id="#{escape(element.id)}">
75
+ <rect x="#{bounds.x}" y="#{bounds.y}" width="#{bounds.width}" height="#{bounds.height}"
76
+ fill="#{fill_color(style)}" stroke="#{style.stroke_color}"
77
+ stroke-width="#{style.stroke_width}"/>
78
+ <text x="#{bounds.x + (bounds.width / 2.0)}"
79
+ y="#{bounds.y + (bounds.height / 2.0)}"
80
+ text-anchor="middle" dominant-baseline="middle"
81
+ fill="#{style.font_color}"
82
+ font-family="sans-serif" font-size="14">#{escape(element.id)}</text>
83
+ </g>
84
+ SVG
85
+ end
86
+
87
+ def render_class_box(bounds, classifier)
88
+ stereotype = primary_stereotype(classifier)
89
+ fill = STEREOTYPE_COLORS[stereotype&.downcase] || DEFAULT_FILL
90
+ style = StyleResolver.new(element.style)
91
+ stroke = style.stroke_color
92
+ stroke_width = style.stroke_width
93
+ font_color = style.font_color
94
+
95
+ header_lines = build_header_lines(classifier, stereotype)
96
+ attr_lines = build_attribute_lines(classifier)
97
+ op_lines = build_operation_lines(classifier)
98
+
99
+ header_bottom = bounds.y + header_height(header_lines.size)
100
+ attrs_bottom = header_bottom + compartment_height(attr_lines.size)
101
+ ops_bottom = attrs_bottom + compartment_height(op_lines.size)
102
+
103
+ parts = []
104
+ parts << %(<g class="element" data-element-id="#{escape(element.id)}">)
105
+ parts << render_outer_rect(bounds, fill, stroke, stroke_width)
106
+ parts << render_header_divider(bounds, header_bottom, stroke, stroke_width)
107
+ parts << render_attrs_divider(bounds, attrs_bottom, stroke, stroke_width) if op_lines.any?
108
+ parts << render_header_text(bounds, header_lines, font_color)
109
+ parts << render_attribute_text(bounds, header_bottom, attr_lines, font_color)
110
+ parts << render_operation_text(bounds, attrs_bottom, op_lines, font_color)
111
+ parts << %(</g>)
112
+ parts.join("\n ")
113
+ end
114
+
115
+ def build_header_lines(classifier, stereotype)
116
+ lines = []
117
+ lines << "«#{stereotype}»" if stereotype && !stereotype.empty?
118
+ lines << (classifier.qualified_name&.split("::")&.last || classifier.name || "(unnamed)")
119
+ lines
120
+ end
121
+
122
+ def build_attribute_lines(classifier)
123
+ return [] unless classifier.properties
124
+
125
+ classifier.properties.map do |prop|
126
+ vis = visibility_marker(prop.visibility)
127
+ mult = multiplicity_text(prop)
128
+ type = prop.type_name ? ": #{prop.type_name}" : ""
129
+ "#{vis} #{prop.name}#{type}#{mult}"
130
+ end
131
+ end
132
+
133
+ def build_operation_lines(classifier)
134
+ return [] unless classifier.operations
135
+
136
+ classifier.operations.map do |op|
137
+ vis = visibility_marker(op.visibility)
138
+ ret = op.return_type_name ? ": #{op.return_type_name}" : ""
139
+ params = (op.parameters || []).map { |p| "#{p.name}: #{p.type_name || 'T'}" }.join(", ")
140
+ "#{vis} #{op.name}(#{params})#{ret}"
141
+ end
142
+ end
143
+
144
+ def visibility_marker(visibility)
145
+ case visibility&.downcase
146
+ when "public" then "+"
147
+ when "private" then "-"
148
+ when "protected" then "#"
149
+ when "package" then "~"
150
+ else "+"
151
+ end
152
+ end
153
+
154
+ def multiplicity_text(prop)
155
+ lower = prop.multiplicity_lower
156
+ upper = prop.multiplicity_upper
157
+ return "" if lower.nil? && upper.nil?
158
+ return "" if lower == 1 && upper == 1
159
+
160
+ upper_text = upper == -1 ? "*" : upper
161
+ lower_text = lower || 0
162
+ return "[0..*]" if lower_text == 0 && upper == -1
163
+ return "[#{lower_text}]" if lower_text == upper
164
+
165
+ "[#{lower_text}..#{upper_text}]"
166
+ end
167
+
168
+ def primary_stereotype(classifier)
169
+ refs = classifier.stereotype_refs
170
+ return nil if refs.nil? || refs.empty?
171
+
172
+ refs.first.to_s.split("::").last
173
+ end
174
+
175
+ def fill_color(style)
176
+ stereotype = primary_stereotype_from_style
177
+ STEREOTYPE_COLORS[stereotype&.downcase] || style.fill_color
178
+ end
179
+
180
+ def primary_stereotype_from_style
181
+ nil
182
+ end
183
+
184
+ def header_height(line_count)
185
+ TOP_PADDING + (line_count * HEADER_LINE_HEIGHT)
186
+ end
187
+
188
+ def compartment_height(line_count)
189
+ return 0 if line_count.zero?
190
+
191
+ 10 + (line_count * (line_count == 0 ? 0 : (line_count < 3 ? 17 : 17)))
192
+ end
193
+
194
+ def render_outer_rect(bounds, fill, stroke, stroke_width)
195
+ %( <rect x="#{bounds.x}" y="#{bounds.y}" width="#{bounds.width}" height="#{bounds.height}" fill="#{fill}" stroke="#{stroke}" stroke-width="#{stroke_width}"/>)
196
+ end
197
+
198
+ def render_header_divider(bounds, y, stroke, stroke_width)
199
+ %( <path d="M #{bounds.x} #{y} L #{bounds.x + bounds.width} #{y}" stroke="#{stroke}" stroke-width="#{stroke_width}" fill="none"/>)
200
+ end
201
+
202
+ def render_attrs_divider(bounds, y, stroke, stroke_width)
203
+ %( <path d="M #{bounds.x} #{y} L #{bounds.x + bounds.width} #{y}" stroke="#{stroke}" stroke-width="#{stroke_width}" fill="none"/>)
204
+ end
205
+
206
+ def render_header_text(bounds, lines, font_color)
207
+ center_x = bounds.x + (bounds.width / 2.0)
208
+ lines.each_with_index.map do |line, idx|
209
+ y = bounds.y + TOP_PADDING + (idx * HEADER_LINE_HEIGHT) - 4
210
+ weight = (idx == lines.size - 1) ? "bold" : "normal"
211
+ %( <text x="#{center_x}" y="#{y}" text-anchor="middle" fill="#{font_color}" font-family="sans-serif" font-size="13" font-weight="#{weight}">#{escape(line)}</text>)
212
+ end.join("\n ")
213
+ end
214
+
215
+ def render_attribute_text(bounds, header_bottom, lines, font_color)
216
+ return "" if lines.empty?
217
+
218
+ left = bounds.x + 5
219
+ lines.each_with_index.map do |line, idx|
220
+ y = header_bottom + 14 + (idx * ATTR_LINE_HEIGHT)
221
+ %( <text x="#{left}" y="#{y}" text-anchor="start" fill="#{font_color}" font-family="sans-serif" font-size="12">#{escape(line)}</text>)
222
+ end.join("\n ")
223
+ end
224
+
225
+ def render_operation_text(bounds, attrs_bottom, lines, font_color)
226
+ return "" if lines.empty?
227
+
228
+ left = bounds.x + 5
229
+ lines.each_with_index.map do |line, idx|
230
+ y = attrs_bottom + 14 + (idx * OP_LINE_HEIGHT)
231
+ %( <text x="#{left}" y="#{y}" text-anchor="start" fill="#{font_color}" font-family="sans-serif" font-size="12">#{escape(line)}</text>)
232
+ end.join("\n ")
233
+ end
234
+
235
+ def normalize_bounds(bounds)
236
+ x = bounds.x
237
+ y = bounds.y
238
+ w = bounds.width
239
+ h = bounds.height
240
+ x, w = x + w, -w if w.negative?
241
+ y, h = y + h, -h if h.negative?
242
+ OpenStruct.new(x: x, y: y, width: w, height: h)
243
+ end
244
+
245
+ def escape(text)
246
+ return "" if text.nil?
247
+
248
+ text.to_s
249
+ .gsub("&", "&amp;")
250
+ .gsub("<", "&lt;")
251
+ .gsub(">", "&gt;")
252
+ .gsub("\"", "&quot;")
253
+ end
254
+ end
255
+ end
256
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ostruct"
4
+
5
+ module Ea
6
+ module Svg
7
+ # Renders an Ea::Model::Diagram into a standalone SVG string.
8
+ # Coordinates come straight from the umldi (UML Diagram
9
+ # Interchange) content captured by the source adapter:
10
+ # DiagramElement bounds and DiagramConnector waypoints.
11
+ #
12
+ # The renderer walks the diagram once, computes the union
13
+ # bounding box, and emits SVG in the same coordinate space
14
+ # (no y-flip; SVG's +y is down, same as EA's pixel space).
15
+ class Renderer
16
+ DEFAULT_PADDING = 20
17
+
18
+ attr_reader :diagram, :model_index, :options
19
+
20
+ def initialize(diagram, model_index: {}, padding: DEFAULT_PADDING)
21
+ @diagram = diagram
22
+ @model_index = model_index
23
+ @options = { padding: padding }
24
+ end
25
+
26
+ def render
27
+ bounds = BoundsCalculator.new(diagram).compute
28
+ padded = pad(bounds)
29
+
30
+ <<~SVG
31
+ <?xml version="1.0" encoding="UTF-8"?>
32
+ <svg xmlns="http://www.w3.org/2000/svg"
33
+ viewBox="#{padded.x} #{padded.y} #{padded.width} #{padded.height}"
34
+ width="#{padded.width}" height="#{padded.height}"
35
+ font-family="sans-serif">
36
+ <rect x="#{padded.x}" y="#{padded.y}"
37
+ width="#{padded.width}" height="#{padded.height}"
38
+ fill="white"/>
39
+ #{render_elements}
40
+ #{render_connectors}
41
+ </svg>
42
+ SVG
43
+ end
44
+
45
+ private
46
+
47
+ def render_elements
48
+ diagram.elements.map do |elem|
49
+ ElementBox.new(elem, model_index: model_index).render
50
+ end.join("\n ")
51
+ end
52
+
53
+ def render_connectors
54
+ diagram.connectors.map do |conn|
55
+ ConnectorPath.new(conn,
56
+ relationship: relationship_for(conn)).render
57
+ end.join("\n ")
58
+ end
59
+
60
+ def relationship_for(connector)
61
+ return nil unless connector.relationship_ref
62
+
63
+ model_index[connector.relationship_ref]
64
+ end
65
+
66
+ def pad(bounds)
67
+ p = options[:padding]
68
+ OpenStruct.new(
69
+ x: bounds.x - p,
70
+ y: bounds.y - p,
71
+ width: bounds.width + (2 * p),
72
+ height: bounds.height + (2 * p)
73
+ )
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ea
4
+ module Svg
5
+ # Translates the parsed style hash (from
6
+ # Ea::Sources::Qea::DiagramStyleParser, or the equivalent for
7
+ # XMI) into SVG-friendly attributes. EA packs colors as
8
+ # integers (e.g. 16777215 = white); we translate to CSS hex.
9
+ class StyleResolver
10
+ DEFAULT_FILL = "#ffffff"
11
+ DEFAULT_STROKE = "#000000"
12
+ DEFAULT_FONT_COLOR = "#000000"
13
+
14
+ attr_reader :style
15
+
16
+ def initialize(style_hash)
17
+ @style = style_hash || {}
18
+ end
19
+
20
+ def fill_color
21
+ color_from_ea(style[:bcol]) || DEFAULT_FILL
22
+ end
23
+
24
+ def stroke_color
25
+ color_from_ea(style[:lcol]) || DEFAULT_STROKE
26
+ end
27
+
28
+ def font_color
29
+ color_from_ea(style[:fcol]) || DEFAULT_FONT_COLOR
30
+ end
31
+
32
+ def stroke_width
33
+ raw = style[:lwd]
34
+ return 1 if raw.nil? || raw.to_s.empty?
35
+
36
+ Integer(raw)
37
+ rescue ArgumentError
38
+ 1
39
+ end
40
+
41
+ def to_svg_attrs
42
+ {
43
+ fill: fill_color,
44
+ stroke: stroke_color,
45
+ "stroke-width": stroke_width
46
+ }
47
+ end
48
+
49
+ # EA stores colors as decimal integers in BGR byte order
50
+ # (low byte = red, high byte = blue). The high byte may hold
51
+ # alpha in some variants; we treat anything above 0xFFFFFF
52
+ # as opaque.
53
+ def color_from_ea(raw)
54
+ return nil if raw.nil? || raw.to_s.empty?
55
+
56
+ # Hex strings (e.g. from XMI): passthrough.
57
+ return "##{raw}" if raw.to_s.match?(/\A[0-9a-fA-F]{6}\z/)
58
+
59
+ Integer(raw.to_s)
60
+ rescue ArgumentError
61
+ nil
62
+ else
63
+ # Convert BGR integer → RGB hex.
64
+ value = Integer(raw)
65
+ b = (value >> 16) & 0xff
66
+ g = (value >> 8) & 0xff
67
+ r = value & 0xff
68
+ format("#%02X%02X%02X", r, g, b)
69
+ end
70
+ end
71
+ end
72
+ end
data/lib/ea/svg.rb ADDED
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ea
4
+ # Ea::Svg is a consumer adapter of Ea::Model::Diagram — it
5
+ # projects the umldi (UML Diagram Interchange) content of a
6
+ # diagram into standalone SVG. Coordinates are taken straight
7
+ # from the source: EA's pixel space (rectleft, recttop,
8
+ # rectright, rectbottom, t_diagramlinks.geometry) or XMI's
9
+ # uml:Diagram owned_element bounds.
10
+ #
11
+ # Distinct from Ea::Diagram::SvgRenderer which operates on the
12
+ # legacy Lutaml::Uml::Document pipeline. This module consumes
13
+ # the canonical Ea::Model types only.
14
+ module Svg
15
+ autoload :BoundsCalculator, "ea/svg/bounds_calculator"
16
+ autoload :StyleResolver, "ea/svg/style_resolver"
17
+ autoload :ElementBox, "ea/svg/element_box"
18
+ autoload :ConnectorPath, "ea/svg/connector_path"
19
+ autoload :Renderer, "ea/svg/renderer"
20
+ end
21
+ end
data/lib/ea/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ea
4
- VERSION = "0.2.5"
4
+ VERSION = "0.3.1"
5
5
  end
data/lib/ea.rb CHANGED
@@ -9,6 +9,10 @@ module Ea
9
9
  class Error < StandardError; end
10
10
 
11
11
  autoload :Qea, "ea/qea"
12
+ autoload :Model, "ea/model"
13
+ autoload :Sources, "ea/sources"
14
+ autoload :Spa, "ea/spa"
15
+ autoload :Svg, "ea/svg"
12
16
  autoload :Diagram, "ea/diagram"
13
17
  autoload :Transformations, "ea/transformations"
14
18
  autoload :Xmi, "ea/xmi"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ea
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.3.1
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-07-18 00:00:00.000000000 Z
11
+ date: 2026-07-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lutaml-model
@@ -234,6 +234,18 @@ files:
234
234
  - TODO.next/38-xmi-parser-feature-parity.md
235
235
  - TODO.next/39-ea-spa-cli-command.md
236
236
  - TODO.next/40-drop-lur-only-check-in-diagrams-extract.md
237
+ - TODO.refactor/01-ea-model-domain-layer.md
238
+ - TODO.refactor/02-ea-model-qea-source-adapter.md
239
+ - TODO.refactor/03-ea-model-xmi-source-adapter.md
240
+ - TODO.refactor/04-ea-model-annotations-tagged-values.md
241
+ - TODO.refactor/05-ea-model-diagrams-coordinates.md
242
+ - TODO.refactor/06-spa-projection-layer.md
243
+ - TODO.refactor/07-spa-sharded-output-strategy.md
244
+ - TODO.refactor/08-spa-build-time-search-index.md
245
+ - TODO.refactor/09-spa-frontend-data-contract.md
246
+ - TODO.refactor/10-spa-cli-command-rework.md
247
+ - TODO.refactor/11-spa-perf-benchmark.md
248
+ - TODO.refactor/12-lutaml-uml-static-site-deprecation.md
237
249
  - TODO.release/01-release-lutaml-uml-030.md
238
250
  - TODO.release/02-fix-lutaml-meta-gem-requires.md
239
251
  - TODO.release/03-release-lutaml-0110.md
@@ -281,6 +293,7 @@ files:
281
293
  - lib/ea/cli/command/repository_builder.rb
282
294
  - lib/ea/cli/command/spa.rb
283
295
  - lib/ea/cli/command/stats.rb
296
+ - lib/ea/cli/command/svg.rb
284
297
  - lib/ea/cli/command/validate.rb
285
298
  - lib/ea/cli/error.rb
286
299
  - lib/ea/cli/output.rb
@@ -302,6 +315,36 @@ files:
302
315
  - lib/ea/diagram/style_resolver.rb
303
316
  - lib/ea/diagram/svg_renderer.rb
304
317
  - lib/ea/diagram/util.rb
318
+ - lib/ea/model.rb
319
+ - lib/ea/model/annotation.rb
320
+ - lib/ea/model/association.rb
321
+ - lib/ea/model/base.rb
322
+ - lib/ea/model/bounds.rb
323
+ - lib/ea/model/classifier.rb
324
+ - lib/ea/model/data_type.rb
325
+ - lib/ea/model/dependency.rb
326
+ - lib/ea/model/diagram.rb
327
+ - lib/ea/model/diagram_connector.rb
328
+ - lib/ea/model/diagram_element.rb
329
+ - lib/ea/model/document.rb
330
+ - lib/ea/model/enumeration.rb
331
+ - lib/ea/model/enumeration_literal.rb
332
+ - lib/ea/model/generalization.rb
333
+ - lib/ea/model/interface.rb
334
+ - lib/ea/model/klass.rb
335
+ - lib/ea/model/metadata.rb
336
+ - lib/ea/model/operation.rb
337
+ - lib/ea/model/package.rb
338
+ - lib/ea/model/parameter.rb
339
+ - lib/ea/model/point.rb
340
+ - lib/ea/model/polymorphic_maps.rb
341
+ - lib/ea/model/primitive_type.rb
342
+ - lib/ea/model/property.rb
343
+ - lib/ea/model/realization.rb
344
+ - lib/ea/model/relationship.rb
345
+ - lib/ea/model/stereotype.rb
346
+ - lib/ea/model/tagged_value.rb
347
+ - lib/ea/model/waypoint.rb
305
348
  - lib/ea/qea.rb
306
349
  - lib/ea/qea/benchmark.rb
307
350
  - lib/ea/qea/database.rb
@@ -390,6 +433,58 @@ files:
390
433
  - lib/ea/qea/verification/document_verifier.rb
391
434
  - lib/ea/qea/verification/element_comparator.rb
392
435
  - lib/ea/qea/verification/structure_matcher.rb
436
+ - lib/ea/sources.rb
437
+ - lib/ea/sources/qea.rb
438
+ - lib/ea/sources/qea/adapter.rb
439
+ - lib/ea/sources/qea/annotation_builder.rb
440
+ - lib/ea/sources/qea/classifier_builder.rb
441
+ - lib/ea/sources/qea/connector_relationship_map.rb
442
+ - lib/ea/sources/qea/diagram_builder.rb
443
+ - lib/ea/sources/qea/diagram_style_parser.rb
444
+ - lib/ea/sources/qea/id_normalizer.rb
445
+ - lib/ea/sources/qea/metadata_builder.rb
446
+ - lib/ea/sources/qea/object_classifier_map.rb
447
+ - lib/ea/sources/qea/operation_builder.rb
448
+ - lib/ea/sources/qea/package_builder.rb
449
+ - lib/ea/sources/qea/property_builder.rb
450
+ - lib/ea/sources/qea/relationship_builder.rb
451
+ - lib/ea/sources/qea/stereotype_builder.rb
452
+ - lib/ea/sources/qea/tagged_value_builder.rb
453
+ - lib/ea/sources/xmi.rb
454
+ - lib/ea/sources/xmi/adapter.rb
455
+ - lib/ea/sources/xmi/annotation_builder.rb
456
+ - lib/ea/sources/xmi/classifier_builder.rb
457
+ - lib/ea/sources/xmi/diagram_builder.rb
458
+ - lib/ea/sources/xmi/id_normalizer.rb
459
+ - lib/ea/sources/xmi/metadata_builder.rb
460
+ - lib/ea/sources/xmi/operation_builder.rb
461
+ - lib/ea/sources/xmi/package_builder.rb
462
+ - lib/ea/sources/xmi/property_builder.rb
463
+ - lib/ea/sources/xmi/relationship_builder.rb
464
+ - lib/ea/sources/xmi/relationship_type_map.rb
465
+ - lib/ea/sources/xmi/type_classifier_map.rb
466
+ - lib/ea/spa.rb
467
+ - lib/ea/spa/configuration.rb
468
+ - lib/ea/spa/generator.rb
469
+ - lib/ea/spa/lazy_ref.rb
470
+ - lib/ea/spa/output.rb
471
+ - lib/ea/spa/output/sharded_multi_file_strategy.rb
472
+ - lib/ea/spa/output/single_file_strategy.rb
473
+ - lib/ea/spa/output/strategy.rb
474
+ - lib/ea/spa/package_tree.rb
475
+ - lib/ea/spa/package_tree_node.rb
476
+ - lib/ea/spa/projector.rb
477
+ - lib/ea/spa/search_entry.rb
478
+ - lib/ea/spa/search_index.rb
479
+ - lib/ea/spa/shard.rb
480
+ - lib/ea/spa/skeleton.rb
481
+ - lib/ea/spa/skeleton_entry.rb
482
+ - lib/ea/svg.rb
483
+ - lib/ea/svg/bounds_calculator.rb
484
+ - lib/ea/svg/connector_path.rb
485
+ - lib/ea/svg/element_box.rb
486
+ - lib/ea/svg/renderer.rb
487
+ - lib/ea/svg/style_resolver.rb
393
488
  - lib/ea/transformations.rb
394
489
  - lib/ea/transformations/configuration.rb
395
490
  - lib/ea/transformations/format_registry.rb