ea 0.2.5 → 0.3.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 (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 +130 -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 +96 -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 +194 -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 +46 -0
  96. data/lib/ea/svg/element_box.rb +71 -0
  97. data/lib/ea/svg/renderer.rb +70 -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,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ea
4
+ module Spa
5
+ class SearchIndex < Lutaml::Model::Serializable
6
+ attribute :version, :string, default: -> { "1.0" }
7
+ attribute :fields, :string, collection: true,
8
+ default: -> { %w[name qualifiedName kind package content] }
9
+ attribute :entries, SearchEntry, collection: true, initialize_empty: true
10
+
11
+ json do
12
+ map "version", to: :version, render_default: true
13
+ map "fields", to: :fields, render_default: true
14
+ map "entries", to: :entries, render_empty: true
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ea
4
+ module Spa
5
+ # Per-entity detail payload. Plain Ruby value object (not a
6
+ # lutaml-model type) because the payload is an arbitrary JSON
7
+ # blob whose shape depends on the model element's kind — we
8
+ # don't want the framework's hash-type cast getting in the way.
9
+ Shard = Struct.new(:id, :kind, :payload, keyword_init: true) do
10
+ def to_h
11
+ { "id" => id, "kind" => kind, "payload" => payload }
12
+ end
13
+
14
+ def to_json(*args)
15
+ JSON.generate(to_h, *args)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ea
4
+ module Spa
5
+ # Top-level SPA skeleton. Plain Struct (not a lutaml-model
6
+ # type) because it's a thin transport wrapper around typed
7
+ # sub-objects (PackageTree, SkeletonEntry) plus a raw metadata
8
+ # hash extracted from the model.
9
+ Skeleton = Struct.new(:metadata, :package_tree, :entries, :view_extras,
10
+ keyword_init: true) do
11
+ def to_json(*args)
12
+ payload = {
13
+ "metadata" => metadata,
14
+ "packageTree" => package_tree,
15
+ "entries" => entries
16
+ }
17
+ payload["viewExtras"] = view_extras unless view_extras.nil? || view_extras.empty?
18
+ JSON.generate(payload, *args)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ea
4
+ module Spa
5
+ # One row in the SPA skeleton: the minimal info needed to
6
+ # render the sidebar, do name searches, and route to a shard.
7
+ # Everything else (properties, operations, etc.) lives in the
8
+ # per-entity Shard.
9
+ class SkeletonEntry < Lutaml::Model::Serializable
10
+ attribute :id, :string
11
+ attribute :name, :string
12
+ attribute :kind, :string # class|enumeration|data_type|...
13
+ attribute :package_id, :string
14
+ attribute :qualified_name, :string
15
+ attribute :shard_url, :string # where to fetch the full Shard
16
+
17
+ json do
18
+ map "id", to: :id
19
+ map "name", to: :name
20
+ map "kind", to: :kind
21
+ map "packageId", to: :package_id
22
+ map "qualifiedName", to: :qualified_name
23
+ map "shardUrl", to: :shard_url
24
+ end
25
+ end
26
+ end
27
+ end
data/lib/ea/spa.rb ADDED
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Ea
6
+ # Ea::Spa is the SPA consumer adapter — a one-way projection of
7
+ # Ea::Model into view-shaped artifacts (Skeleton, Shard,
8
+ # SearchIndex, PackageTree) suitable for a browser frontend.
9
+ #
10
+ # Projection vs. modeling: the SPA does not redefine what a Class
11
+ # is. It owns view-shaped types that refer to model elements by
12
+ # id and add browsing-specific metadata (shard URLs, lazy refs,
13
+ # search content, navigation tree position).
14
+ #
15
+ # Output strategies (single-file vs sharded) live under
16
+ # Ea::Spa::Output and project the same artifacts to disk.
17
+ module Spa
18
+ autoload :SkeletonEntry, "ea/spa/skeleton_entry"
19
+ autoload :Skeleton, "ea/spa/skeleton"
20
+ autoload :PackageTreeNode, "ea/spa/package_tree_node"
21
+ autoload :PackageTree, "ea/spa/package_tree"
22
+ autoload :SearchEntry, "ea/spa/search_entry"
23
+ autoload :SearchIndex, "ea/spa/search_index"
24
+ autoload :Shard, "ea/spa/shard"
25
+ autoload :LazyRef, "ea/spa/lazy_ref"
26
+ autoload :Projector, "ea/spa/projector"
27
+ autoload :Output, "ea/spa/output"
28
+ autoload :Generator, "ea/spa/generator"
29
+ autoload :Configuration, "ea/spa/configuration"
30
+ end
31
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ea
4
+ module Svg
5
+ # Computes the actual drawing-area bounding box of an
6
+ # Ea::Model::Diagram. EA stores bounds in pixel space with two
7
+ # quirks: element rects can be inverted (rectbottom < recttop,
8
+ # producing negative height), and elements/connectors can sit
9
+ # outside the canvas bounds. The drawing area is the union of
10
+ # all element rects and connector waypoint positions.
11
+ class BoundsCalculator
12
+ attr_reader :diagram
13
+
14
+ def initialize(diagram)
15
+ @diagram = diagram
16
+ end
17
+
18
+ def compute
19
+ points = all_points
20
+ return fallback_bounds if points.empty?
21
+
22
+ xs = points.map(&:first)
23
+ ys = points.map(&:last)
24
+ Bounds.new(x: xs.min, y: ys.min, width: xs.max - xs.min,
25
+ height: ys.max - ys.min)
26
+ end
27
+
28
+ private
29
+
30
+ def all_points
31
+ points = []
32
+ diagram.elements.each do |elem|
33
+ next unless elem.bounds
34
+
35
+ b = normalize_bounds(elem.bounds)
36
+ points << [b.x, b.y]
37
+ points << [b.x + b.width, b.y + b.height]
38
+ end
39
+ diagram.connectors.each do |conn|
40
+ conn.waypoints.each do |wp|
41
+ next unless wp.position
42
+
43
+ points << [wp.position.x, wp.position.y]
44
+ end
45
+ end
46
+ points
47
+ end
48
+
49
+ # EA occasionally stores inverted rects (rectbottom < recttop).
50
+ # Normalize so width/height are non-negative.
51
+ def normalize_bounds(bounds)
52
+ x = bounds.x
53
+ y = bounds.y
54
+ w = bounds.width
55
+ h = bounds.height
56
+ x, w = x + w, -w if w.negative?
57
+ y, h = y + h, -h if h.negative?
58
+ Bounds.new(x: x, y: y, width: w, height: h)
59
+ end
60
+
61
+ def fallback_bounds
62
+ return Bounds.new(x: 0, y: 0, width: 1, height: 1) unless diagram.bounds
63
+
64
+ Bounds.new(x: diagram.bounds.x, y: diagram.bounds.y,
65
+ width: diagram.bounds.width.abs,
66
+ height: diagram.bounds.height.abs)
67
+ end
68
+
69
+ # Internal value type — keep private to avoid polluting the
70
+ # Ea::Svg namespace.
71
+ Bounds = Struct.new(:x, :y, :width, :height, keyword_init: true)
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ea
4
+ module Svg
5
+ # Renders one DiagramConnector as an SVG <polyline> through
6
+ # its waypoints. Arrowheads and per-direction routing are
7
+ # future work; today we emit a straight-segment polyline
8
+ # matching the source layout.
9
+ class ConnectorPath
10
+ attr_reader :connector
11
+
12
+ def initialize(connector)
13
+ @connector = connector
14
+ end
15
+
16
+ def render
17
+ points = waypoints
18
+ return "" if points.empty?
19
+
20
+ <<~SVG.chomp
21
+ <polyline points="#{points.join(' ')}"
22
+ fill="none" stroke="#{stroke_color}"
23
+ stroke-width="#{stroke_width}"/>
24
+ SVG
25
+ end
26
+
27
+ private
28
+
29
+ def waypoints
30
+ connector.waypoints.filter_map do |wp|
31
+ next unless wp.position
32
+
33
+ "#{wp.position.x},#{wp.position.y}"
34
+ end
35
+ end
36
+
37
+ def stroke_color
38
+ StyleResolver.new(connector.style).stroke_color
39
+ end
40
+
41
+ def stroke_width
42
+ StyleResolver.new(connector.style).stroke_width
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ostruct"
4
+
5
+ module Ea
6
+ module Svg
7
+ # Renders one DiagramElement as an SVG <g> containing the rect
8
+ # and a name label. Class-shape rendering (with attribute /
9
+ # operation compartments) is future work; for now we emit a
10
+ # simple labeled box that mirrors EA's logical placement.
11
+ class ElementBox
12
+ attr_reader :element, :model_index
13
+
14
+ def initialize(element, model_index:)
15
+ @element = element
16
+ @model_index = model_index
17
+ end
18
+
19
+ def render
20
+ return "" unless element.bounds
21
+
22
+ b = normalize_bounds(element.bounds)
23
+ style = StyleResolver.new(element.style)
24
+ label_text = model_element_name
25
+
26
+ <<~SVG.chomp
27
+ <g class="element" data-element-id="#{escape(element.id)}">
28
+ <rect x="#{b.x}" y="#{b.y}" width="#{b.width}" height="#{b.height}"
29
+ fill="#{style.fill_color}" stroke="#{style.stroke_color}"
30
+ stroke-width="#{style.stroke_width}"/>
31
+ <text x="#{b.x + (b.width / 2.0)}"
32
+ y="#{b.y + (b.height / 2.0)}"
33
+ text-anchor="middle" dominant-baseline="middle"
34
+ fill="#{style.font_color}"
35
+ font-family="sans-serif" font-size="14">#{escape(label_text)}</text>
36
+ </g>
37
+ SVG
38
+ end
39
+
40
+ private
41
+
42
+ def model_element_name
43
+ ref = element.model_element_ref
44
+ return "(unbound)" unless ref
45
+
46
+ model = model_index[ref]
47
+ model&.name || "(missing #{ref})"
48
+ end
49
+
50
+ def normalize_bounds(bounds)
51
+ x = bounds.x
52
+ y = bounds.y
53
+ w = bounds.width
54
+ h = bounds.height
55
+ x, w = x + w, -w if w.negative?
56
+ y, h = y + h, -h if h.negative?
57
+ OpenStruct.new(x: x, y: y, width: w, height: h)
58
+ end
59
+
60
+ def escape(text)
61
+ return "" if text.nil?
62
+
63
+ text.to_s
64
+ .gsub("&", "&amp;")
65
+ .gsub("<", "&lt;")
66
+ .gsub(">", "&gt;")
67
+ .gsub("\"", "&quot;")
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,70 @@
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).render
56
+ end.join("\n ")
57
+ end
58
+
59
+ def pad(bounds)
60
+ p = options[:padding]
61
+ OpenStruct.new(
62
+ x: bounds.x - p,
63
+ y: bounds.y - p,
64
+ width: bounds.width + (2 * p),
65
+ height: bounds.height + (2 * p)
66
+ )
67
+ end
68
+ end
69
+ end
70
+ 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.0"
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.0
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-19 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