ea 0.3.1 → 0.5.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 (544) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +3 -0
  3. data/TODO.complete/01-t-xref-parsing.md +91 -0
  4. data/TODO.complete/02-per-label-geometry.md +50 -0
  5. data/TODO.complete/03-object-properties-constraints.md +57 -0
  6. data/TODO.complete/04-operation-params.md +37 -0
  7. data/TODO.complete/05-pdata-flag-matrix.md +52 -0
  8. data/TODO.complete/06-emf-image-rendering.md +34 -0
  9. data/TODO.complete/07-auxiliary-tables.md +47 -0
  10. data/TODO.complete/10-mdg-stereotype-registry.md +40 -0
  11. data/TODO.complete/11-gml-xsd-generation.md +42 -0
  12. data/TODO.complete/13-shapescript-interpreter.md +28 -0
  13. data/TODO.complete/20-cli-diff.md +46 -0
  14. data/TODO.complete/21-cli-render.md +26 -0
  15. data/TODO.complete/22-cli-export.md +29 -0
  16. data/TODO.complete/23-cli-mdg.md +23 -0
  17. data/TODO.complete/30-headerlines-ocp-refactor.md +72 -0
  18. data/TODO.complete/31-public-send-cleanup.md +61 -0
  19. data/TODO.complete/32-spec-coverage.md +33 -0
  20. data/TODO.complete/33-blocked-parity-gaps.md +41 -0
  21. data/TODO.complete/36-stereotype-icon-wiring.md +32 -0
  22. data/TODO.complete/37-cli-lint.md +32 -0
  23. data/TODO.complete/38-cli-query.md +26 -0
  24. data/TODO.complete/39-cli-info.md +23 -0
  25. data/TODO.complete/40-ocl-evaluator.md +31 -0
  26. data/TODO.complete/41-round-trip-spec.md +18 -0
  27. data/TODO.complete/42-html-diff-report.md +18 -0
  28. data/TODO.complete/43-json-schema-export.md +20 -0
  29. data/TODO.complete/44-remaining-qea-tables.md +40 -0
  30. data/TODO.complete/45-shapescript-extensions.md +25 -0
  31. data/TODO.complete/46-xsd-consolidation.md +20 -0
  32. data/TODO.complete/47-headerlines-legacy-removal.md +20 -0
  33. data/TODO.complete/STATUS.md +109 -0
  34. data/TODO.diagrams/01-svg-measurement-harness.md +31 -0
  35. data/TODO.diagrams/01-xmi-extension-elements-parsing.md +67 -0
  36. data/TODO.diagrams/02-diagram-element-rich-model.md +61 -0
  37. data/TODO.diagrams/02-polygon-over-rendering.md +29 -0
  38. data/TODO.diagrams/03-ea-style-svg-emitter.md +70 -0
  39. data/TODO.diagrams/03-text-over-rendering.md +30 -0
  40. data/TODO.diagrams/04-connector-routing-from-soid-eoid.md +55 -0
  41. data/TODO.diagrams/04-rect-under-rendering.md +33 -0
  42. data/TODO.diagrams/05-canvas-dimension-parity.md +51 -0
  43. data/TODO.diagrams/05-marker-rendering-per-relationship-type.md +49 -0
  44. data/TODO.diagrams/06-connector-labels.md +49 -0
  45. data/TODO.diagrams/06-group-layering-parity.md +39 -0
  46. data/TODO.diagrams/07-canvas-size-and-viewbox.md +39 -0
  47. data/TODO.diagrams/07-text-content-fidelity.md +65 -0
  48. data/TODO.diagrams/08-qea-direct-pipeline.md +46 -0
  49. data/TODO.diagrams/08-visual-regression-harness.md +34 -0
  50. data/TODO.diagrams/09-cli-render-all-diagrams.md +25 -0
  51. data/TODO.diagrams/10-stereotype-color-config.md +29 -0
  52. data/TODO.diagrams/11-elkrb-auto-layout-integration.md +53 -0
  53. data/TODO.diagrams/12-connector-labels.md +40 -0
  54. data/TODO.diagrams/12-per-entity-svg-layer-ordering.md +24 -0
  55. data/TODO.diagrams/13-marker-polygon-vs-path-dispatch.md +20 -0
  56. data/TODO.diagrams/13-per-text-type-font-sizes.md +33 -0
  57. data/TODO.diagrams/14-center-header-text.md +33 -0
  58. data/TODO.diagrams/14-filter-diagram-frame-elements.md +18 -0
  59. data/TODO.diagrams/15-deep-dead-code-audit.md +47 -0
  60. data/TODO.diagrams/15-per-element-font-from-style.md +24 -0
  61. data/TODO.diagrams/16-canvas-marker-extent.md +30 -0
  62. data/TODO.diagrams/16-document-remaining-parity-gaps.md +91 -0
  63. data/TODO.diagrams/17-italic-abstract-classes.md +28 -0
  64. data/TODO.diagrams/17-remaining-parity-gaps.md +90 -0
  65. data/TODO.diagrams/18-canvas-from-image-bounds.md +20 -0
  66. data/TODO.diagrams/18-property-lookup-index.md +42 -0
  67. data/TODO.diagrams/19-connector-sx-sy-routing.md +27 -0
  68. data/TODO.diagrams/19-replace-respond-to-with-is-a.md +31 -0
  69. data/TODO.diagrams/20-split-labels-emitter.md +56 -0
  70. data/TODO.diagrams/20-visibility-glyph-font-encoding.md +27 -0
  71. data/TODO.diagrams/21-aggregation-navigability-arrow.md +21 -0
  72. data/TODO.diagrams/21-auto-generated-legend-block.md +65 -0
  73. data/TODO.diagrams/22-ghost-element-discriminator.md +57 -0
  74. data/TODO.diagrams/22-style-based-path-grouping.md +28 -0
  75. data/TODO.diagrams/23-marker-polygon-deduplication.md +47 -0
  76. data/TODO.diagrams/23-multiplicity-label-positioning.md +29 -0
  77. data/TODO.diagrams/24-marker-anchor-structural.md +35 -0
  78. data/TODO.diagrams/24-track-marker-anchors-structurally.md +66 -0
  79. data/TODO.diagrams/24-truncate-properties-to-fit-box.md +24 -0
  80. data/TODO.diagrams/26-phantom-general-parent-rendering.md +59 -0
  81. data/TODO.diagrams/27-path-grouping-mode-detection.md +43 -0
  82. data/TODO.diagrams/28-architecture-cleanup-batch.md +47 -0
  83. data/TODO.diagrams/30-decompose-elements-groups-for.md +52 -0
  84. data/TODO.diagrams/32-examples-coverage-batch.md +78 -0
  85. data/TODO.diagrams/36-instance-specification-model.md +42 -0
  86. data/TODO.diagrams/37-element-icon-decorations.md +41 -0
  87. data/TODO.diagrams/38-html-note-and-receptions.md +32 -0
  88. data/TODO.diagrams/39-property-stereotype-discriminator.md +40 -0
  89. data/TODO.diagrams/40-standalone-1-discriminator.md +38 -0
  90. data/TODO.diagrams/41-xmi-to-svg-pipeline.md +113 -0
  91. data/TODO.diagrams/42-close-all-parity-deltas.md +69 -0
  92. data/TODO.diagrams/43-marker-deduplication-strategy.md +54 -0
  93. data/TODO.diagrams/44-element-icon-decorations.md +34 -0
  94. data/TODO.diagrams/45-phantom-parent-class-boxes.md +40 -0
  95. data/TODO.diagrams/46-user-drawn-legend-swatches.md +44 -0
  96. data/TODO.diagrams/47-attribute-line-fidelity.md +72 -0
  97. data/TODO.diagrams/48-spec-coverage-critical-emitter-components.md +45 -0
  98. data/TODO.diagrams/49-spec-coverage-orchestrators.md +25 -0
  99. data/TODO.diagrams/50-examples-parity.md +85 -0
  100. data/TODO.diagrams/51-property-oy-gap-and-remaining-gaps.md +48 -0
  101. data/TODO.diagrams/52-marker-registration-architecture.md +89 -0
  102. data/TODO.diagrams/53-remaining-example-gaps.md +86 -0
  103. data/TODO.diagrams/54-display-name-nested-classes.md +40 -0
  104. data/TODO.diagrams/55-visibility-icon-discriminator.md +58 -0
  105. data/TODO.diagrams/56-package-contents-rendering.md +148 -0
  106. data/TODO.diagrams/57-instance-specification-model.md +100 -0
  107. data/TODO.diagrams/58-domain-model-note-text.md +67 -0
  108. data/TODO.diagrams/59-classes-arrow-discriminator.md +57 -0
  109. data/TODO.diagrams/60-testschema-association-marker.md +40 -0
  110. data/TODO.diagrams/61-legend-block-rendering.md +55 -0
  111. data/TODO.diagrams/61-plateau-parity-gaps.md +59 -0
  112. data/TODO.diagrams/62-ghost-element-rendering.md +56 -0
  113. data/TODO.diagrams/63-qualified-name-wrap.md +36 -0
  114. data/TODO.diagrams/64-property-stereotype-labels.md +22 -0
  115. data/TODO.diagrams/65-path-coordinate-frame.md +62 -0
  116. data/TODO.diagrams/67-path-coordinate-frame.md +62 -0
  117. data/TODO.diagrams/68-inherited-attributes.md +65 -0
  118. data/TODO.diagrams/69-package-anchor-conditional.md +29 -0
  119. data/TODO.diagrams/70-mdg-technology-support.md +68 -0
  120. data/TODO.diagrams/71-off-canvas-parent-ghost.md +45 -0
  121. data/TODO.diagrams/72-basic-attr-divider-paths.md +39 -0
  122. data/TODO.diagrams/73-plateau-polygon-gap.md +69 -0
  123. data/TODO.diagrams/74-plateau-rect-gap.md +22 -0
  124. data/TODO.diagrams/75-plateau-text-gap.md +39 -0
  125. data/TODO.diagrams/76-basic-poly-path-gaps.md +41 -0
  126. data/TODO.diagrams/77-basic-text-overrender.md +40 -0
  127. data/TODO.diagrams/78-headerlines-ocp-refactor.md +65 -0
  128. data/TODO.diagrams/79-architecture-backlog.md +65 -0
  129. data/TODO.diagrams/80-basic-triangle-polygons.md +51 -0
  130. data/TODO.diagrams/81-plateau-path-overrender.md +53 -0
  131. data/TODO.diagrams/82-appearance-canvas-offset.md +54 -0
  132. data/TODO.diagrams/83-3d-diagram-subtitle.md +58 -0
  133. data/TODO.diagrams/84-canvas-offset-mismatches.md +61 -0
  134. data/TODO.diagrams/85-phantom-property-overrender.md +95 -0
  135. data/TODO.diagrams/86-foreign-package-rule.md +62 -0
  136. data/TODO.diagrams/87-internal-tech-encryption.md +80 -0
  137. data/TODO.diagrams/EXAMPLES_STATUS.md +88 -0
  138. data/TODO.diagrams/README.md +69 -0
  139. data/TODO.diagrams/STATUS.md +73 -0
  140. data/TODO.fixup/01-default-grouped-paths.md +34 -0
  141. data/TODO.fixup/02-marker-consolidation-per-connector.md +20 -0
  142. data/TODO.fixup/03-diagram-font-inference.md +28 -0
  143. data/TODO.fixup/04-extract-bounds-calculator.md +25 -0
  144. data/TODO.fixup/05-marker-registry-ocp.md +32 -0
  145. data/TODO.fixup/06-connector-path-bend-routing.md +28 -0
  146. data/TODO.fixup/07-edge-attachment-formula.md +22 -0
  147. data/TODO.fixup/08-visual-diff-harness.md +28 -0
  148. data/TODO.fixup/09-extract-element-compartments.md +34 -0
  149. data/TODO.fixup/10-canvas-width-overshoot-fix.md +20 -0
  150. data/TODO.fixup/11-layer-sequencer-extraction.md +18 -0
  151. data/TODO.fixup/12-path-style-harmony.md +23 -0
  152. data/TODO.fixup/13-datatype-stereotype-fallback.md +28 -0
  153. data/TODO.fixup/14-ea-exe-reverse-engineering-notes.md +56 -0
  154. data/TODO.fixup/15-enumeration-literal-rendering.md +30 -0
  155. data/TODO.fixup/16-operation-compartment-rendering.md +42 -0
  156. data/TODO.fixup/17-path-count-calibration.md +27 -0
  157. data/TODO.fixup/18-polygon-count-calibration.md +32 -0
  158. data/TODO.fixup/19-rect-count-undershoot-investigation.md +40 -0
  159. data/TODO.fixup/20-stereotype-color-from-classifier.md +18 -0
  160. data/TODO.fixup/21-visibility-filter-for-properties.md +24 -0
  161. data/TODO.fixup/22-multiplicity-display-rule-calibration.md +25 -0
  162. data/TODO.fixup/23-diagram-frame-title-element.md +31 -0
  163. data/TODO.fixup/24-note-element-rendering.md +23 -0
  164. data/TODO.fixup/25-ea-exe-disassembly-findings.md +177 -0
  165. data/TODO.fixup/26-svg-renderer-architecture.md +78 -0
  166. data/TODO.fixup/27-svg-element-emitters-disassembly.md +135 -0
  167. data/TODO.fixup/28-geometry-parser-identification.md +57 -0
  168. data/TODO.fixup/29-qea-svg-xmi-triple-comparison.md +185 -0
  169. data/TODO.fixup/30-theme-system-stub.md +46 -0
  170. data/TODO.fixup/31-theme-value-object-registry.md +17 -0
  171. data/TODO.fixup/32-styleex-on-diagram-model.md +22 -0
  172. data/TODO.fixup/33-text-encoding-decimals-rotation.md +29 -0
  173. data/TODO.fixup/34-per-type-fill-via-theme.md +18 -0
  174. data/TODO.fixup/35-stroke-width-per-theme.md +7 -0
  175. data/TODO.fixup/36-qea-rect-coord-normalization.md +24 -0
  176. data/TODO.fixup/37-package-shape-rendering.md +22 -0
  177. data/TODO.fixup/38-note-element-rendering.md +15 -0
  178. data/TODO.fixup/39-styleex-flag-honoring.md +25 -0
  179. data/TODO.fixup/40-connector-dashed-lines.md +15 -0
  180. data/TODO.fixup/41-diagram-frame-showborder-detection.md +23 -0
  181. data/TODO.fixup/42-textrenderer-centralization.md +10 -0
  182. data/TODO.fixup/43-colorresolver-unification.md +24 -0
  183. data/TODO.fixup/44-theme-aware-textrenderer.md +17 -0
  184. data/TODO.fixup/45-theme-aware-fontresolver.md +22 -0
  185. data/TODO.fixup/46-style-parameterized-by-theme.md +21 -0
  186. data/TODO.fixup/47-canvas-frame-inset.md +19 -0
  187. data/TODO.fixup/48-background-rect-format.md +15 -0
  188. data/TODO.fixup/49-all-samples-integration-test.md +17 -0
  189. data/TODO.fixup/50-svg-emitter-architecture-docs.md +33 -0
  190. data/TODO.fixup/51-promote-theme-to-ea-namespace.md +28 -0
  191. data/TODO.fixup/52-theme-definition-integrated-fills.md +26 -0
  192. data/TODO.fixup/53-theme-registry-yaml-loading.md +50 -0
  193. data/TODO.fixup/54-diagram-theme-api.md +50 -0
  194. data/TODO.fixup/55-update-eaemitter-to-ea-theme.md +23 -0
  195. data/TODO.fixup/56-theme-yaml-files.md +65 -0
  196. data/TODO.fixup/57-theme-specs-and-integration.md +27 -0
  197. data/TODO.fixup/58-ea-entry-point-theme-autoload.md +20 -0
  198. data/TODO.fixup/59-thread-theme-through-all-renderers.md +29 -0
  199. data/TODO.fixup/60-cli-theme-option.md +22 -0
  200. data/TODO.fixup/61-theme-validation.md +28 -0
  201. data/TODO.fixup/62-theme-builder-dsl.md +31 -0
  202. data/TODO.fixup/63-theme-integration-rendering-spec.md +24 -0
  203. data/TODO.fixup/64-theme-writeback-styleex.md +21 -0
  204. data/TODO.fixup/65-remove-dead-eaemitter-theme-files.md +30 -0
  205. data/TODO.fixup/66-styleex-writeback.md +22 -0
  206. data/TODO.fixup/67-delete-dead-code.md +28 -0
  207. data/TODO.fixup/68-figure-parity-status.md +82 -0
  208. data/TODO.fixup/69-package-polygon-rendering.md +54 -0
  209. data/TODO.fixup/70-tagged-values-compartment.md +39 -0
  210. data/TODO.fixup/71-auto-detect-theme-from-xmi.md +37 -0
  211. data/TODO.fixup/72-sample-exports-as-regression-specs.md +37 -0
  212. data/TODO.fixup/73-delete-dead-transformations.md +14 -0
  213. data/TODO.fixup/74-delete-dead-diagram-renderers.md +18 -0
  214. data/TODO.fixup/75-visibility-legend-icons.md +23 -0
  215. data/TODO.fixup/76-plateau-text-undershoot.md +27 -0
  216. data/TODO.fixup/77-canvas-frame-margins.md +28 -0
  217. data/TODO.fixup/78-note-element-rendering.md +30 -0
  218. data/TODO.fixup/79-operation-compartment-rendering.md +27 -0
  219. data/TODO.fixup/80-tagged-value-stereotype-visibility.md +37 -0
  220. data/TODO.fixup/81-figure-parity-current-state.md +63 -0
  221. data/config/qea_schema.yml +356 -0
  222. data/config/stereotype_colors.yml +15 -0
  223. data/config/themes/119.yml +98 -0
  224. data/config/themes/default.yml +14 -0
  225. data/examples/exports/20251010_current_plateau_v5/UML_EA.DTD +6856 -0
  226. data/examples/exports/20251010_current_plateau_v5/model.xml +96709 -0
  227. data/examples/exports/ArcGISWorkspace_template/UML_EA.DTD +6856 -0
  228. data/examples/exports/ArcGISWorkspace_template/model.xml +1427 -0
  229. data/examples/exports/UmlModel_template/UML_EA.DTD +6856 -0
  230. data/examples/exports/UmlModel_template/model.xml +23 -0
  231. data/examples/exports/basic/UML_EA.DTD +6856 -0
  232. data/examples/exports/basic/model.xml +8039 -0
  233. data/examples/exports/simple/UML_EA.DTD +6856 -0
  234. data/examples/exports/simple/model.xml +585 -0
  235. data/examples/exports/simple_example/UML_EA.DTD +6856 -0
  236. data/examples/exports/simple_example/model.xml +23 -0
  237. data/examples/exports/test/UML_EA.DTD +6856 -0
  238. data/examples/exports/test/model.xml +1638 -0
  239. data/examples/qea/basic.qea +0 -0
  240. data/frontend/README.md +51 -0
  241. data/frontend/dist/app.iife.js +24 -0
  242. data/frontend/dist/style.css +1 -0
  243. data/frontend/index.html +26 -0
  244. data/frontend/package-lock.json +2359 -0
  245. data/frontend/package.json +26 -0
  246. data/frontend/src/App.vue +59 -0
  247. data/frontend/src/app.ts +8 -0
  248. data/frontend/src/components/AppHeader.vue +127 -0
  249. data/frontend/src/components/AppSidebar.vue +119 -0
  250. data/frontend/src/components/ClassDetails.vue +247 -0
  251. data/frontend/src/components/DiagramView.vue +79 -0
  252. data/frontend/src/components/PackageDetails.vue +92 -0
  253. data/frontend/src/components/PackageTreeNode.vue +64 -0
  254. data/frontend/src/components/SearchResults.vue +48 -0
  255. data/frontend/src/components/WelcomeView.vue +87 -0
  256. data/frontend/src/shims-vue.d.ts +5 -0
  257. data/frontend/src/stores/dataStore.ts +79 -0
  258. data/frontend/src/stores/uiStore.ts +167 -0
  259. data/frontend/src/styles/main.css +1566 -0
  260. data/frontend/src/types.ts +221 -0
  261. data/frontend/tests/e2e/__screenshots__/new-dark-mode.png +0 -0
  262. data/frontend/tests/e2e/__screenshots__/new-package-details.png +0 -0
  263. data/frontend/tests/e2e/__screenshots__/new-search-modal.png +0 -0
  264. data/frontend/tests/e2e/__screenshots__/new-sidebar-collapsed.png +0 -0
  265. data/frontend/tests/e2e/__screenshots__/new-welcome.png +0 -0
  266. data/frontend/tests/e2e/render.spec.ts +188 -0
  267. data/frontend/tsconfig.json +20 -0
  268. data/frontend/vite.config.ts +26 -0
  269. data/frontend/vitest.config.ts +8 -0
  270. data/lib/ea/cli/app.rb +62 -1
  271. data/lib/ea/cli/command/diagrams.rb +37 -28
  272. data/lib/ea/cli/command/diff.rb +46 -0
  273. data/lib/ea/cli/command/export.rb +80 -0
  274. data/lib/ea/cli/command/info.rb +75 -0
  275. data/lib/ea/cli/command/lint.rb +48 -0
  276. data/lib/ea/cli/command/mdg.rb +98 -0
  277. data/lib/ea/cli/command/query.rb +34 -0
  278. data/lib/ea/cli/command/render.rb +135 -0
  279. data/lib/ea/cli/command/svg.rb +43 -6
  280. data/lib/ea/cli/command.rb +7 -0
  281. data/lib/ea/diagram/display_config.rb +184 -0
  282. data/lib/ea/diagram.rb +4 -41
  283. data/lib/ea/diff/change.rb +30 -0
  284. data/lib/ea/diff/comparator.rb +82 -0
  285. data/lib/ea/diff/html_reporter.rb +91 -0
  286. data/lib/ea/diff.rb +15 -0
  287. data/lib/ea/export/json/generator.rb +42 -0
  288. data/lib/ea/export/json.rb +12 -0
  289. data/lib/ea/export/json_schema/generator.rb +77 -0
  290. data/lib/ea/export/json_schema.rb +12 -0
  291. data/lib/ea/export/plantuml/generator.rb +73 -0
  292. data/lib/ea/export/plantuml.rb +12 -0
  293. data/lib/ea/export/xmi/generator.rb +77 -0
  294. data/lib/ea/export/xmi.rb +11 -0
  295. data/lib/ea/export/xsd/class_mapping.rb +65 -0
  296. data/lib/ea/export/xsd/generator.rb +142 -0
  297. data/lib/ea/export/xsd/namespace_registry.rb +82 -0
  298. data/lib/ea/export/xsd.rb +19 -0
  299. data/lib/ea/export.rb +14 -0
  300. data/lib/ea/image/emf_renderer.rb +42 -0
  301. data/lib/ea/image.rb +12 -0
  302. data/lib/ea/lint/engine.rb +30 -0
  303. data/lib/ea/lint/lint_rule.rb +38 -0
  304. data/lib/ea/lint/offense.rb +18 -0
  305. data/lib/ea/lint/rules/cyclic_generalization.rb +62 -0
  306. data/lib/ea/lint/rules/duplicate_name.rb +28 -0
  307. data/lib/ea/lint/rules/missing_stereotype.rb +35 -0
  308. data/lib/ea/lint/rules/naming_convention.rb +44 -0
  309. data/lib/ea/lint/rules/orphan_element.rb +28 -0
  310. data/lib/ea/lint/rules.rb +14 -0
  311. data/lib/ea/lint.rb +13 -0
  312. data/lib/ea/mdg/document.rb +120 -0
  313. data/lib/ea/mdg/loader.rb +118 -0
  314. data/lib/ea/mdg/registry.rb +98 -0
  315. data/lib/ea/mdg/stereotype_alias_registry.rb +77 -0
  316. data/lib/ea/mdg/xml/applies_to.rb +18 -0
  317. data/lib/ea/mdg/xml/apply.rb +18 -0
  318. data/lib/ea/mdg/xml/content.rb +18 -0
  319. data/lib/ea/mdg/xml/documentation.rb +24 -0
  320. data/lib/ea/mdg/xml/stereotype.rb +28 -0
  321. data/lib/ea/mdg/xml/stereotypes.rb +18 -0
  322. data/lib/ea/mdg/xml/tag.rb +28 -0
  323. data/lib/ea/mdg/xml/tagged_values.rb +18 -0
  324. data/lib/ea/mdg/xml/technology.rb +28 -0
  325. data/lib/ea/mdg/xml/uml_profile.rb +22 -0
  326. data/lib/ea/mdg/xml/uml_profiles.rb +18 -0
  327. data/lib/ea/mdg/xml.rb +24 -0
  328. data/lib/ea/mdg.rb +25 -0
  329. data/lib/ea/model/classifier.rb +4 -0
  330. data/lib/ea/model/constraint.rb +24 -0
  331. data/lib/ea/model/diagram.rb +85 -0
  332. data/lib/ea/model/diagram_connector.rb +53 -1
  333. data/lib/ea/model/diagram_element.rb +44 -0
  334. data/lib/ea/model/document.rb +47 -2
  335. data/lib/ea/model/ghost_label.rb +32 -0
  336. data/lib/ea/model/instance_specification.rb +34 -0
  337. data/lib/ea/model/legend.rb +43 -0
  338. data/lib/ea/model/legend_item.rb +26 -0
  339. data/lib/ea/model/note.rb +28 -0
  340. data/lib/ea/model/operation.rb +2 -0
  341. data/lib/ea/model/property.rb +2 -0
  342. data/lib/ea/model/relationship.rb +2 -0
  343. data/lib/ea/model/signal.rb +14 -0
  344. data/lib/ea/model/slot.rb +19 -0
  345. data/lib/ea/model.rb +8 -0
  346. data/lib/ea/ocl/evaluator.rb +94 -0
  347. data/lib/ea/ocl/nodes.rb +30 -0
  348. data/lib/ea/ocl/parser.rb +133 -0
  349. data/lib/ea/ocl/unsupported_error.rb +7 -0
  350. data/lib/ea/ocl.rb +13 -0
  351. data/lib/ea/qea/factory/document_builder.rb +24 -10
  352. data/lib/ea/qea/factory/generalization_builder.rb +9 -11
  353. data/lib/ea/qea/infrastructure/table_reader.rb +9 -0
  354. data/lib/ea/qea/models/ea_author.rb +35 -0
  355. data/lib/ea/qea/models/ea_glossary.rb +34 -0
  356. data/lib/ea/qea/models/ea_image.rb +53 -0
  357. data/lib/ea/qea/models/ea_implement.rb +32 -0
  358. data/lib/ea/qea/models/ea_list.rb +42 -0
  359. data/lib/ea/qea/models/ea_object_effort.rb +34 -0
  360. data/lib/ea/qea/models/ea_object_problem.rb +37 -0
  361. data/lib/ea/qea/models/ea_object_require.rb +34 -0
  362. data/lib/ea/qea/models/ea_object_resource.rb +34 -0
  363. data/lib/ea/qea/models/ea_object_risk.rb +34 -0
  364. data/lib/ea/qea/models/ea_object_scenario.rb +34 -0
  365. data/lib/ea/qea/models/ea_object_test.rb +35 -0
  366. data/lib/ea/qea/models/ea_object_trx.rb +34 -0
  367. data/lib/ea/qea/models/ea_operation.rb +7 -0
  368. data/lib/ea/qea/models/ea_palette.rb +30 -0
  369. data/lib/ea/qea/models/ea_palette_item.rb +36 -0
  370. data/lib/ea/qea/models/ea_phase.rb +40 -0
  371. data/lib/ea/qea/models/ea_role_constraint.rb +32 -0
  372. data/lib/ea/qea/models/ea_secrypt.rb +34 -0
  373. data/lib/ea/qea/models/ea_version.rb +39 -0
  374. data/lib/ea/qea/models/ea_xref.rb +11 -1
  375. data/lib/ea/qea/models.rb +19 -0
  376. data/lib/ea/qea/services/database_loader.rb +22 -1
  377. data/lib/ea/query/builder.rb +108 -0
  378. data/lib/ea/query.rb +9 -0
  379. data/lib/ea/render/image_converter.rb +101 -0
  380. data/lib/ea/render.rb +10 -0
  381. data/lib/ea/shapescript/parser.rb +208 -0
  382. data/lib/ea/shapescript/renderer.rb +74 -0
  383. data/lib/ea/shapescript/shape.rb +34 -0
  384. data/lib/ea/shapescript.rb +24 -0
  385. data/lib/ea/sources/qea/adapter.rb +22 -5
  386. data/lib/ea/sources/qea/classifier_builder.rb +184 -7
  387. data/lib/ea/sources/qea/diagram_builder.rb +352 -24
  388. data/lib/ea/sources/qea/id_normalizer.rb +16 -1
  389. data/lib/ea/sources/qea/instance_builder.rb +113 -0
  390. data/lib/ea/sources/qea/legend_builder.rb +137 -0
  391. data/lib/ea/sources/qea/note_builder.rb +58 -0
  392. data/lib/ea/sources/qea/object_classifier_map.rb +6 -1
  393. data/lib/ea/sources/qea/operation_builder.rb +1 -0
  394. data/lib/ea/sources/qea/package_builder.rb +16 -0
  395. data/lib/ea/sources/qea/relationship_builder.rb +21 -5
  396. data/lib/ea/sources/qea/tagged_value_builder.rb +28 -9
  397. data/lib/ea/sources/qea/xref/legend_definition.rb +35 -0
  398. data/lib/ea/sources/qea/xref/parser.rb +150 -0
  399. data/lib/ea/sources/qea/xref/property_definition.rb +29 -0
  400. data/lib/ea/sources/qea/xref/record.rb +41 -0
  401. data/lib/ea/sources/qea/xref/stereotype_application.rb +37 -0
  402. data/lib/ea/sources/qea/xref.rb +27 -0
  403. data/lib/ea/sources/qea.rb +4 -0
  404. data/lib/ea/sources/xmi/adapter.rb +80 -2
  405. data/lib/ea/sources/xmi/annotation_builder.rb +1 -1
  406. data/lib/ea/sources/xmi/classifier_builder.rb +10 -1
  407. data/lib/ea/sources/xmi/diagram_builder.rb +242 -45
  408. data/lib/ea/sources/xmi/extension_elements.rb +74 -0
  409. data/lib/ea/sources/xmi/extension_geometry_parser.rb +124 -0
  410. data/lib/ea/sources/xmi/extension_style_parser.rb +91 -0
  411. data/lib/ea/sources/xmi/note_builder.rb +46 -0
  412. data/lib/ea/sources/xmi/property_builder.rb +9 -0
  413. data/lib/ea/sources/xmi/stereotype_builder.rb +54 -0
  414. data/lib/ea/sources/xmi/tag_builder.rb +45 -0
  415. data/lib/ea/sources/xmi/umldi_keyword_extractor.rb +87 -0
  416. data/lib/ea/sources/xmi.rb +7 -0
  417. data/lib/ea/spa/output/sharded_multi_file_strategy.rb +18 -3
  418. data/lib/ea/spa/output/single_file_strategy.rb +8 -2
  419. data/lib/ea/spa/output/strategy.rb +34 -0
  420. data/lib/ea/svg/connector_router.rb +134 -0
  421. data/lib/ea/svg/ea_emitter/background.rb +15 -0
  422. data/lib/ea/svg/ea_emitter/bounds_calculator.rb +142 -0
  423. data/lib/ea/svg/ea_emitter/canvas.rb +88 -0
  424. data/lib/ea/svg/ea_emitter/color_resolver.rb +56 -0
  425. data/lib/ea/svg/ea_emitter/compartment/attributes.rb +28 -0
  426. data/lib/ea/svg/ea_emitter/compartment/constraints.rb +30 -0
  427. data/lib/ea/svg/ea_emitter/compartment/enum_literals.rb +86 -0
  428. data/lib/ea/svg/ea_emitter/compartment/header.rb +32 -0
  429. data/lib/ea/svg/ea_emitter/compartment/header_divider.rb +57 -0
  430. data/lib/ea/svg/ea_emitter/compartment/instance_slots.rb +96 -0
  431. data/lib/ea/svg/ea_emitter/compartment/instance_underline.rb +67 -0
  432. data/lib/ea/svg/ea_emitter/compartment/note_body.rb +52 -0
  433. data/lib/ea/svg/ea_emitter/compartment/note_text.rb +102 -0
  434. data/lib/ea/svg/ea_emitter/compartment/operations.rb +38 -0
  435. data/lib/ea/svg/ea_emitter/compartment/package_contents.rb +72 -0
  436. data/lib/ea/svg/ea_emitter/compartment/package_from_parent.rb +136 -0
  437. data/lib/ea/svg/ea_emitter/compartment/shape.rb +82 -0
  438. data/lib/ea/svg/ea_emitter/compartment/tagged_values.rb +30 -0
  439. data/lib/ea/svg/ea_emitter/compartment.rb +58 -0
  440. data/lib/ea/svg/ea_emitter/connectors.rb +84 -0
  441. data/lib/ea/svg/ea_emitter/diagram_frame.rb +143 -0
  442. data/lib/ea/svg/ea_emitter/document.rb +35 -0
  443. data/lib/ea/svg/ea_emitter/element/attribute_line_builder.rb +117 -0
  444. data/lib/ea/svg/ea_emitter/element/attribute_renderer.rb +119 -0
  445. data/lib/ea/svg/ea_emitter/element/bcol_decoder.rb +29 -0
  446. data/lib/ea/svg/ea_emitter/element/compartment_geometry.rb +113 -0
  447. data/lib/ea/svg/ea_emitter/element/constraint_renderer.rb +53 -0
  448. data/lib/ea/svg/ea_emitter/element/divider_renderer.rb +17 -0
  449. data/lib/ea/svg/ea_emitter/element/enumeration_literal_renderer.rb +34 -0
  450. data/lib/ea/svg/ea_emitter/element/filter.rb +44 -0
  451. data/lib/ea/svg/ea_emitter/element/hand_draw_shape_renderer.rb +77 -0
  452. data/lib/ea/svg/ea_emitter/element/header_line_pipeline.rb +43 -0
  453. data/lib/ea/svg/ea_emitter/element/header_line_provider/instance_spec.rb +27 -0
  454. data/lib/ea/svg/ea_emitter/element/header_line_provider/name.rb +76 -0
  455. data/lib/ea/svg/ea_emitter/element/header_line_provider/parent_ghost.rb +25 -0
  456. data/lib/ea/svg/ea_emitter/element/header_line_provider/stereotype_label.rb +68 -0
  457. data/lib/ea/svg/ea_emitter/element/header_line_provider.rb +19 -0
  458. data/lib/ea/svg/ea_emitter/element/header_lines.rb +27 -0
  459. data/lib/ea/svg/ea_emitter/element/header_renderer.rb +48 -0
  460. data/lib/ea/svg/ea_emitter/element/icon_renderer.rb +109 -0
  461. data/lib/ea/svg/ea_emitter/element/legend_renderer.rb +177 -0
  462. data/lib/ea/svg/ea_emitter/element/note_shape_renderer.rb +112 -0
  463. data/lib/ea/svg/ea_emitter/element/operation_renderer.rb +100 -0
  464. data/lib/ea/svg/ea_emitter/element/package_shape_renderer.rb +181 -0
  465. data/lib/ea/svg/ea_emitter/element/row_icon_renderer.rb +156 -0
  466. data/lib/ea/svg/ea_emitter/element/shape_renderer.rb +17 -0
  467. data/lib/ea/svg/ea_emitter/element/stereotype_icon_renderer.rb +82 -0
  468. data/lib/ea/svg/ea_emitter/element/tagged_value_renderer.rb +50 -0
  469. data/lib/ea/svg/ea_emitter/element/text_escape.rb +20 -0
  470. data/lib/ea/svg/ea_emitter/element.rb +37 -0
  471. data/lib/ea/svg/ea_emitter/elements.rb +357 -0
  472. data/lib/ea/svg/ea_emitter/font_resolver.rb +111 -0
  473. data/lib/ea/svg/ea_emitter/ghost_labels.rb +66 -0
  474. data/lib/ea/svg/ea_emitter/label/end_label.rb +266 -0
  475. data/lib/ea/svg/ea_emitter/label/midpoint_label.rb +101 -0
  476. data/lib/ea/svg/ea_emitter/label/registry.rb +50 -0
  477. data/lib/ea/svg/ea_emitter/label.rb +23 -0
  478. data/lib/ea/svg/ea_emitter/labels.rb +130 -0
  479. data/lib/ea/svg/ea_emitter/layer.rb +20 -0
  480. data/lib/ea/svg/ea_emitter/layer_sequencer.rb +93 -0
  481. data/lib/ea/svg/ea_emitter/marker/arrow_path.rb +52 -0
  482. data/lib/ea/svg/ea_emitter/marker/diamond.rb +57 -0
  483. data/lib/ea/svg/ea_emitter/marker/kind.rb +35 -0
  484. data/lib/ea/svg/ea_emitter/marker/open_triangle.rb +27 -0
  485. data/lib/ea/svg/ea_emitter/marker/package_import.rb +39 -0
  486. data/lib/ea/svg/ea_emitter/marker/plus.rb +40 -0
  487. data/lib/ea/svg/ea_emitter/marker/registry.rb +42 -0
  488. data/lib/ea/svg/ea_emitter/marker.rb +37 -0
  489. data/lib/ea/svg/ea_emitter/markers.rb +404 -0
  490. data/lib/ea/svg/ea_emitter/render_context.rb +52 -0
  491. data/lib/ea/svg/ea_emitter/style.rb +15 -0
  492. data/lib/ea/svg/ea_emitter/text_renderer.rb +92 -0
  493. data/lib/ea/svg/ea_emitter.rb +51 -0
  494. data/lib/ea/svg/parity/checker.rb +105 -0
  495. data/lib/ea/svg/parity/source.rb +59 -0
  496. data/lib/ea/svg/parity/suite.rb +113 -0
  497. data/lib/ea/svg/parity.rb +14 -0
  498. data/lib/ea/svg/stereotype_color_resolver.rb +50 -0
  499. data/lib/ea/svg.rb +4 -15
  500. data/lib/ea/theme/definition.rb +176 -0
  501. data/lib/ea/theme/loader.rb +125 -0
  502. data/lib/ea/theme/registry.rb +96 -0
  503. data/lib/ea/theme.rb +37 -0
  504. data/lib/ea/transformations.rb +5 -88
  505. data/lib/ea/version.rb +4 -1
  506. data/lib/ea.rb +14 -4
  507. data/lib/tasks/svg_bench.rake +87 -0
  508. data/lutaml-uml-0.5.1.gem +0 -0
  509. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes-list.png +0 -0
  510. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes.png +0 -0
  511. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-2-gradients.png +0 -0
  512. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-3-colors.png +0 -0
  513. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance-fonts.png +0 -0
  514. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance.png +0 -0
  515. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-5-behavior.png +0 -0
  516. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-6-sequence.png +0 -0
  517. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram.png +0 -0
  518. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-2-objects.png +0 -0
  519. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-3-links.png +0 -0
  520. metadata +473 -26
  521. data/lib/ea/diagram/configuration.rb +0 -379
  522. data/lib/ea/diagram/element_renderers/base_renderer.rb +0 -77
  523. data/lib/ea/diagram/element_renderers/class_renderer.rb +0 -323
  524. data/lib/ea/diagram/element_renderers/connector_renderer.rb +0 -41
  525. data/lib/ea/diagram/element_renderers/package_renderer.rb +0 -61
  526. data/lib/ea/diagram/element_renderers.rb +0 -43
  527. data/lib/ea/diagram/extractor.rb +0 -566
  528. data/lib/ea/diagram/layout_engine.rb +0 -170
  529. data/lib/ea/diagram/path_builder.rb +0 -202
  530. data/lib/ea/diagram/style_parser.rb +0 -42
  531. data/lib/ea/diagram/style_resolver.rb +0 -291
  532. data/lib/ea/diagram/svg_renderer.rb +0 -274
  533. data/lib/ea/diagram/util.rb +0 -73
  534. data/lib/ea/svg/bounds_calculator.rb +0 -74
  535. data/lib/ea/svg/connector_path.rb +0 -138
  536. data/lib/ea/svg/element_box.rb +0 -256
  537. data/lib/ea/svg/renderer.rb +0 -77
  538. data/lib/ea/svg/style_resolver.rb +0 -72
  539. data/lib/ea/transformations/configuration.rb +0 -333
  540. data/lib/ea/transformations/format_registry.rb +0 -366
  541. data/lib/ea/transformations/parsers/base_parser.rb +0 -482
  542. data/lib/ea/transformations/parsers/qea_parser.rb +0 -401
  543. data/lib/ea/transformations/parsers/xmi_parser.rb +0 -243
  544. data/lib/ea/transformations/transformation_engine.rb +0 -390
@@ -0,0 +1,69 @@
1
+ # TODO.diagrams — Remaining Work Status
2
+
3
+ ## Completed (recent sessions)
4
+
5
+ ### Architecture & Performance
6
+ - [18-property-lookup-index.md](18-property-lookup-index.md) — Document#property_index. 10x speedup.
7
+ - [19-replace-respond-to-with-is-a.md](19-replace-respond-to-with-is-a.md) — respond_to? → is_a?(Relationship).
8
+ - [20-split-labels-emitter.md](20-split-labels-emitter.md) — Labels split into EndLabel + MidpointLabel + Registry.
9
+ - [25-extract-compartment-geometry.md](25-extract-compartment-geometry.md) — Element::CompartmentGeometry extracted.
10
+ - [28-architecture-cleanup-batch.md](28-architecture-cleanup-batch.md) — Canvas promoted; OpenStruct removed; specs added.
11
+
12
+ ### Examples Coverage (basic.qea + test.qea focus)
13
+ - [32-examples-coverage-batch.md](32-examples-coverage-batch.md) — Cross-fixture spec; Package labels; Nesting filter; t_objectproperties tagged values.
14
+ - Signal classifier type with «signal» fallback stereotype.
15
+ - Midpoint name rendering (Association A/B names at midpoint).
16
+ - Operation parameter types only (op(int): void not op(name: int): void).
17
+ - Stereotype wins over association in Label::Registry#midpoint?
18
+ - "Object" InstanceSpecification mapping to Klass (basic.qea).
19
+ - Nested-class qualified names via ParentID (Class B::Class B.1).
20
+ - "object" diagram frame prefix fix.
21
+
22
+ ### Other
23
+ - [17-remaining-parity-gaps.md](17-remaining-parity-gaps.md) — High-level parity report.
24
+ - [23-marker-polygon-deduplication.md](23-marker-polygon-deduplication.md) — Documented dedup rules.
25
+
26
+ ## Deferred (blocked on external work)
27
+
28
+ - [21-auto-generated-legend-block.md](21-auto-generated-legend-block.md) — Need EA.exe RE.
29
+ - [22-ghost-element-discriminator.md](22-ghost-element-discriminator.md) — Need EA GUI testing.
30
+ - [24-marker-anchor-structural.md](24-marker-anchor-structural.md) — Refactor regresses within-tolerance.
31
+ - [26-phantom-general-parent-rendering.md](26-phantom-general-parent-rendering.md) — Needs synthetic bounds.
32
+ - [27-path-grouping-mode-detection.md](27-path-grouping-mode-detection.md) — No StyleEx toggle.
33
+ - [30-decompose-elements-groups_for] — Linear recipe; extraction broke specs twice.
34
+ - [36-instance-specification-model.md](36-instance-specification-model.md) — Full UML InstanceSpecification with classifier_ref + slots.
35
+ - [37-element-icon-decorations.md](37-element-icon-decorations.md) — Per-row icon shapes need EA.exe RE.
36
+ - [38-html-note-and-receptions.md](38-html-note-and-receptions.md) — HTML Note body + Receptions compartment.
37
+
38
+ ## Current Per-Example Parity Snapshot (2026-07-27)
39
+
40
+ | Example | Text overlap | Text delta |
41
+ |----------|--------------|-------------|
42
+ | plateau | 87.1% | -0.2% |
43
+ | simple | 100% | 0% |
44
+ | arcgis | ~55% | -1.9% |
45
+ | basic | ~70% | -7.8% |
46
+ | test | ~54% | -10.6% |
47
+
48
+ simple.qea is now at **100% text parity** (22/22 texts match).
49
+
50
+ ## Architecture
51
+
52
+ Code quality rules honored:
53
+
54
+ - `autoload` for all internal namespaces; no `require_relative`
55
+ outside `lib/ea.rb`'s version constant.
56
+ - No `send` / `instance_variable_set` / `instance_variable_get`
57
+ outside framework internals.
58
+ - No `respond_to?` (replaced with `is_a?` and polymorphic dispatch).
59
+ - No `OpenStruct` (replaced with model value objects).
60
+ - Registry pattern for OCP: Marker::Registry, Label::Registry.
61
+ - MECE: each label kind in its own class; CompartmentGeometry,
62
+ Canvas, Layer, Background, Signal as proper classes.
63
+ - DRY: Document#property_index, wrap_in_text_group, DiagramConnector#renderable?.
64
+ - Performance: QEA render time 3.25s → 0.34s (~10x).
65
+
66
+ ## Specs
67
+
68
+ 1685 examples, 0 failures, 52 pending. 35 new examples in
69
+ `spec/ea/svg/examples_regression_spec.rb` covering all 5 fixtures.
@@ -0,0 +1,73 @@
1
+ # Parity Status (updated 2026-08-02)
2
+
3
+ ## Headline numbers — examples (current)
4
+
5
+ | QEA | Matched (tol=5) | Matched (tol=0) | rect Δ | path Δ | polygon Δ | text Δ |
6
+ |---|---|---|---|---|---|---|
7
+ | **basic** | 22/22 | **22/22** | 0 | +6 | -6 | +2 |
8
+ | **plateau** | 188/188 | 167/188 | +4 | **0** | -4 | -40 |
9
+ | ArcGISWorkspace | 6/6 | — | 0 | 0 | 0 | +1 |
10
+ | simple | 2/2 | 2/2 | 0 | 0 | 0 | 0 |
11
+ | test | 2/2 | 2/2 | 0 | 0 | 0 | 0 |
12
+
13
+ Plateau at tighter tolerances:
14
+
15
+ | tol | matched | % |
16
+ |-----|---------|---|
17
+ | 5 | 188/188 | 100% |
18
+ | 2 | 185/188 | 98.4% |
19
+ | 1 | 179/188 | 95.2% |
20
+ | 0 | 167/188 | 88.8% |
21
+
22
+ ## Pixel-perfect parity status
23
+
24
+ - **basic.qea: 100% pixel-perfect** (22/22 at tolerance=0). The
25
+ aggregation arrow fix (commit 4b25abe) closed the last outlier.
26
+ - **plateau QEA: 88.8% pixel-perfect** (167/188 at tolerance=0),
27
+ 100% within standard tolerance=5.
28
+
29
+ ## Recent parity commits (2026-08-01)
30
+
31
+ | commit | summary | impact |
32
+ |---|---|---|
33
+ | ad7b058 | fix: suppress package subtitle when all placed packages share parent | +19 overshoot closed |
34
+ | 59dd4f7 | feat: render off-canvas parent classifier as italic header line | -98 → -36 (62 texts closed) |
35
+ | c54a391 | docs: TODO-D 71 + 72 | — |
36
+ | 4b25abe | fix: aggregation arrow only on reverse-direction | basic 21/22 → 22/22, plateau path +1 → 0 |
37
+ | abf2b72 | docs: TODOs 73-79 + is_a? fix + header_lines specs | — |
38
+ | f7d33cb | docs: TODO-D 80 — basic triangle polygon investigation | — |
39
+
40
+ ## MDG integration
41
+
42
+ - Loader, Registry, Adapter wiring all functional
43
+ - CityGML MDG (11 stereotypes) and ISO 19103 MDG (12 stereotypes)
44
+ both load successfully
45
+ - Properties added = 0 because available MDG files only define
46
+ stereotypes (no class hierarchies). A richer MDG file would
47
+ close the phantom-attribute gap. Documented in TODO-D 70.
48
+
49
+ ## Code-quality rules (all satisfied)
50
+
51
+ - autoload only — no `require_relative` in lib/
52
+ - No doubles in specs — real model instances
53
+ - No private `send`, `instance_variable_get/set`, `respond_to?`
54
+ - OCP-friendly marker dispatch via `Marker::Registry.register`
55
+ - OCP-friendly compartment pipeline (add module to ALL)
56
+ - MECE per-domain builders (Package, Classifier, Relationship, etc.)
57
+
58
+ ## Specs
59
+
60
+ - 1855 examples, 0 failures, 55 pending (3 new specs added)
61
+
62
+ ## Open parity TODOs (all priorities)
63
+
64
+ - 73: plateau polygon under-render (-4)
65
+ - 74: plateau rect over-render (+4)
66
+ - 75: plateau text under-render (-36, foreign-package rule too
67
+ aggressive for some diagrams)
68
+ - 76: basic polygon/path deltas (per-diagram within tol=5,
69
+ nonzero in aggregate)
70
+ - 77: basic text over-render (+2)
71
+ - 78: HeaderLines OCP refactor proposal (provider chain)
72
+ - 79: architecture backlog
73
+ - 80: basic triangle polygon markers (initial hypothesis disproven)
@@ -0,0 +1,34 @@
1
+ # 01 - Default Connectors to Style-Grouped Mode
2
+
3
+ ## Status: DONE (2026-07-24)
4
+
5
+ ## Outcome
6
+
7
+ Refactored emitters to use a `Layer` value object (style_key +
8
+ style + body). `Connectors` and `Markers` both return Arrays of
9
+ Layer structs. Document orchestrator renders each Layer as one
10
+ `<g>`.
11
+
12
+ Default mode is `grouped: true` for both Connectors and Markers —
13
+ all same-style paths/polygons collapse into ONE `<g>` matching
14
+ EA's encoding.
15
+
16
+ ## Outcome metrics (5 sample diagrams)
17
+
18
+ Group count diffs (ours vs ref):
19
+ - Bridge: +120 → -24 (97 vs 121)
20
+ - Building: +77 → -36 (93 vs 129)
21
+ - Waterway: +6 → -10 (37 vs 47)
22
+ - CityFurniture: was +6, now **exact match** (20 vs 20)
23
+
24
+ Slight overshoot on Bridge/Building because we collapse all
25
+ markers of one style into a single group, while EA keeps some
26
+ sub-bucketing. Acceptable for now.
27
+
28
+ ## Files changed
29
+
30
+ - `lib/ea/svg/ea_emitter/layer.rb` — NEW Layer value object
31
+ - `lib/ea/svg/ea_emitter.rb` — autoload Layer
32
+ - `lib/ea/svg/ea_emitter/connectors.rb` — Layer-based, `grouped:` flag
33
+ - `lib/ea/svg/ea_emitter/markers.rb` — Layer-based, style-bucketed
34
+ - `lib/ea/svg/ea_emitter/document.rb` — consumes Layer API
@@ -0,0 +1,20 @@
1
+ # 02 - Marker Consolidation Per Connector
2
+
3
+ ## Status: DONE (2026-07-24)
4
+
5
+ ## Outcome
6
+
7
+ Markers now use `:connector_line` style_key for arrow paths,
8
+ matching the line style. `Document#merge_layers_by_style` collapses
9
+ all Layers with the same style_key into one `<g>`, so:
10
+
11
+ - All line `<path>`s + arrow `<path>`s → ONE `<g>` (shared style:
12
+ stroke-width:2, no fill, black stroke)
13
+ - All diamond `<polygon>`s → ONE `<g>` (filled black)
14
+ - All open triangle `<polygon>`s → ONE `<g>` (white fill)
15
+
16
+ ## Files changed
17
+
18
+ - `lib/ea/svg/ea_emitter/markers.rb` — arrow uses `:connector_line` key,
19
+ STYLE_MAP references Connectors::LINE_STYLE
20
+ - `lib/ea/svg/ea_emitter/document.rb` — `merge_layers_by_style` collapses
@@ -0,0 +1,28 @@
1
+ # 03 - Diagram-Level Font Inference
2
+
3
+ ## Status: DONE (2026-07-24)
4
+
5
+ ## Outcome
6
+
7
+ Updated `FontResolver#diagram_default_family` and
8
+ `#diagram_default_size`:
9
+
10
+ - If ANY element specifies `font=`, use the most common (existing
11
+ behavior — picks up Yu Gothic UI diagrams).
12
+ - If NO element specifies font=, fall back to EA's English-locale
13
+ default: **Calibri 10px**.
14
+
15
+ This handles the 63 Calibri diagrams where no element carries font
16
+ info — EA's runtime default kicks in at render time.
17
+
18
+ ## Outcome metrics
19
+
20
+ Font family match rate: 62% → **71%** (133/185 diagrams).
21
+
22
+ Remaining 29% are diagrams where elements have a non-Calibri,
23
+ non-Yu-Gothic font explicitly (Meiryo UI, mixed-font diagrams).
24
+
25
+ ## Files changed
26
+
27
+ - `lib/ea/svg/ea_emitter/font_resolver.rb` — Calibri fallback
28
+ - `spec/ea/svg/ea_emitter/font_resolver_spec.rb` — covers fallback
@@ -0,0 +1,25 @@
1
+ # 04 - Extract BoundsCalculator (SRP)
2
+
3
+ ## Status: DONE (2026-07-24)
4
+
5
+ ## Outcome
6
+
7
+ `Ea::Svg::EaEmitter::BoundsCalculator` now owns canvas bound
8
+ computation. Three private methods each contribute points:
9
+
10
+ - `element_points`: logical bounds for x-extent, union of logical
11
+ + image_bounds for y-extent.
12
+ - `connector_points`: waypoint positions.
13
+ - `marker_points`: MARKER_EXTENT padding around each connector's
14
+ endpoints.
15
+
16
+ `Canvas.from` shrinks to 2 lines (delegate + construct). Canvas
17
+ remains a small value-object with translation and formatting.
18
+
19
+ ## Files changed
20
+
21
+ - `lib/ea/svg/ea_emitter/bounds_calculator.rb` — NEW extractor class
22
+ - `lib/ea/svg/ea_emitter.rb` — autoload registration
23
+ - `lib/ea/svg/ea_emitter/canvas.rb` — delegates to BoundsCalculator
24
+ - `spec/ea/svg/ea_emitter/bounds_calculator_spec.rb` — 4 specs covering
25
+ x-extent, y-extent, marker extent, empty diagram
@@ -0,0 +1,32 @@
1
+ # 05 - Marker Registry (OCP)
2
+
3
+ ## Status: DONE (2026-07-24)
4
+
5
+ ## Outcome
6
+
7
+ Refactored marker dispatch from case/when to a Registry of Kind
8
+ classes. `Marker::Registry.register(kind)` adds a new kind;
9
+ `Registry.specs_for(connector, effective_type, ...)` returns the
10
+ Spec list from the first kind that handles the type.
11
+
12
+ Built-in kinds (registered in priority order):
13
+ - `Marker::Diamond` — Aggregation, Composition (emits diamond +
14
+ arrow specs)
15
+ - `Marker::OpenTriangle` — Generalization, Realization, Dependency
16
+ - `Marker::ArrowPath` — Association navigability arrow
17
+
18
+ Adding a new kind = creating a Kind subclass + calling
19
+ `Marker::Registry.register(MyKind)`. No modification of existing
20
+ code (OCP).
21
+
22
+ ## Files changed
23
+
24
+ - `lib/ea/svg/ea_emitter/marker.rb` — module entry + registration
25
+ - `lib/ea/svg/ea_emitter/marker/kind.rb` — base Kind class
26
+ - `lib/ea/svg/ea_emitter/marker/registry.rb` — Registry + Spec
27
+ - `lib/ea/svg/ea_emitter/marker/diamond.rb` — Diamond kind
28
+ - `lib/ea/svg/ea_emitter/marker/open_triangle.rb` — OpenTriangle kind
29
+ - `lib/ea/svg/ea_emitter/marker/arrow_path.rb` — ArrowPath kind
30
+ - `lib/ea/svg/ea_emitter.rb` — autoload Marker
31
+ - `lib/ea/svg/ea_emitter/markers.rb` — delegates to Registry
32
+ - `spec/ea/svg/ea_emitter/marker/registry_spec.rb` — 6 specs incl OCP
@@ -0,0 +1,28 @@
1
+ # 06 - Connector Path= Bend Routing
2
+
3
+ ## Status: DONE (2026-07-24)
4
+
5
+ ## Outcome
6
+
7
+ `ConnectorRouter` now accepts an optional `bend_path:` Array of
8
+ [x, y] pairs. When non-empty, the router emits
9
+ `[source_point, *bend_path, target_point]` instead of computing
10
+ its own L-shaped bend.
11
+
12
+ `ExtensionGeometryParser#parse_bend_path` extracts EA's `Path=`
13
+ field format `x1:y1$x2:y2$...` into Ruby pairs.
14
+
15
+ `DiagramBuilder#compute_waypoints` plumbs `geom.bend_points`
16
+ through to the router.
17
+
18
+ ## Outcome metrics
19
+
20
+ Polygon count within ±1: 68% → 69% (small improvement from
21
+ proper bend routing reducing the marker rendering mismatches).
22
+
23
+ ## Files changed
24
+
25
+ - `lib/ea/svg/connector_router.rb` — `bend_path:` parameter
26
+ - `lib/ea/sources/xmi/extension_geometry_parser.rb` —
27
+ `parse_bend_path` + `bend_points` Placement field
28
+ - `lib/ea/sources/xmi/diagram_builder.rb` — passes bend_points to router
@@ -0,0 +1,22 @@
1
+ # 07 - Reverse-Engineer EA's Edge Attachment Formula
2
+
3
+ ## Status: DONE (2026-07-24)
4
+
5
+ ## Outcome
6
+
7
+ Added `EDGE_TOP_OFFSET = 9` to `ConnectorRouter`. Top-edge
8
+ attachment (EDGE=1) now positions the connector at
9
+ `(center_x, bounds.y + 9)` instead of `(center_x, bounds.y)`.
10
+
11
+ This matches EA's behavior of starting the connector just below
12
+ the header text rather than at the absolute top edge.
13
+
14
+ ## Outcome metrics
15
+
16
+ Mean abs path diff stays at 4 (no regression). The offset only
17
+ affects top-edge connectors; those that use bottom/left/right
18
+ edges are unchanged.
19
+
20
+ ## Files changed
21
+
22
+ - `lib/ea/svg/connector_router.rb` — `EDGE_TOP_OFFSET` constant
@@ -0,0 +1,28 @@
1
+ # 08 - Visual Diff Regression Harness
2
+
3
+ ## Status: DONE (2026-07-24)
4
+
5
+ ## Outcome
6
+
7
+ New `Ea::Svg::ParityChecker` compares two SVG strings across seven
8
+ parity metrics: rect, path, polygon, text, group counts + font
9
+ family + view_box match.
10
+
11
+ Returns a `Report` Struct of `Diff` Structs. Specs can assert on
12
+ individual dimensions or use `report.any_within?(tolerance)` for
13
+ aggregate checks.
14
+
15
+ ## Usage
16
+
17
+ ```ruby
18
+ checker = Ea::Svg::ParityChecker.new(ours: our_svg, reference: ref_svg)
19
+ report = checker.report
20
+ expect(report.text.within?(5)).to be(true)
21
+ expect(report.font_family).to be(true)
22
+ ```
23
+
24
+ ## Files changed
25
+
26
+ - `lib/ea/svg/parity_checker.rb` — NEW checker with Report/Diff
27
+ - `lib/ea/svg.rb` — autoload registration
28
+ - `spec/ea/svg/parity_checker_spec.rb` — 8 specs
@@ -0,0 +1,34 @@
1
+ # 09 - Extract ElementRenderer Compartments
2
+
3
+ ## Status: DONE (2026-07-24)
4
+
5
+ ## Outcome
6
+
7
+ Split `Elements` into focused collaborators under
8
+ `Ea::Svg::EaEmitter::Element::`:
9
+
10
+ - `Filter` — frame-element skip predicate
11
+ - `BColDecoder` — BGR int → #RRGGBB hex
12
+ - `ShapeRenderer` — element box `<g>` with rect
13
+ - `HeaderRenderer` — stereotype + name text `<g>`
14
+ - `HeaderLines` — line computation (abstract + stereotype logic)
15
+ - `TextEscape` — XML escape helper
16
+ - `DividerRenderer` — compartment divider path `<g>`
17
+ - `AttributeRenderer` — attribute text `<g>` with visibility split
18
+
19
+ `Elements` body shrinks to delegation. `CompartmentGeometry` struct
20
+ holds the y-coordinate math for header/divider/attr layout.
21
+
22
+ ## Files changed
23
+
24
+ - `lib/ea/svg/ea_emitter/element.rb` — module entry with autoloads
25
+ - `lib/ea/svg/ea_emitter/element/filter.rb`
26
+ - `lib/ea/svg/ea_emitter/element/bcol_decoder.rb`
27
+ - `lib/ea/svg/ea_emitter/element/shape_renderer.rb`
28
+ - `lib/ea/svg/ea_emitter/element/header_renderer.rb`
29
+ - `lib/ea/svg/ea_emitter/element/header_lines.rb`
30
+ - `lib/ea/svg/ea_emitter/element/text_escape.rb`
31
+ - `lib/ea/svg/ea_emitter/element/divider_renderer.rb`
32
+ - `lib/ea/svg/ea_emitter/element/attribute_renderer.rb`
33
+ - `lib/ea/svg/ea_emitter/elements.rb` — orchestrator only
34
+ - `lib/ea/svg/ea_emitter.rb` — autoload Element
@@ -0,0 +1,20 @@
1
+ # 10 - Canvas Width Overshoot Fix
2
+
3
+ ## Status: DONE (2026-07-24)
4
+
5
+ ## Outcome
6
+
7
+ `Canvas.from` now uses **logical bounds for x-extent** (matching
8
+ EA's canvas left/right exactly) while still unioning **logical +
9
+ image_bounds for y-extent** (image_bounds extends below bounds
10
+ for shadow/padding).
11
+
12
+ Waterway width: 1163 → **1138** (matches ref exactly).
13
+ Waterway height: 899 (ref=892, within 7).
14
+ Building width: 1381 (ref=1406, within 25).
15
+ Bridge width: 1292 (ref=1305, within 13).
16
+
17
+ ## Files changed
18
+
19
+ - `lib/ea/svg/ea_emitter/canvas.rb` — split x/y source rules
20
+ - `spec/ea/svg/ea_emitter/canvas_spec.rb` — unchanged, still passes
@@ -0,0 +1,18 @@
1
+ # 11 - Layer Sequencer Extraction
2
+
3
+ ## Status: DONE (2026-07-24)
4
+
5
+ ## Outcome
6
+
7
+ `Ea::Svg::EaEmitter::LayerSequencer` takes ownership of layer
8
+ ordering. Document shrinks to SVG envelope construction (~15 lines).
9
+
10
+ LayerSequencer exposes `layers` returning Array<String>; internally
11
+ composes Elements + Connectors + Markers + Labels, and merges
12
+ same-style Layer structs.
13
+
14
+ ## Files changed
15
+
16
+ - `lib/ea/svg/ea_emitter/layer_sequencer.rb` — NEW sequencer
17
+ - `lib/ea/svg/ea_emitter.rb` — autoload registration
18
+ - `lib/ea/svg/ea_emitter/document.rb` — delegates to LayerSequencer
@@ -0,0 +1,23 @@
1
+ # 12 - Connector Path Style Harmony
2
+
3
+ ## Status: DONE (2026-07-24)
4
+
5
+ ## Outcome
6
+
7
+ New `Ea::Svg::EaEmitter::Style` module centralizes style strings:
8
+ - `BACKGROUND` — white fill, no stroke
9
+ - `CONNECTOR_LINE` — used for line paths AND arrow paths
10
+ - `DIAMOND_FILLED` — aggregation/composition diamond polygons
11
+ - `TRIANGLE_OPEN` — generalization/realization triangles
12
+ - `TEXT_GROUP` — text wrapper `<g>`
13
+ - `ELEMENT_SHAPE_*` — shape stroke constants
14
+
15
+ `Connectors::LINE_STYLE` and `Markers::STYLE_MAP` reference Style
16
+ constants — single source of truth (DRY).
17
+
18
+ ## Files changed
19
+
20
+ - `lib/ea/svg/ea_emitter/style.rb` — NEW constants module
21
+ - `lib/ea/svg/ea_emitter.rb` — autoload registration
22
+ - `lib/ea/svg/ea_emitter/connectors.rb` — references Style::CONNECTOR_LINE
23
+ - `lib/ea/svg/ea_emitter/markers.rb` — STYLE_MAP references Style
@@ -0,0 +1,28 @@
1
+ # 13 - DataType Stereotype Fallback for Klass
2
+
3
+ ## Status: DONE (2026-07-25)
4
+
5
+ ## Outcome
6
+
7
+ `Element::HeaderLines#for` now always emits a stereotype label as
8
+ the first header line. When the classifier has no explicit
9
+ stereotype_refs, falls back to a type-derived label:
10
+
11
+ - `Ea::Model::Klass` → `«DataType»`
12
+ - `Ea::Model::Enumeration` → `«enumeration»`
13
+ - `Ea::Model::DataType` → `«DataType»`
14
+ - `Ea::Model::PrimitiveType` → `«primitive»`
15
+ - `Ea::Model::Interface` → `«interface»`
16
+
17
+ For abstract Klasses the abstract name (`_Name`) is still italic;
18
+ for concrete Klasses the name is bold.
19
+
20
+ ## Outcome metrics
21
+
22
+ Mean text abs diff across 185 diagrams: **14 → 7** (50% reduction).
23
+ CityFurniture text count: 30 → **34** (exact match).
24
+ Waterway text count: 103 → **111** (ref=113, within 2).
25
+
26
+ ## Files changed
27
+
28
+ - `lib/ea/svg/ea_emitter/element/header_lines.rb` — fallback rule
@@ -0,0 +1,56 @@
1
+ # 14 - EA.exe Reverse-Engineering Notes
2
+
3
+ ## Status: DONE (informational)
4
+
5
+ ## Location
6
+
7
+ EA.exe and supporting DLLs are installed at:
8
+
9
+ ~/Library/Application Support/CrossOver/Bottles/Enterprise Architect 16.x/drive_c/Program Files/Sparx Systems/EA/
10
+
11
+ Key files:
12
+ - `EA.exe` — main PE32 Windows binary, ~? MB
13
+ - `DrawEx161-32.dll` — drawing extension (CDrawEx class with
14
+ Bezier/FillPath/StrokePath/etc.)
15
+ - `SSXML161-32.dll` — XML processing
16
+ - `EALayout161-32.dll` — layout engine
17
+ - `Cairo161-32.dll` — Cairo graphics bindings
18
+ - `Scintilla161-32.dll` — code editor
19
+
20
+ ## What's discoverable
21
+
22
+ Symbols found in EA.exe (via `strings`):
23
+
24
+ - `SVGRenderer.cpp` — the C++ source file implementing SVG output
25
+ - `CBCGPSVG*` — BCGSoft SVG library classes (Base, Rect, Ellipse,
26
+ Line, Text, Polygon, Path, Group, ClipPath, Gradient, Mask,
27
+ ViewBox, Symbol, Marker)
28
+
29
+ The BCGSoft library is a commercial MFC extension. EA's SVG output
30
+ is built on top of `CBCGPSVG` and `CDrawEx` (a custom drawing
31
+ abstraction with both GDI and SVG backends).
32
+
33
+ ## What's NOT discoverable without disassembly
34
+
35
+ - Exact style string assembly logic
36
+ - Coordinate transformation math
37
+ - Style bucketing rules (which paths share a `<g>`)
38
+ - Marker shape selection per relationship kind
39
+
40
+ These are constructed dynamically from many small format strings
41
+ at runtime. EA's diagram SVG output uses `printf`-style formatting
42
+ with the format templates assembled by C++ code from many
43
+ fragments — not stored as literal strings in the binary.
44
+
45
+ ## Implication for parity work
46
+
47
+ Without source code or disassembly tools (Ghidra, IDA Pro), the
48
+ only practical path to closing remaining parity gaps is:
49
+
50
+ 1. Empirically derive rules from reference SVGs (current approach)
51
+ 2. Test against many diagrams to find consistent patterns
52
+ 3. Accept residual ~5-10% diff as uncloseable without binary RE
53
+
54
+ The `Ea::Svg::ParityChecker` (fixup 08) is the right tool for
55
+ empirical validation — it surfaces exactly which dimensions
56
+ diverge so we can target them.
@@ -0,0 +1,30 @@
1
+ # 15 - Enumeration Literal Rendering
2
+
3
+ ## Status: DONE (2026-07-25)
4
+
5
+ ## Outcome
6
+
7
+ New `Element::EnumerationLiteralRenderer` emits a literal
8
+ compartment below the attribute compartment for Enumeration
9
+ classifiers. Layout:
10
+
11
+ ```
12
+ ┌────────────────────┐
13
+ │ «enumeration» │ header
14
+ │ EnumName │
15
+ ├────────────────────┤
16
+ │ + attr: Type │ attributes (if any)
17
+ ├────────────────────┤
18
+ │ literal1 │ literal compartment
19
+ │ literal2 │
20
+ └────────────────────┘
21
+ ```
22
+
23
+ `CompartmentGeometry` extended with `attr_lines_count`,
24
+ `enum_divider_y`, `enum_literal_first_y`.
25
+
26
+ ## Files changed
27
+
28
+ - `lib/ea/svg/ea_emitter/element/enumeration_literal_renderer.rb` — NEW
29
+ - `lib/ea/svg/ea_emitter/element.rb` — autoload
30
+ - `lib/ea/svg/ea_emitter/elements.rb` — invoke renderer, extend geometry
@@ -0,0 +1,42 @@
1
+ # 16 - Operation Compartment Rendering
2
+
3
+ ## Status: DONE (2026-07-25)
4
+
5
+ ## Outcome
6
+
7
+ New `Element::OperationRenderer` emits operations as a third
8
+ compartment below attributes (when classifier has operations).
9
+ Layout:
10
+
11
+ ```
12
+ ┌────────────────────┐
13
+ │ «DataType» │ header
14
+ │ ClassName │
15
+ ├────────────────────┤
16
+ │ + attr: Type │ attributes
17
+ ├────────────────────┤
18
+ │ + method1() │ operations
19
+ │ + method2(): Type │
20
+ ├────────────────────┤
21
+ │ literal1 │ enum literals (if Enumeration)
22
+ └────────────────────┘
23
+ ```
24
+
25
+ Each operation emits as TWO `<text>` elements (visibility + content)
26
+ matching EA's attribute encoding. Operation signature format:
27
+ `+ name(params): ReturnType`.
28
+
29
+ `CompartmentGeometry` extended with `op_divider_y`, `op_first_y`,
30
+ `op_bottom_y` and adjusted `enum_divider_y` to follow op compartment.
31
+
32
+ ## Note
33
+
34
+ In the current plateau XMI dataset, no classifiers have operations
35
+ (0/599). The renderer is implemented for completeness — future
36
+ XMI imports with operation data will render correctly.
37
+
38
+ ## Files changed
39
+
40
+ - `lib/ea/svg/ea_emitter/element/operation_renderer.rb` — NEW
41
+ - `lib/ea/svg/ea_emitter/element.rb` — autoload
42
+ - `lib/ea/svg/ea_emitter/elements.rb` — invoke renderer, extend geometry
@@ -0,0 +1,27 @@
1
+ # 17 - Path Count Calibration
2
+
3
+ ## Status: DONE (2026-07-25)
4
+
5
+ ## Outcome
6
+
7
+ Removed navigability arrow emission from aggregations. EA's
8
+ diagrams do NOT render an arrow at the part end of aggregations
9
+ — the diamond already conveys direction.
10
+
11
+ Updated `Marker::Diamond` to emit only ONE spec (the diamond),
12
+ not two (diamond + arrow). Updated spec accordingly.
13
+
14
+ ## Outcome metrics
15
+
16
+ Path count within ±2: 49% → 49% (no aggregate change since path
17
+ diffs come from other sources too).
18
+
19
+ Bridge: 140 → 127 paths (ref=113, was +27, now +14).
20
+ Building: 112 → 102 (ref=96, was +16, now +6).
21
+
22
+ Significant reduction on individual diagrams.
23
+
24
+ ## Files changed
25
+
26
+ - `lib/ea/svg/ea_emitter/marker/diamond.rb` — single spec only
27
+ - `spec/ea/svg/ea_emitter/marker/registry_spec.rb` — updated expectation