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,54 @@
1
+ # TODO-D 43: Marker deduplication strategy
2
+
3
+ ## Current behavior
4
+
5
+ `lib/ea/svg/ea_emitter/markers.rb` deduplicates marker polygons/paths
6
+ by their anchor point (first coord pair, rounded to integer).
7
+
8
+ ```
9
+ unique_bodies = grouped_entries.uniq { |e| anchor_key(e.body) }
10
+ ```
11
+
12
+ ## Reference behavior (verified from plateau)
13
+
14
+ EA's reference set is INCONSISTENT:
15
+
16
+ - `EAID_E7AABA98` (Building): 9 parallel generalizations to one
17
+ parent — EA emits 9 polygons at the same anchor (collapses NOT
18
+ applied).
19
+ - `EAID_9994BF62` (地域地区および用途地域): 29 generalizations, EA
20
+ emits only 3 triangles. Many generalizations share the same
21
+ parent — EA emits ONE marker per parent point, not per connector.
22
+
23
+ So:
24
+ - Same parent, single shape per connector endpoint: 1 marker (collapsed)
25
+ - Same parent, parallel (multiple distinct routes): 1 marker per route
26
+
27
+ ## Discriminator hypothesis
28
+
29
+ The discriminator is likely the connector's `Mode` style flag:
30
+
31
+ - `Mode=1` — Custom routing (each connector has its own route →
32
+ emit per connector)
33
+ - `Mode=3` — Tree routing (children share route to parent →
34
+ emit ONE marker per parent point)
35
+
36
+ ## Acceptance
37
+
38
+ - Identify the exact field that distinguishes "tree" from "custom"
39
+ routing.
40
+ - Implement per-mode marker strategy:
41
+ - Tree mode: emit one marker per (parent, edge) tuple.
42
+ - Custom mode: emit one marker per connector.
43
+ - Bench polygon delta → 0.
44
+ - Spec coverage for both modes.
45
+
46
+ ## Bench impact (current)
47
+
48
+ ```
49
+ polygon ours=955 ref=961 delta=-6 (-0.6%)
50
+ ```
51
+
52
+ If the discriminator is wrong we either over-render (Mode=3 case
53
+ with parallel connectors) or under-render (Mode=1 case with shared
54
+ parent).
@@ -0,0 +1,34 @@
1
+ # TODO-D 44: Element icon decorations (folded-paper class icon)
2
+
3
+ ## Symptom
4
+
5
+ EA renders a small "folded paper" icon at the top-right corner of
6
+ each class shape. The icon is two `<path>` elements:
7
+
8
+ 1. Outer outline: `M x y L x+6 y L x+9 y+4 L x+9 y+11 L x y+11 Z`
9
+ 2. Folded corner: `M x+6 y L x+6 y+4 L x+9 y+4`
10
+
11
+ Style:
12
+ - `stroke-width:1; stroke-linecap:square; stroke-linejoin:bevel;`
13
+ - Outer: `fill:#DCF8F0; stroke:#577AC1` (light cyan fill, blue stroke)
14
+ - Inner corner: `fill:transparent; stroke:#577AC1`
15
+
16
+ ## Discriminator
17
+
18
+ The XMI element style carries `HideIcon=0` (show) or `HideIcon=1`
19
+ (hide). When shown, EA emits the icon paths regardless of element
20
+ type (class, data type, etc.).
21
+
22
+ ## Bench impact (estimated)
23
+
24
+ - 2 paths per shown icon × ~140 elements with `HideIcon=0` ≈ 280
25
+ paths. This matches the current path delta of `-280`.
26
+
27
+ ## Acceptance
28
+
29
+ - Add an `Element::IconRenderer` that emits the two `<path>`
30
+ elements at (bounds.right - 12, bounds.top + 3) when
31
+ `element.style["HideIcon"] == "0"` (default visible).
32
+ - Thread HideIcon parsing through `ExtensionStyleParser`.
33
+ - Spec coverage for both shown and hidden cases.
34
+ - Bench path delta → 0.
@@ -0,0 +1,40 @@
1
+ # TODO-D 45: Phantom parent class boxes (generalization tree)
2
+
3
+ ## Symptom
4
+
5
+ Some diagrams render extra `<rect>`+`<text>` for a classifier that
6
+ is NOT placed on the diagram via `t_diagramobjects` (or XMI
7
+ `<elements>` block), but IS referenced as a generalization parent
8
+ by a connector on the diagram.
9
+
10
+ Reference SVG for `EAID_5A43833E_680B_4a90_8931_0C902304E029` has:
11
+
12
+ ```
13
+ <rect x="161" y="161" width="179" height="80" .../>
14
+ <text>_AbstractGeometricAggregate</text>
15
+ ```
16
+
17
+ The classifier `_AbstractGeometricAggregate` is the general parent
18
+ of one of the placed children, but is NOT placed itself. EA renders
19
+ a phantom box at the parent end of the generalization connector.
20
+
21
+ ## Discriminator (hypothesis)
22
+
23
+ When a connector's `EOID` references a `DUID` that is NOT in the
24
+ placed-elements index, EA renders a minimal phantom box at the
25
+ connector's endpoint coordinate. The phantom box shows the parent
26
+ classifier's name and stereotype but no attributes/operations.
27
+
28
+ ## Acceptance
29
+
30
+ - Detect connectors whose endpoint DUID has no matching placed
31
+ element.
32
+ - Render a phantom box at the connector's endpoint with the
33
+ referenced classifier's header.
34
+ - Bench rect delta improves by N where N is the count of phantom
35
+ parents across the plateau reference set.
36
+
37
+ ## Related
38
+
39
+ - TODO-D 26 (phantom class headers from connector endpoints) —
40
+ same root cause, separate TODO for tracking.
@@ -0,0 +1,44 @@
1
+ # TODO-D 46: User-drawn legend swatches (colored marker rects)
2
+
3
+ ## Symptom
4
+
5
+ Some diagrams include manually-drawn legend boxes — small colored
6
+ `<rect>` elements (typically 17×17) accompanied by text labels,
7
+ grouped inside a larger "legend" container rect.
8
+
9
+ Reference SVG for `EAID_5A43833E_680B_4a90_8931_0C902304E029` has:
10
+
11
+ ```
12
+ <rect x="647" y="751" width="17" height="17" fill="#CCFFCC" .../>
13
+ <text>GMLに定義されたクラス</text>
14
+ <rect x="647" y="770" width="17" height="17" fill="#FFFFCC" .../>
15
+ <text>CityGMLに定義されたクラス</text>
16
+ <rect x="647" y="789" width="17" height="17" fill="#FFCCFF" .../>
17
+ ```
18
+
19
+ These are NOT modeled classifiers — they're user-drawn shapes
20
+ inside a "diagram note" or "text" element.
21
+
22
+ ## Source
23
+
24
+ EA encodes these as nested `<element>` rows inside a parent
25
+ `<element>` in the extension block, OR as separate `<element>`
26
+ rows whose `subject` references a "Note" or "Text" classifier with
27
+ custom geometry/style.
28
+
29
+ In the plateau XMI, these specific swatches appear to be embedded
30
+ in a Klass with `name=nil` that serves as the legend frame. The
31
+ swatches themselves are not present as separate element rows.
32
+
33
+ ## Acceptance
34
+
35
+ - Investigate whether the XMI carries these as nested elements,
36
+ tagged values, or Note element children.
37
+ - If unrecoverable from XMI, document as "out of scope — user
38
+ decoration not encoded in the model" and exclude from parity
39
+ measurement.
40
+
41
+ ## Bench impact
42
+
43
+ About 50-100 rects across the plateau set. Cannot be fully closed
44
+ without explicit source data.
@@ -0,0 +1,72 @@
1
+ # TODO-D 47: Attribute line fidelity (qualified prefix + multiplicity shorthand + primitive type strip)
2
+
3
+ ## Symptom (largest single source of text delta)
4
+
5
+ Aggregated text diff against 185 plateau diagrams:
6
+
7
+ ```
8
+ Ref has but we don't: We have but ref doesn't:
9
+ qualified_name: 539 qualified_name: 1016
10
+ other: 1501 other: 462
11
+ ```
12
+
13
+ Most "qualified_name" cases are attribute lines on inherited
14
+ properties. Reference renders:
15
+
16
+ ```
17
+ core::mimeType: gml::CodeType [0..1]
18
+ core::elements: double [16] {ordered}
19
+ ```
20
+
21
+ We render:
22
+
23
+ ```
24
+ mimeType: gml::CodeType [0..1]
25
+ elements: xs::double [16..16]
26
+ ```
27
+
28
+ ## Three distinct bugs
29
+
30
+ ### A. Missing namespace prefix on inherited properties
31
+
32
+ When a class displays a property inherited from a parent in a
33
+ different package, EA prepends the parent's package name to the
34
+ property name (`core::mimeType`). For own properties, no prefix.
35
+
36
+ Discriminator: the property's `owner_id` (the classifier that
37
+ declares it) — if that classifier's `package_id` differs from the
38
+ displayed classifier's `package_id`, render the prefix.
39
+
40
+ ### B. Multiplicity shorthand `[N]` not `[N..N]`
41
+
42
+ When `multiplicity_lower == multiplicity_upper`, EA renders `[N]`
43
+ (single value), not `[N..N]`. We always render the range.
44
+
45
+ ### C. Primitive type strip
46
+
47
+ When the type is a primitive (xs:string, xs:double, xs:integer,
48
+ xs:date, xs:gYear, xs:boolean, xs:anyURI, etc.), EA strips the
49
+ namespace prefix and renders just `string`, `double`, etc.
50
+
51
+ Verified against ref: `double` not `xs::double`, `string` not
52
+ `xs::string`. The exception is when the property's type is an
53
+ in-model Classifier (not a primitive) — then qualified form is
54
+ kept (`gml::CodeType`, `core::TransformationMatrix4x4`).
55
+
56
+ ### D. `{ordered}` modifier on ordered properties
57
+
58
+ When `is_ordered == true` and multiplicity is non-singleton,
59
+ EA appends ` {ordered}` after the multiplicity.
60
+
61
+ ## Acceptance
62
+
63
+ - All four rules implemented in `AttributeRenderer.line_for`.
64
+ - Property model exposes the source classifier (for prefix logic).
65
+ - Spec coverage for each rule (own/inherited, primitive/typed,
66
+ lower==upper, ordered/unordered).
67
+ - Bench text overlap → ~90% (from 64.5%).
68
+
69
+ ## Bench impact estimate
70
+
71
+ Closes ~600 text deltas (the qualified_name category) plus ~1000
72
+ "other" deltas that are attribute lines with wrong format.
@@ -0,0 +1,45 @@
1
+ # TODO-D 48: Spec coverage for critical svg/ea_emitter components
2
+
3
+ ## Goal
4
+
5
+ Most `lib/ea/svg/ea_emitter/element/*` and `lib/ea/svg/ea_emitter/*.rb`
6
+ files had zero dedicated specs — they were only exercised through
7
+ the high-level regression suites. A regression in BColDecoder,
8
+ HeaderLines, Filter, or TextEscape could ship undetected if it
9
+ didn't trigger a regression-suite threshold.
10
+
11
+ ## Coverage added
12
+
13
+ - `spec/ea/svg/ea_emitter/element/bcol_decoder_spec.rb` — BGR
14
+ decoding, sentinel handling, color hex format.
15
+ - `spec/ea/svg/ea_emitter/element/filter_spec.rb` — skip?
16
+ predicate under all permutations of (background_color, name,
17
+ properties, model_index presence).
18
+ - `spec/ea/svg/ea_emitter/element/header_lines_spec.rb` —
19
+ stereotype fallback rules, abstract italic-bold, UMLDI keyword
20
+ override, package-qualified display name, Note special-case.
21
+ - `spec/ea/svg/ea_emitter/element/divider_renderer_spec.rb` —
22
+ horizontal path geometry, group style attributes.
23
+ - `spec/ea/svg/ea_emitter/element/shape_renderer_spec.rb` — rect
24
+ attributes, fill/stroke group style, shape-rendering.
25
+ - `spec/ea/svg/ea_emitter/element/text_escape_spec.rb` — XML
26
+ special-char escaping, UTF-8 preservation, stereotype/namespace
27
+ marker preservation.
28
+
29
+ ## Bug found and fixed during spec writing
30
+
31
+ `HeaderLines.explicit_stereotype` called `classifier.stereotype_refs`
32
+ without guarding for Note (which extends Base, not Classifier).
33
+ Same issue in `display_name` (qualified_name missing on Note).
34
+
35
+ Added `is_a?(Ea::Model::Classifier)` guards so Note and other
36
+ non-Classifier model elements degrade gracefully instead of
37
+ raising NoMethodError. Without the new spec coverage this bug
38
+ would only surface when a user rendered a diagram containing a
39
+ Note element with a stereotype keyword.
40
+
41
+ ## Verification
42
+
43
+ - 1746 examples pass (up from 1694).
44
+ - New specs cover both the happy path and edge cases.
45
+ - Bench plateau XMI unchanged.
@@ -0,0 +1,25 @@
1
+ # TODO-D 49: More spec coverage for orchestrators + labels cleanup
2
+
3
+ ## Goal
4
+
5
+ Add dedicated specs for the high-level orchestrators that were
6
+ previously only exercised through end-to-end regression tests.
7
+
8
+ ## Coverage added
9
+
10
+ - `spec/ea/svg/ea_emitter/element/operation_renderer_spec.rb` —
11
+ Operation signature rendering, parameter joining, line-height
12
+ stacking, visibility marker offsets.
13
+ - `spec/ea/svg/ea_emitter/layer_sequencer_spec.rb` — Background
14
+ layer presence, labels layer inclusion, frame toggle, theme
15
+ propagation, connector path integration.
16
+
17
+ ## Dead code removed
18
+
19
+ `Labels#midpoint_text_for` was an unused private method (the
20
+ actual midpoint text emission goes through `texts_for`). Deleted.
21
+
22
+ ## Verification
23
+
24
+ - 1759 examples pass (up from 1746, +13 new).
25
+ - Bench plateau XMI unchanged.
@@ -0,0 +1,85 @@
1
+ # TODO-D 50: Examples (basic, simple, test, etc.) parity
2
+
3
+ ## Goal
4
+
5
+ Get every example QEA in `examples/qea/` matching its reference
6
+ SVGs in `examples/exports/<name>/images/`.
7
+
8
+ ## Current bench (`rake svg:examples`)
9
+
10
+ | Example | Matched | rect | path | polygon | text |
11
+ |---------|---------|------|------|---------|------|
12
+ | simple | 2/2 | 0 | 0 | 0 | 0 |
13
+ | ArcGISWorkspace_template | 5/6 | -2 | -7 | 0 | -1 |
14
+ | basic | 19/22 | -3 | -30 | -6 | -22 |
15
+ | test | 1/2 | -15 | -58 | 0 | -11 |
16
+
17
+ **simple.qea is at 100%!** Zero deltas across the board.
18
+
19
+ ## Architecture addition
20
+
21
+ `rake svg:examples` benches every QEA in `examples/qea/` against
22
+ its matching `examples/exports/<name>/{images,Images}/` directory.
23
+ Run after every renderer change to catch regressions in any
24
+ example.
25
+
26
+ ## Remaining per-example deltas
27
+
28
+ ### test.qea — Test Model diagram (-15 rect, -58 path, -11 text)
29
+
30
+ 1 element (Package "Test Schema") + 0 connectors. Reference has
31
+ 16 small visibility-marker rects at x=40 (one per attribute row)
32
+ + 8 horizontal divider paths inside the markers. Each attribute
33
+ row in this diagram shows:
34
+ - 11x14 outer rect (pale yellow, blue stroke)
35
+ - 11x4 inner rect (white)
36
+ - 1 horizontal divider path
37
+
38
+ That's 3 elements per attribute row × 8 rows = 24 missing
39
+ elements. Plus the Package tab icon path. Total ~25 missing.
40
+
41
+ ### basic.qea — visibility icons + object instance format
42
+
43
+ Top outliers:
44
+ - Package Imports (-6 rect, -18 path): visibility icons +
45
+ package-tab icons.
46
+ - Object with Value Specifications (-6 path, -19 text): Object
47
+ instance rendering. EA shows "Object 01 / roleOne: Class A" and
48
+ "attribute = value" slot format. We render the qualified class
49
+ name only.
50
+ - Objects as Instances of Classes (-4 path, -9 text): same Object
51
+ instance format issue.
52
+
53
+ ## Discriminator for visibility icons
54
+
55
+ Visibility icons appear in:
56
+ - Test Model (test.qea) — Package element with attribute rows
57
+ - Package Imports (basic.qea) — visibility column next to attrs
58
+
59
+ They do NOT appear in:
60
+ - simple.qea — no attribute compartments shown
61
+ - Most basic.qea class diagrams — already have +/- text markers
62
+
63
+ The discriminator is likely:
64
+ - Diagram style1 flag (HideProps=0 + VisibleAttributeDetail=1)
65
+ - OR element-level ShowIcon-style flag
66
+
67
+ ## Acceptance
68
+
69
+ - Implement VisibilityIconRenderer (per-attribute 3-element
70
+ decoration).
71
+ - Implement ObjectInstance rendering format.
72
+ - Bench each example QEA → 0/0/0/0 deltas.
73
+
74
+ ## Verification
75
+
76
+ `rake svg:examples` runs all example benchmarks in one command.
77
+ Output format:
78
+
79
+ ```
80
+ name N/M matched
81
+ rect ours=X ref=Y delta=Z (Z%)
82
+ path ...
83
+ polygon ...
84
+ text ...
85
+ ```
@@ -0,0 +1,48 @@
1
+ # TODO-D 51: «property» OY-gap rule + remaining examples gaps
2
+
3
+ ## Completed
4
+
5
+ ### «property» label discriminator (DONE)
6
+
7
+ `EndLabel#property_label?` now actually inspects the LLT/LLB OY
8
+ gap and returns false when below 15px. Previously it always
9
+ returned true, causing 4-8 spurious «property» texts per diagram
10
+ in basic.qea.
11
+
12
+ After fix:
13
+ - basic.qea 'Basic Class Diagram with Operations' → 100% parity
14
+ - basic.qea text overlap: 84.0% (high — most matching text correct)
15
+ - plateau text overlap unchanged at 64.5%
16
+ - plateau text count delta: -601 → -627 (correctly removes the
17
+ spurious «property» labels that ref doesn't have)
18
+
19
+ ## Remaining example gaps (still open)
20
+
21
+ ### Visibility icons (Test Model + Package Imports)
22
+
23
+ EA renders a complex "folded page" icon for each attribute row in
24
+ some diagram styles:
25
+ - 1 outer rect (11x14, pale yellow fill, blue stroke)
26
+ - 1 inner rect (11x4 at top, white fill, blue stroke)
27
+ - 1 horizontal divider path (midline)
28
+ - 3-4 short "text line" paths inside (4px wide each)
29
+
30
+ That's 5-6 elements per attribute row. Discriminator likely the
31
+ `ShowIcons=1` flag in diagram Style1.
32
+
33
+ ### Object instance rendering (Objects as Instances of Classes)
34
+
35
+ EA renders `Object 01 / roleOne: Class A` (instance name + role +
36
+ classifier) and `attribute = value` slots. Requires a new
37
+ InstanceSpecification model + renderer.
38
+
39
+ ### Domain Model connector routing
40
+
41
+ Ref uses cubic bezier (`C`) for connector paths in tree mode;
42
+ we use linear `L` segments. The visual is similar but path
43
+ geometry differs. EA also emits more sub-paths per connector
44
+ in some layouts.
45
+
46
+ ## Verification
47
+
48
+ `rake svg:examples` shows current state. 15/27 diagrams at 100%.
@@ -0,0 +1,89 @@
1
+ # TODO-D 52: Marker registration architecture + Plus marker
2
+
3
+ ## Problem
4
+
5
+ The original `marker.rb` had eager registration:
6
+
7
+ ```ruby
8
+ Registry.register(Diamond)
9
+ Registry.register(OpenTriangle)
10
+ Registry.register(Plus)
11
+ Registry.register(ArrowPath)
12
+ ```
13
+
14
+ But Diamond, OpenTriangle, etc. were declared via `autoload`, so
15
+ the constant lookup at module load time failed with:
16
+
17
+ ```
18
+ NameError: uninitialized constant Ea::Svg::EaEmitter::Marker::Plus
19
+ ```
20
+
21
+ ## Solution
22
+
23
+ Two-part lazy registration:
24
+
25
+ 1. **Self-registration at file scope**: each marker kind file
26
+ (diamond.rb, open_triangle.rb, plus.rb, arrow_path.rb) ends
27
+ with a fully-qualified registration call:
28
+
29
+ ```ruby
30
+ Ea::Svg::EaEmitter::Marker::Registry.register(
31
+ Ea::Svg::EaEmitter::Marker::Plus
32
+ )
33
+ ```
34
+
35
+ This runs when the file loads (which happens via autoload when
36
+ the constant is first referenced).
37
+
38
+ 2. **Lazy autoload trigger**: `Marker.ensure_builtins_registered!`
39
+ references each autoloaded marker constant, which triggers
40
+ file load, which runs the per-file registration line.
41
+
42
+ ```ruby
43
+ def self.ensure_builtins_registered!
44
+ Diamond
45
+ OpenTriangle
46
+ Plus
47
+ ArrowPath
48
+ end
49
+ ```
50
+
51
+ 3. **First-use hook**: `Registry.specs_for` calls
52
+ `Marker.ensure_builtins_registered!` before searching kinds,
53
+ so registration is triggered on the first marker lookup.
54
+
55
+ ## Benefits
56
+
57
+ - **OCP**: Adding a new marker kind = creating a new file with
58
+ its class + registration line. The marker.rb dispatcher does
59
+ NOT need modification.
60
+ - **Lazy loading**: marker kinds only load when the registry is
61
+ first queried.
62
+ - **No autoload cycle**: each kind file knows its own constant;
63
+ registration at the bottom of the file is safe.
64
+
65
+ ## Plus marker addition
66
+
67
+ New `Marker::Plus` for Nesting connectors. EA renders a 16x16
68
+ plus symbol at the contained end:
69
+
70
+ ```
71
+ M cx cy-8 L cx cy+8 (vertical arm)
72
+ M cx+8 cy L cx-8 cy (horizontal arm)
73
+ ```
74
+
75
+ basic.qea 'Package Contents' (3 visible nesting connectors) →
76
+ 100% path parity.
77
+
78
+ ## Tests
79
+
80
+ - spec/ea/svg/ea_emitter/marker/plus_spec.rb (5 specs):
81
+ handles? for Nesting, specs_for shape/anchor, ARM_LENGTH
82
+ constant.
83
+
84
+ ## Verification
85
+
86
+ - 1764 specs pass (up from 1759, +5 new)
87
+ - basic.qea: 20/22 diagrams within tolerance (was 19/22)
88
+ - Plateau bench unchanged: rect -221, path -280, polygon -6,
89
+ text -627.
@@ -0,0 +1,86 @@
1
+ # TODO-D 53: Remaining example parity gaps (deferred)
2
+
3
+ ## Summary
4
+
5
+ This round achieved 15/27 → 17/27 example diagrams at 100% parity
6
+ (plus 2/2 simple + 1/2 test, 20/22 basic, 5/6 ArcGIS).
7
+
8
+ ```
9
+ simple 2/2 matched 100% ✓
10
+ ArcGISWorkspace 5/6 matched
11
+ basic 20/22 matched
12
+ test 1/2 matched
13
+ ```
14
+
15
+ ## Remaining basic.qea gaps (7 diagrams, all minor)
16
+
17
+ | Diagram | rect | path | polygon | text | Root cause |
18
+ |---------|------|------|---------|------|------------|
19
+ | Package Imports | -6 | -18 | 0 | -4 | visibility icons missing |
20
+ | Object with Value Specifications | 0 | -6 | 0 | -19 | object instance format |
21
+ | Objects as Instances of Classes | 0 | -4 | 0 | -9 | object instance format |
22
+ | Domain Model | +3 | -7 | +1 | -8 | tree-routed bezier paths |
23
+ | Basic Object Diagram | 0 | -3 | 0 | -2 | (object value slots) |
24
+ | Basic Class with Receptions | 0 | +5 | -2 | -3 | extra compartment dividers |
25
+ | Composition with Substitution | 0 | 0 | 0 | -1 | nested class display_name |
26
+
27
+ ## test.qea gap
28
+
29
+ `Test Model` diagram: r=-15, p=-58, po=0, t=-11. Needs visibility
30
+ icons + Package element attribute rendering.
31
+
32
+ ## Implementation paths (in priority order)
33
+
34
+ ### TODO-D 54: Visibility icons (TODO-D 51 expansion)
35
+
36
+ EA renders 5-6 element decorations per attribute row when
37
+ `ShowIcons=1`:
38
+ - 1 outer rect (11x14, pale yellow + blue stroke)
39
+ - 1 inner rect (11x4, white)
40
+ - 1 horizontal divider path (midline)
41
+ - 3-4 short "text line" paths inside
42
+
43
+ This closes `Test Model` (r=-15, p=-58) and `Package Imports`
44
+ (r=-6, p=-18). 73+ missing elements across examples.
45
+
46
+ Implementation: `Compartment::VisibilityIcon` + discriminator in
47
+ `RenderContext` (default hidden, opt-in via DiagramElement#icon_visible
48
+ or DisplayConfig#show_icons).
49
+
50
+ ### TODO-D 55: Object instance format
51
+
52
+ EA renders object instances as:
53
+ - Header: `Object 01 / roleOne: Class A` (instance name + role + classifier)
54
+ - Slot rows: `attribute = value` for each slot
55
+ - Package qualifier: `(from Objects)`
56
+
57
+ Current code renders them as plain classes with the qualified class
58
+ name. Requires new `Ea::Model::InstanceSpecification` model + QEA
59
+ parser support + ObjectInstanceRenderer compartment.
60
+
61
+ ### TODO-D 56: Tree-routed bezier paths
62
+
63
+ EA renders tree-routed connectors with cubic bezier curves
64
+ (C commands) for smooth paths. We render straight L segments.
65
+ The visual is similar but path count differs. Detection: when a
66
+ connector has 3+ waypoints with `tree:` style, emit bezier.
67
+
68
+ ## Architectural decisions documented this round
69
+
70
+ 1. **«property» label OY-gap rule**: real geometry check (15px
71
+ threshold) instead of always-true.
72
+ 2. **Implicit connector visibility**: render Nesting when
73
+ `tree:` style is set, filter otherwise.
74
+ 3. **Plus marker**: new `Marker::Plus` kind for Nesting connector
75
+ "+" decoration (lazy registration architecture).
76
+ 4. **Marker registration**: per-file `Registry.register(...)` +
77
+ `Marker.ensure_builtins_registered!` — OCP-friendly, no
78
+ autoload cycle.
79
+
80
+ ## Final state
81
+
82
+ - 1764 specs pass
83
+ - Zero code-quality violations
84
+ - basic.qea: 8 → 9 perfect diagrams (out of 22)
85
+ - test.qea: 0 → 1 perfect diagram (out of 2)
86
+ - simple.qea: 2/2 perfect
@@ -0,0 +1,40 @@
1
+ # TODO-D 54: display_name for nested classes (DONE)
2
+
3
+ ## Before
4
+
5
+ `HeaderLines#display_name` used both `visually_nested` AND
6
+ `nested_class_qualifier?` to decide whether to render the
7
+ qualified name:
8
+
9
+ ```ruby
10
+ return name if visually_nested &&
11
+ classifier.is_a?(Ea::Model::Classifier) &&
12
+ nested_class_qualifier?(classifier, name)
13
+ ```
14
+
15
+ The `visually_nested` check is a position-based heuristic (child
16
+ bounds inside parent bounds). For basic.qea's "Composition with
17
+ Substitution" diagram, Class B.1, B.2, B.3 are placed at y=-330
18
+ (off-canvas) while Class B is at y=-172. The position check returns
19
+ false, but the reference renders "Class B::Class B.1" (qualified).
20
+
21
+ ## After
22
+
23
+ The `visually_nested` check is dropped. The `nested_class_qualifier?`
24
+ check alone determines the display:
25
+
26
+ ```ruby
27
+ return name if classifier.is_a?(Ea::Model::Classifier) &&
28
+ nested_class_qualifier?(classifier, name)
29
+ ```
30
+
31
+ The qualifier is a parent class name (not a package name) when it
32
+ differs from the classifier's package name. EA always shows the
33
+ parent-class qualifier regardless of visual position.
34
+
35
+ ## Verification
36
+
37
+ - basic.qea "Composition with Substitution": text delta -1 → 0 ✓
38
+ - 1764 specs pass
39
+ - Plateau unchanged (text overlap 64.5%)
40
+ - simple.qea unchanged (100%)