ea 0.4.0 → 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.
- checksums.yaml +4 -4
- data/Rakefile +3 -0
- data/TODO.complete/01-t-xref-parsing.md +91 -0
- data/TODO.complete/02-per-label-geometry.md +50 -0
- data/TODO.complete/03-object-properties-constraints.md +57 -0
- data/TODO.complete/04-operation-params.md +37 -0
- data/TODO.complete/05-pdata-flag-matrix.md +52 -0
- data/TODO.complete/06-emf-image-rendering.md +34 -0
- data/TODO.complete/07-auxiliary-tables.md +47 -0
- data/TODO.complete/10-mdg-stereotype-registry.md +40 -0
- data/TODO.complete/11-gml-xsd-generation.md +42 -0
- data/TODO.complete/13-shapescript-interpreter.md +28 -0
- data/TODO.complete/20-cli-diff.md +46 -0
- data/TODO.complete/21-cli-render.md +26 -0
- data/TODO.complete/22-cli-export.md +29 -0
- data/TODO.complete/23-cli-mdg.md +23 -0
- data/TODO.complete/30-headerlines-ocp-refactor.md +72 -0
- data/TODO.complete/31-public-send-cleanup.md +61 -0
- data/TODO.complete/32-spec-coverage.md +33 -0
- data/TODO.complete/33-blocked-parity-gaps.md +41 -0
- data/TODO.complete/36-stereotype-icon-wiring.md +32 -0
- data/TODO.complete/37-cli-lint.md +32 -0
- data/TODO.complete/38-cli-query.md +26 -0
- data/TODO.complete/39-cli-info.md +23 -0
- data/TODO.complete/40-ocl-evaluator.md +31 -0
- data/TODO.complete/41-round-trip-spec.md +18 -0
- data/TODO.complete/42-html-diff-report.md +18 -0
- data/TODO.complete/43-json-schema-export.md +20 -0
- data/TODO.complete/44-remaining-qea-tables.md +40 -0
- data/TODO.complete/45-shapescript-extensions.md +25 -0
- data/TODO.complete/46-xsd-consolidation.md +20 -0
- data/TODO.complete/47-headerlines-legacy-removal.md +20 -0
- data/TODO.complete/STATUS.md +109 -0
- data/TODO.diagrams/01-svg-measurement-harness.md +31 -0
- data/TODO.diagrams/02-polygon-over-rendering.md +29 -0
- data/TODO.diagrams/03-text-over-rendering.md +30 -0
- data/TODO.diagrams/04-rect-under-rendering.md +33 -0
- data/TODO.diagrams/05-canvas-dimension-parity.md +51 -0
- data/TODO.diagrams/06-group-layering-parity.md +39 -0
- data/TODO.diagrams/07-text-content-fidelity.md +65 -0
- data/TODO.diagrams/08-qea-direct-pipeline.md +46 -0
- data/TODO.diagrams/12-connector-labels.md +40 -0
- data/TODO.diagrams/12-per-entity-svg-layer-ordering.md +24 -0
- data/TODO.diagrams/13-marker-polygon-vs-path-dispatch.md +20 -0
- data/TODO.diagrams/13-per-text-type-font-sizes.md +33 -0
- data/TODO.diagrams/14-center-header-text.md +33 -0
- data/TODO.diagrams/14-filter-diagram-frame-elements.md +18 -0
- data/TODO.diagrams/15-deep-dead-code-audit.md +47 -0
- data/TODO.diagrams/15-per-element-font-from-style.md +24 -0
- data/TODO.diagrams/16-canvas-marker-extent.md +30 -0
- data/TODO.diagrams/16-document-remaining-parity-gaps.md +91 -0
- data/TODO.diagrams/17-italic-abstract-classes.md +28 -0
- data/TODO.diagrams/17-remaining-parity-gaps.md +90 -0
- data/TODO.diagrams/18-canvas-from-image-bounds.md +20 -0
- data/TODO.diagrams/18-property-lookup-index.md +42 -0
- data/TODO.diagrams/19-connector-sx-sy-routing.md +27 -0
- data/TODO.diagrams/19-replace-respond-to-with-is-a.md +31 -0
- data/TODO.diagrams/20-split-labels-emitter.md +56 -0
- data/TODO.diagrams/20-visibility-glyph-font-encoding.md +27 -0
- data/TODO.diagrams/21-aggregation-navigability-arrow.md +21 -0
- data/TODO.diagrams/21-auto-generated-legend-block.md +65 -0
- data/TODO.diagrams/22-ghost-element-discriminator.md +57 -0
- data/TODO.diagrams/22-style-based-path-grouping.md +28 -0
- data/TODO.diagrams/23-marker-polygon-deduplication.md +47 -0
- data/TODO.diagrams/23-multiplicity-label-positioning.md +29 -0
- data/TODO.diagrams/24-marker-anchor-structural.md +35 -0
- data/TODO.diagrams/24-track-marker-anchors-structurally.md +66 -0
- data/TODO.diagrams/24-truncate-properties-to-fit-box.md +24 -0
- data/TODO.diagrams/26-phantom-general-parent-rendering.md +59 -0
- data/TODO.diagrams/27-path-grouping-mode-detection.md +43 -0
- data/TODO.diagrams/28-architecture-cleanup-batch.md +47 -0
- data/TODO.diagrams/30-decompose-elements-groups-for.md +52 -0
- data/TODO.diagrams/32-examples-coverage-batch.md +78 -0
- data/TODO.diagrams/36-instance-specification-model.md +42 -0
- data/TODO.diagrams/37-element-icon-decorations.md +41 -0
- data/TODO.diagrams/38-html-note-and-receptions.md +32 -0
- data/TODO.diagrams/39-property-stereotype-discriminator.md +40 -0
- data/TODO.diagrams/40-standalone-1-discriminator.md +38 -0
- data/TODO.diagrams/41-xmi-to-svg-pipeline.md +113 -0
- data/TODO.diagrams/42-close-all-parity-deltas.md +69 -0
- data/TODO.diagrams/43-marker-deduplication-strategy.md +54 -0
- data/TODO.diagrams/44-element-icon-decorations.md +34 -0
- data/TODO.diagrams/45-phantom-parent-class-boxes.md +40 -0
- data/TODO.diagrams/46-user-drawn-legend-swatches.md +44 -0
- data/TODO.diagrams/47-attribute-line-fidelity.md +72 -0
- data/TODO.diagrams/48-spec-coverage-critical-emitter-components.md +45 -0
- data/TODO.diagrams/49-spec-coverage-orchestrators.md +25 -0
- data/TODO.diagrams/50-examples-parity.md +85 -0
- data/TODO.diagrams/51-property-oy-gap-and-remaining-gaps.md +48 -0
- data/TODO.diagrams/52-marker-registration-architecture.md +89 -0
- data/TODO.diagrams/53-remaining-example-gaps.md +86 -0
- data/TODO.diagrams/54-display-name-nested-classes.md +40 -0
- data/TODO.diagrams/55-visibility-icon-discriminator.md +58 -0
- data/TODO.diagrams/56-package-contents-rendering.md +148 -0
- data/TODO.diagrams/57-instance-specification-model.md +100 -0
- data/TODO.diagrams/58-domain-model-note-text.md +67 -0
- data/TODO.diagrams/59-classes-arrow-discriminator.md +57 -0
- data/TODO.diagrams/60-testschema-association-marker.md +40 -0
- data/TODO.diagrams/61-legend-block-rendering.md +55 -0
- data/TODO.diagrams/61-plateau-parity-gaps.md +59 -0
- data/TODO.diagrams/62-ghost-element-rendering.md +56 -0
- data/TODO.diagrams/63-qualified-name-wrap.md +36 -0
- data/TODO.diagrams/64-property-stereotype-labels.md +22 -0
- data/TODO.diagrams/65-path-coordinate-frame.md +62 -0
- data/TODO.diagrams/67-path-coordinate-frame.md +62 -0
- data/TODO.diagrams/68-inherited-attributes.md +65 -0
- data/TODO.diagrams/69-package-anchor-conditional.md +29 -0
- data/TODO.diagrams/70-mdg-technology-support.md +68 -0
- data/TODO.diagrams/71-off-canvas-parent-ghost.md +45 -0
- data/TODO.diagrams/72-basic-attr-divider-paths.md +39 -0
- data/TODO.diagrams/73-plateau-polygon-gap.md +69 -0
- data/TODO.diagrams/74-plateau-rect-gap.md +22 -0
- data/TODO.diagrams/75-plateau-text-gap.md +39 -0
- data/TODO.diagrams/76-basic-poly-path-gaps.md +41 -0
- data/TODO.diagrams/77-basic-text-overrender.md +40 -0
- data/TODO.diagrams/78-headerlines-ocp-refactor.md +65 -0
- data/TODO.diagrams/79-architecture-backlog.md +65 -0
- data/TODO.diagrams/80-basic-triangle-polygons.md +51 -0
- data/TODO.diagrams/81-plateau-path-overrender.md +53 -0
- data/TODO.diagrams/82-appearance-canvas-offset.md +54 -0
- data/TODO.diagrams/83-3d-diagram-subtitle.md +58 -0
- data/TODO.diagrams/84-canvas-offset-mismatches.md +61 -0
- data/TODO.diagrams/85-phantom-property-overrender.md +95 -0
- data/TODO.diagrams/86-foreign-package-rule.md +62 -0
- data/TODO.diagrams/87-internal-tech-encryption.md +80 -0
- data/TODO.diagrams/EXAMPLES_STATUS.md +88 -0
- data/TODO.diagrams/README.md +69 -0
- data/TODO.diagrams/STATUS.md +73 -0
- data/TODO.fixup/01-default-grouped-paths.md +34 -0
- data/TODO.fixup/02-marker-consolidation-per-connector.md +20 -0
- data/TODO.fixup/03-diagram-font-inference.md +28 -0
- data/TODO.fixup/04-extract-bounds-calculator.md +25 -0
- data/TODO.fixup/05-marker-registry-ocp.md +32 -0
- data/TODO.fixup/06-connector-path-bend-routing.md +28 -0
- data/TODO.fixup/07-edge-attachment-formula.md +22 -0
- data/TODO.fixup/08-visual-diff-harness.md +28 -0
- data/TODO.fixup/09-extract-element-compartments.md +34 -0
- data/TODO.fixup/10-canvas-width-overshoot-fix.md +20 -0
- data/TODO.fixup/11-layer-sequencer-extraction.md +18 -0
- data/TODO.fixup/12-path-style-harmony.md +23 -0
- data/TODO.fixup/13-datatype-stereotype-fallback.md +28 -0
- data/TODO.fixup/14-ea-exe-reverse-engineering-notes.md +56 -0
- data/TODO.fixup/15-enumeration-literal-rendering.md +30 -0
- data/TODO.fixup/16-operation-compartment-rendering.md +42 -0
- data/TODO.fixup/17-path-count-calibration.md +27 -0
- data/TODO.fixup/18-polygon-count-calibration.md +32 -0
- data/TODO.fixup/19-rect-count-undershoot-investigation.md +40 -0
- data/TODO.fixup/20-stereotype-color-from-classifier.md +18 -0
- data/TODO.fixup/21-visibility-filter-for-properties.md +24 -0
- data/TODO.fixup/22-multiplicity-display-rule-calibration.md +25 -0
- data/TODO.fixup/23-diagram-frame-title-element.md +31 -0
- data/TODO.fixup/24-note-element-rendering.md +23 -0
- data/TODO.fixup/25-ea-exe-disassembly-findings.md +177 -0
- data/TODO.fixup/26-svg-renderer-architecture.md +78 -0
- data/TODO.fixup/27-svg-element-emitters-disassembly.md +135 -0
- data/TODO.fixup/28-geometry-parser-identification.md +57 -0
- data/TODO.fixup/29-qea-svg-xmi-triple-comparison.md +185 -0
- data/TODO.fixup/30-theme-system-stub.md +46 -0
- data/TODO.fixup/31-theme-value-object-registry.md +17 -0
- data/TODO.fixup/32-styleex-on-diagram-model.md +22 -0
- data/TODO.fixup/33-text-encoding-decimals-rotation.md +29 -0
- data/TODO.fixup/34-per-type-fill-via-theme.md +18 -0
- data/TODO.fixup/35-stroke-width-per-theme.md +7 -0
- data/TODO.fixup/36-qea-rect-coord-normalization.md +24 -0
- data/TODO.fixup/37-package-shape-rendering.md +22 -0
- data/TODO.fixup/38-note-element-rendering.md +15 -0
- data/TODO.fixup/39-styleex-flag-honoring.md +25 -0
- data/TODO.fixup/40-connector-dashed-lines.md +15 -0
- data/TODO.fixup/41-diagram-frame-showborder-detection.md +23 -0
- data/TODO.fixup/42-textrenderer-centralization.md +10 -0
- data/TODO.fixup/43-colorresolver-unification.md +24 -0
- data/TODO.fixup/44-theme-aware-textrenderer.md +17 -0
- data/TODO.fixup/45-theme-aware-fontresolver.md +22 -0
- data/TODO.fixup/46-style-parameterized-by-theme.md +21 -0
- data/TODO.fixup/47-canvas-frame-inset.md +19 -0
- data/TODO.fixup/48-background-rect-format.md +15 -0
- data/TODO.fixup/49-all-samples-integration-test.md +17 -0
- data/TODO.fixup/50-svg-emitter-architecture-docs.md +33 -0
- data/TODO.fixup/51-promote-theme-to-ea-namespace.md +28 -0
- data/TODO.fixup/52-theme-definition-integrated-fills.md +26 -0
- data/TODO.fixup/53-theme-registry-yaml-loading.md +50 -0
- data/TODO.fixup/54-diagram-theme-api.md +50 -0
- data/TODO.fixup/55-update-eaemitter-to-ea-theme.md +23 -0
- data/TODO.fixup/56-theme-yaml-files.md +65 -0
- data/TODO.fixup/57-theme-specs-and-integration.md +27 -0
- data/TODO.fixup/58-ea-entry-point-theme-autoload.md +20 -0
- data/TODO.fixup/59-thread-theme-through-all-renderers.md +29 -0
- data/TODO.fixup/60-cli-theme-option.md +22 -0
- data/TODO.fixup/61-theme-validation.md +28 -0
- data/TODO.fixup/62-theme-builder-dsl.md +31 -0
- data/TODO.fixup/63-theme-integration-rendering-spec.md +24 -0
- data/TODO.fixup/64-theme-writeback-styleex.md +21 -0
- data/TODO.fixup/65-remove-dead-eaemitter-theme-files.md +30 -0
- data/TODO.fixup/66-styleex-writeback.md +22 -0
- data/TODO.fixup/67-delete-dead-code.md +28 -0
- data/TODO.fixup/68-figure-parity-status.md +82 -0
- data/TODO.fixup/69-package-polygon-rendering.md +54 -0
- data/TODO.fixup/70-tagged-values-compartment.md +39 -0
- data/TODO.fixup/71-auto-detect-theme-from-xmi.md +37 -0
- data/TODO.fixup/72-sample-exports-as-regression-specs.md +37 -0
- data/TODO.fixup/73-delete-dead-transformations.md +14 -0
- data/TODO.fixup/74-delete-dead-diagram-renderers.md +18 -0
- data/TODO.fixup/75-visibility-legend-icons.md +23 -0
- data/TODO.fixup/76-plateau-text-undershoot.md +27 -0
- data/TODO.fixup/77-canvas-frame-margins.md +28 -0
- data/TODO.fixup/78-note-element-rendering.md +30 -0
- data/TODO.fixup/79-operation-compartment-rendering.md +27 -0
- data/TODO.fixup/80-tagged-value-stereotype-visibility.md +37 -0
- data/TODO.fixup/81-figure-parity-current-state.md +63 -0
- data/config/qea_schema.yml +356 -0
- data/config/themes/119.yml +98 -0
- data/config/themes/default.yml +14 -0
- data/examples/exports/20251010_current_plateau_v5/UML_EA.DTD +6856 -0
- data/examples/exports/20251010_current_plateau_v5/model.xml +96709 -0
- data/examples/exports/ArcGISWorkspace_template/UML_EA.DTD +6856 -0
- data/examples/exports/ArcGISWorkspace_template/model.xml +1427 -0
- data/examples/exports/UmlModel_template/UML_EA.DTD +6856 -0
- data/examples/exports/UmlModel_template/model.xml +23 -0
- data/examples/exports/basic/UML_EA.DTD +6856 -0
- data/examples/exports/basic/model.xml +8039 -0
- data/examples/exports/simple/UML_EA.DTD +6856 -0
- data/examples/exports/simple/model.xml +585 -0
- data/examples/exports/simple_example/UML_EA.DTD +6856 -0
- data/examples/exports/simple_example/model.xml +23 -0
- data/examples/exports/test/UML_EA.DTD +6856 -0
- data/examples/exports/test/model.xml +1638 -0
- data/examples/qea/basic.qea +0 -0
- data/frontend/README.md +51 -0
- data/frontend/dist/app.iife.js +24 -0
- data/frontend/dist/style.css +1 -0
- data/frontend/index.html +26 -0
- data/frontend/package-lock.json +2359 -0
- data/frontend/package.json +26 -0
- data/frontend/src/App.vue +59 -0
- data/frontend/src/app.ts +8 -0
- data/frontend/src/components/AppHeader.vue +127 -0
- data/frontend/src/components/AppSidebar.vue +119 -0
- data/frontend/src/components/ClassDetails.vue +247 -0
- data/frontend/src/components/DiagramView.vue +79 -0
- data/frontend/src/components/PackageDetails.vue +92 -0
- data/frontend/src/components/PackageTreeNode.vue +64 -0
- data/frontend/src/components/SearchResults.vue +48 -0
- data/frontend/src/components/WelcomeView.vue +87 -0
- data/frontend/src/shims-vue.d.ts +5 -0
- data/frontend/src/stores/dataStore.ts +79 -0
- data/frontend/src/stores/uiStore.ts +167 -0
- data/frontend/src/styles/main.css +1566 -0
- data/frontend/src/types.ts +221 -0
- data/frontend/tests/e2e/__screenshots__/new-dark-mode.png +0 -0
- data/frontend/tests/e2e/__screenshots__/new-package-details.png +0 -0
- data/frontend/tests/e2e/__screenshots__/new-search-modal.png +0 -0
- data/frontend/tests/e2e/__screenshots__/new-sidebar-collapsed.png +0 -0
- data/frontend/tests/e2e/__screenshots__/new-welcome.png +0 -0
- data/frontend/tests/e2e/render.spec.ts +188 -0
- data/frontend/tsconfig.json +20 -0
- data/frontend/vite.config.ts +26 -0
- data/frontend/vitest.config.ts +8 -0
- data/lib/ea/cli/app.rb +57 -2
- data/lib/ea/cli/command/diagrams.rb +37 -28
- data/lib/ea/cli/command/diff.rb +46 -0
- data/lib/ea/cli/command/export.rb +80 -0
- data/lib/ea/cli/command/info.rb +75 -0
- data/lib/ea/cli/command/lint.rb +48 -0
- data/lib/ea/cli/command/mdg.rb +98 -0
- data/lib/ea/cli/command/query.rb +34 -0
- data/lib/ea/cli/command/render.rb +135 -0
- data/lib/ea/cli/command/svg.rb +8 -15
- data/lib/ea/cli/command.rb +7 -0
- data/lib/ea/diagram/display_config.rb +184 -0
- data/lib/ea/diagram.rb +4 -41
- data/lib/ea/diff/change.rb +30 -0
- data/lib/ea/diff/comparator.rb +82 -0
- data/lib/ea/diff/html_reporter.rb +91 -0
- data/lib/ea/diff.rb +15 -0
- data/lib/ea/export/json/generator.rb +42 -0
- data/lib/ea/export/json.rb +12 -0
- data/lib/ea/export/json_schema/generator.rb +77 -0
- data/lib/ea/export/json_schema.rb +12 -0
- data/lib/ea/export/plantuml/generator.rb +73 -0
- data/lib/ea/export/plantuml.rb +12 -0
- data/lib/ea/export/xmi/generator.rb +77 -0
- data/lib/ea/export/xmi.rb +11 -0
- data/lib/ea/export/xsd/class_mapping.rb +65 -0
- data/lib/ea/export/xsd/generator.rb +142 -0
- data/lib/ea/export/xsd/namespace_registry.rb +82 -0
- data/lib/ea/export/xsd.rb +19 -0
- data/lib/ea/export.rb +14 -0
- data/lib/ea/image/emf_renderer.rb +42 -0
- data/lib/ea/image.rb +12 -0
- data/lib/ea/lint/engine.rb +30 -0
- data/lib/ea/lint/lint_rule.rb +38 -0
- data/lib/ea/lint/offense.rb +18 -0
- data/lib/ea/lint/rules/cyclic_generalization.rb +62 -0
- data/lib/ea/lint/rules/duplicate_name.rb +28 -0
- data/lib/ea/lint/rules/missing_stereotype.rb +35 -0
- data/lib/ea/lint/rules/naming_convention.rb +44 -0
- data/lib/ea/lint/rules/orphan_element.rb +28 -0
- data/lib/ea/lint/rules.rb +14 -0
- data/lib/ea/lint.rb +13 -0
- data/lib/ea/mdg/document.rb +120 -0
- data/lib/ea/mdg/loader.rb +118 -0
- data/lib/ea/mdg/registry.rb +98 -0
- data/lib/ea/mdg/stereotype_alias_registry.rb +77 -0
- data/lib/ea/mdg/xml/applies_to.rb +18 -0
- data/lib/ea/mdg/xml/apply.rb +18 -0
- data/lib/ea/mdg/xml/content.rb +18 -0
- data/lib/ea/mdg/xml/documentation.rb +24 -0
- data/lib/ea/mdg/xml/stereotype.rb +28 -0
- data/lib/ea/mdg/xml/stereotypes.rb +18 -0
- data/lib/ea/mdg/xml/tag.rb +28 -0
- data/lib/ea/mdg/xml/tagged_values.rb +18 -0
- data/lib/ea/mdg/xml/technology.rb +28 -0
- data/lib/ea/mdg/xml/uml_profile.rb +22 -0
- data/lib/ea/mdg/xml/uml_profiles.rb +18 -0
- data/lib/ea/mdg/xml.rb +24 -0
- data/lib/ea/mdg.rb +25 -0
- data/lib/ea/model/classifier.rb +4 -0
- data/lib/ea/model/constraint.rb +24 -0
- data/lib/ea/model/diagram.rb +85 -0
- data/lib/ea/model/diagram_connector.rb +34 -0
- data/lib/ea/model/diagram_element.rb +16 -0
- data/lib/ea/model/document.rb +47 -2
- data/lib/ea/model/ghost_label.rb +32 -0
- data/lib/ea/model/instance_specification.rb +34 -0
- data/lib/ea/model/legend.rb +43 -0
- data/lib/ea/model/legend_item.rb +26 -0
- data/lib/ea/model/note.rb +28 -0
- data/lib/ea/model/operation.rb +2 -0
- data/lib/ea/model/property.rb +2 -0
- data/lib/ea/model/relationship.rb +2 -0
- data/lib/ea/model/signal.rb +14 -0
- data/lib/ea/model/slot.rb +19 -0
- data/lib/ea/model.rb +8 -0
- data/lib/ea/ocl/evaluator.rb +94 -0
- data/lib/ea/ocl/nodes.rb +30 -0
- data/lib/ea/ocl/parser.rb +133 -0
- data/lib/ea/ocl/unsupported_error.rb +7 -0
- data/lib/ea/ocl.rb +13 -0
- data/lib/ea/qea/factory/document_builder.rb +24 -10
- data/lib/ea/qea/factory/generalization_builder.rb +9 -11
- data/lib/ea/qea/infrastructure/table_reader.rb +9 -0
- data/lib/ea/qea/models/ea_author.rb +35 -0
- data/lib/ea/qea/models/ea_glossary.rb +34 -0
- data/lib/ea/qea/models/ea_image.rb +53 -0
- data/lib/ea/qea/models/ea_implement.rb +32 -0
- data/lib/ea/qea/models/ea_list.rb +42 -0
- data/lib/ea/qea/models/ea_object_effort.rb +34 -0
- data/lib/ea/qea/models/ea_object_problem.rb +37 -0
- data/lib/ea/qea/models/ea_object_require.rb +34 -0
- data/lib/ea/qea/models/ea_object_resource.rb +34 -0
- data/lib/ea/qea/models/ea_object_risk.rb +34 -0
- data/lib/ea/qea/models/ea_object_scenario.rb +34 -0
- data/lib/ea/qea/models/ea_object_test.rb +35 -0
- data/lib/ea/qea/models/ea_object_trx.rb +34 -0
- data/lib/ea/qea/models/ea_operation.rb +7 -0
- data/lib/ea/qea/models/ea_palette.rb +30 -0
- data/lib/ea/qea/models/ea_palette_item.rb +36 -0
- data/lib/ea/qea/models/ea_phase.rb +40 -0
- data/lib/ea/qea/models/ea_role_constraint.rb +32 -0
- data/lib/ea/qea/models/ea_secrypt.rb +34 -0
- data/lib/ea/qea/models/ea_version.rb +39 -0
- data/lib/ea/qea/models/ea_xref.rb +11 -1
- data/lib/ea/qea/models.rb +19 -0
- data/lib/ea/qea/services/database_loader.rb +22 -1
- data/lib/ea/query/builder.rb +108 -0
- data/lib/ea/query.rb +9 -0
- data/lib/ea/render/image_converter.rb +101 -0
- data/lib/ea/render.rb +10 -0
- data/lib/ea/shapescript/parser.rb +208 -0
- data/lib/ea/shapescript/renderer.rb +74 -0
- data/lib/ea/shapescript/shape.rb +34 -0
- data/lib/ea/shapescript.rb +24 -0
- data/lib/ea/sources/qea/adapter.rb +22 -5
- data/lib/ea/sources/qea/classifier_builder.rb +184 -7
- data/lib/ea/sources/qea/diagram_builder.rb +352 -24
- data/lib/ea/sources/qea/id_normalizer.rb +16 -1
- data/lib/ea/sources/qea/instance_builder.rb +113 -0
- data/lib/ea/sources/qea/legend_builder.rb +137 -0
- data/lib/ea/sources/qea/note_builder.rb +58 -0
- data/lib/ea/sources/qea/object_classifier_map.rb +6 -1
- data/lib/ea/sources/qea/operation_builder.rb +1 -0
- data/lib/ea/sources/qea/package_builder.rb +16 -0
- data/lib/ea/sources/qea/relationship_builder.rb +21 -5
- data/lib/ea/sources/qea/tagged_value_builder.rb +28 -9
- data/lib/ea/sources/qea/xref/legend_definition.rb +35 -0
- data/lib/ea/sources/qea/xref/parser.rb +150 -0
- data/lib/ea/sources/qea/xref/property_definition.rb +29 -0
- data/lib/ea/sources/qea/xref/record.rb +41 -0
- data/lib/ea/sources/qea/xref/stereotype_application.rb +37 -0
- data/lib/ea/sources/qea/xref.rb +27 -0
- data/lib/ea/sources/qea.rb +4 -0
- data/lib/ea/sources/xmi/adapter.rb +80 -2
- data/lib/ea/sources/xmi/classifier_builder.rb +10 -1
- data/lib/ea/sources/xmi/diagram_builder.rb +95 -18
- data/lib/ea/sources/xmi/extension_geometry_parser.rb +19 -2
- data/lib/ea/sources/xmi/extension_style_parser.rb +15 -2
- data/lib/ea/sources/xmi/note_builder.rb +46 -0
- data/lib/ea/sources/xmi/property_builder.rb +9 -0
- data/lib/ea/sources/xmi/stereotype_builder.rb +54 -0
- data/lib/ea/sources/xmi/tag_builder.rb +45 -0
- data/lib/ea/sources/xmi/umldi_keyword_extractor.rb +87 -0
- data/lib/ea/sources/xmi.rb +4 -0
- data/lib/ea/spa/output/sharded_multi_file_strategy.rb +18 -3
- data/lib/ea/spa/output/single_file_strategy.rb +8 -2
- data/lib/ea/spa/output/strategy.rb +34 -0
- data/lib/ea/svg/connector_router.rb +134 -0
- data/lib/ea/svg/ea_emitter/background.rb +2 -3
- data/lib/ea/svg/ea_emitter/bounds_calculator.rb +142 -0
- data/lib/ea/svg/ea_emitter/canvas.rb +56 -33
- data/lib/ea/svg/ea_emitter/color_resolver.rb +56 -0
- data/lib/ea/svg/ea_emitter/compartment/attributes.rb +28 -0
- data/lib/ea/svg/ea_emitter/compartment/constraints.rb +30 -0
- data/lib/ea/svg/ea_emitter/compartment/enum_literals.rb +86 -0
- data/lib/ea/svg/ea_emitter/compartment/header.rb +32 -0
- data/lib/ea/svg/ea_emitter/compartment/header_divider.rb +57 -0
- data/lib/ea/svg/ea_emitter/compartment/instance_slots.rb +96 -0
- data/lib/ea/svg/ea_emitter/compartment/instance_underline.rb +67 -0
- data/lib/ea/svg/ea_emitter/compartment/note_body.rb +52 -0
- data/lib/ea/svg/ea_emitter/compartment/note_text.rb +102 -0
- data/lib/ea/svg/ea_emitter/compartment/operations.rb +38 -0
- data/lib/ea/svg/ea_emitter/compartment/package_contents.rb +72 -0
- data/lib/ea/svg/ea_emitter/compartment/package_from_parent.rb +136 -0
- data/lib/ea/svg/ea_emitter/compartment/shape.rb +82 -0
- data/lib/ea/svg/ea_emitter/compartment/tagged_values.rb +30 -0
- data/lib/ea/svg/ea_emitter/compartment.rb +58 -0
- data/lib/ea/svg/ea_emitter/connectors.rb +46 -12
- data/lib/ea/svg/ea_emitter/diagram_frame.rb +143 -0
- data/lib/ea/svg/ea_emitter/document.rb +15 -24
- data/lib/ea/svg/ea_emitter/element/attribute_line_builder.rb +117 -0
- data/lib/ea/svg/ea_emitter/element/attribute_renderer.rb +119 -0
- data/lib/ea/svg/ea_emitter/element/bcol_decoder.rb +29 -0
- data/lib/ea/svg/ea_emitter/element/compartment_geometry.rb +113 -0
- data/lib/ea/svg/ea_emitter/element/constraint_renderer.rb +53 -0
- data/lib/ea/svg/ea_emitter/element/divider_renderer.rb +17 -0
- data/lib/ea/svg/ea_emitter/element/enumeration_literal_renderer.rb +34 -0
- data/lib/ea/svg/ea_emitter/element/filter.rb +44 -0
- data/lib/ea/svg/ea_emitter/element/hand_draw_shape_renderer.rb +77 -0
- data/lib/ea/svg/ea_emitter/element/header_line_pipeline.rb +43 -0
- data/lib/ea/svg/ea_emitter/element/header_line_provider/instance_spec.rb +27 -0
- data/lib/ea/svg/ea_emitter/element/header_line_provider/name.rb +76 -0
- data/lib/ea/svg/ea_emitter/element/header_line_provider/parent_ghost.rb +25 -0
- data/lib/ea/svg/ea_emitter/element/header_line_provider/stereotype_label.rb +68 -0
- data/lib/ea/svg/ea_emitter/element/header_line_provider.rb +19 -0
- data/lib/ea/svg/ea_emitter/element/header_lines.rb +27 -0
- data/lib/ea/svg/ea_emitter/element/header_renderer.rb +48 -0
- data/lib/ea/svg/ea_emitter/element/icon_renderer.rb +109 -0
- data/lib/ea/svg/ea_emitter/element/legend_renderer.rb +177 -0
- data/lib/ea/svg/ea_emitter/element/note_shape_renderer.rb +112 -0
- data/lib/ea/svg/ea_emitter/element/operation_renderer.rb +100 -0
- data/lib/ea/svg/ea_emitter/element/package_shape_renderer.rb +181 -0
- data/lib/ea/svg/ea_emitter/element/row_icon_renderer.rb +156 -0
- data/lib/ea/svg/ea_emitter/element/shape_renderer.rb +17 -0
- data/lib/ea/svg/ea_emitter/element/stereotype_icon_renderer.rb +82 -0
- data/lib/ea/svg/ea_emitter/element/tagged_value_renderer.rb +50 -0
- data/lib/ea/svg/ea_emitter/element/text_escape.rb +20 -0
- data/lib/ea/svg/ea_emitter/element.rb +37 -0
- data/lib/ea/svg/ea_emitter/elements.rb +283 -95
- data/lib/ea/svg/ea_emitter/font_resolver.rb +111 -0
- data/lib/ea/svg/ea_emitter/ghost_labels.rb +66 -0
- data/lib/ea/svg/ea_emitter/label/end_label.rb +266 -0
- data/lib/ea/svg/ea_emitter/label/midpoint_label.rb +101 -0
- data/lib/ea/svg/ea_emitter/label/registry.rb +50 -0
- data/lib/ea/svg/ea_emitter/label.rb +23 -0
- data/lib/ea/svg/ea_emitter/labels.rb +93 -27
- data/lib/ea/svg/ea_emitter/layer.rb +20 -0
- data/lib/ea/svg/ea_emitter/layer_sequencer.rb +93 -0
- data/lib/ea/svg/ea_emitter/marker/arrow_path.rb +52 -0
- data/lib/ea/svg/ea_emitter/marker/diamond.rb +57 -0
- data/lib/ea/svg/ea_emitter/marker/kind.rb +35 -0
- data/lib/ea/svg/ea_emitter/marker/open_triangle.rb +27 -0
- data/lib/ea/svg/ea_emitter/marker/package_import.rb +39 -0
- data/lib/ea/svg/ea_emitter/marker/plus.rb +40 -0
- data/lib/ea/svg/ea_emitter/marker/registry.rb +42 -0
- data/lib/ea/svg/ea_emitter/marker.rb +37 -0
- data/lib/ea/svg/ea_emitter/markers.rb +351 -64
- data/lib/ea/svg/ea_emitter/render_context.rb +52 -0
- data/lib/ea/svg/ea_emitter/style.rb +15 -0
- data/lib/ea/svg/ea_emitter/text_renderer.rb +92 -0
- data/lib/ea/svg/ea_emitter.rb +33 -11
- data/lib/ea/svg/parity/checker.rb +105 -0
- data/lib/ea/svg/parity/source.rb +59 -0
- data/lib/ea/svg/parity/suite.rb +113 -0
- data/lib/ea/svg/parity.rb +14 -0
- data/lib/ea/svg.rb +2 -15
- data/lib/ea/theme/definition.rb +176 -0
- data/lib/ea/theme/loader.rb +125 -0
- data/lib/ea/theme/registry.rb +96 -0
- data/lib/ea/theme.rb +37 -0
- data/lib/ea/transformations.rb +5 -88
- data/lib/ea/version.rb +4 -1
- data/lib/ea.rb +14 -4
- data/lib/tasks/svg_bench.rake +87 -0
- data/lutaml-uml-0.5.1.gem +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes-list.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-2-gradients.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-3-colors.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance-fonts.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-5-behavior.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-6-sequence.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-2-objects.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-3-links.png +0 -0
- metadata +449 -26
- data/lib/ea/diagram/configuration.rb +0 -379
- data/lib/ea/diagram/element_renderers/base_renderer.rb +0 -77
- data/lib/ea/diagram/element_renderers/class_renderer.rb +0 -323
- data/lib/ea/diagram/element_renderers/connector_renderer.rb +0 -41
- data/lib/ea/diagram/element_renderers/package_renderer.rb +0 -61
- data/lib/ea/diagram/element_renderers.rb +0 -43
- data/lib/ea/diagram/extractor.rb +0 -566
- data/lib/ea/diagram/layout_engine.rb +0 -170
- data/lib/ea/diagram/path_builder.rb +0 -202
- data/lib/ea/diagram/style_parser.rb +0 -42
- data/lib/ea/diagram/style_resolver.rb +0 -291
- data/lib/ea/diagram/svg_renderer.rb +0 -274
- data/lib/ea/diagram/util.rb +0 -73
- data/lib/ea/svg/bounds_calculator.rb +0 -74
- data/lib/ea/svg/connector_path.rb +0 -138
- data/lib/ea/svg/element_box.rb +0 -256
- data/lib/ea/svg/renderer.rb +0 -77
- data/lib/ea/svg/style_resolver.rb +0 -72
- data/lib/ea/transformations/configuration.rb +0 -333
- data/lib/ea/transformations/format_registry.rb +0 -366
- data/lib/ea/transformations/parsers/base_parser.rb +0 -482
- data/lib/ea/transformations/parsers/qea_parser.rb +0 -401
- data/lib/ea/transformations/parsers/xmi_parser.rb +0 -243
- data/lib/ea/transformations/transformation_engine.rb +0 -390
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# TODO-D 87: Reverse-engineer EA's InternalTechnologies encryption
|
|
2
|
+
|
|
3
|
+
## Status: open (encryption scheme unidentified)
|
|
4
|
+
|
|
5
|
+
EA's `InternalTechnologies/*.xml` files (66 files including
|
|
6
|
+
`GML_Tech.xml`) are stored in an encrypted/compressed format.
|
|
7
|
+
These contain stereotype icon definitions for built-in technologies
|
|
8
|
+
(GML, UML, SysML, BPMN, etc.) — including the FeatureType icon
|
|
9
|
+
needed for the polygon -4 parity gap.
|
|
10
|
+
|
|
11
|
+
## File format analysis
|
|
12
|
+
|
|
13
|
+
- File: GML_Tech.xml, 3076 bytes
|
|
14
|
+
- First bytes: 30 c6 3c f8 e4 d6 4b fd e0 dd 36 f5 57 84 8d 7b
|
|
15
|
+
- NOT standard compression (zip/gzip/zlib headers absent)
|
|
16
|
+
- NOT valid XML
|
|
17
|
+
|
|
18
|
+
## Hypotheses tested (all FAILED)
|
|
19
|
+
|
|
20
|
+
| Approach | Result |
|
|
21
|
+
|---|---|
|
|
22
|
+
| Single-byte XOR (256 keys) | No valid `<?xml` start |
|
|
23
|
+
| Multi-byte XOR assuming `<?xml version=` start | Key derives but doesn't repeat |
|
|
24
|
+
| zlib inflate at offsets 0-63 with wbits -15/-14/15/31/47 | No valid output |
|
|
25
|
+
| Byte rotation then zlib | No valid output |
|
|
26
|
+
| Byte subtraction (delta 1-255) then zlib | No valid output |
|
|
27
|
+
| XOR with position index | No valid output |
|
|
28
|
+
| Position-reversed XOR | No valid output |
|
|
29
|
+
| Add position modulo 256 | No valid output |
|
|
30
|
+
|
|
31
|
+
## Byte frequency analysis
|
|
32
|
+
|
|
33
|
+
Byte distribution at position mod 4 is fairly uniform (each byte
|
|
34
|
+
value appears 7-9 times per position). This is consistent with
|
|
35
|
+
**strong encryption** (AES, RC4, etc.) rather than simple XOR.
|
|
36
|
+
|
|
37
|
+
## EA.exe binary analysis
|
|
38
|
+
|
|
39
|
+
Located `MDGTechnology.cpp` debug tag at offset 0x4584684 in
|
|
40
|
+
EA.exe. Found references to `CryptEncrypt`/`CryptDecrypt` Windows
|
|
41
|
+
APIs and `aes_encrypt`/`aes_decrypt` SQL functions.
|
|
42
|
+
|
|
43
|
+
Searched EA.exe (70MB binary) for plaintext GML technology
|
|
44
|
+
content (`<MDG.Technology`, `ApplicationSchema`, `GML::FeatureType`,
|
|
45
|
+
`FeatureType`) — **zero matches**. The plaintext is NOT embedded
|
|
46
|
+
in the binary.
|
|
47
|
+
|
|
48
|
+
Extracted 19MB `.rsrc` section via `wrestool`. Contains many
|
|
49
|
+
`BSTRING` resources (UI strings, etc.) but none contain MDG
|
|
50
|
+
technology XML.
|
|
51
|
+
|
|
52
|
+
## Decryption options (none trivial)
|
|
53
|
+
|
|
54
|
+
1. **Run EA via Wine** to call the COM API:
|
|
55
|
+
`Repository.GetTechnologyByClassID(...)` then export. Requires
|
|
56
|
+
CrossOver/Wine GUI session — non-trivial setup.
|
|
57
|
+
|
|
58
|
+
2. **Ghidra/IDA disassembly** of MDGTechnology.cpp routine:
|
|
59
|
+
locate the decryption function, identify the algorithm and
|
|
60
|
+
hardcoded key. Requires reverse-engineering expertise and
|
|
61
|
+
10+ hours of analysis.
|
|
62
|
+
|
|
63
|
+
3. **Debugger capture**: run EA under `winedbg`, set breakpoint
|
|
64
|
+
at file-read for GML_Tech.xml, trace until plaintext appears
|
|
65
|
+
in memory, dump it. Requires Wine debugging setup.
|
|
66
|
+
|
|
67
|
+
4. **Side-channel acquisition**: ask Sparx Systems support for
|
|
68
|
+
the technology definition (they may provide it).
|
|
69
|
+
|
|
70
|
+
## Recommendation
|
|
71
|
+
|
|
72
|
+
The polygon -4 parity gap is small (4 missing stereotype
|
|
73
|
+
decorator icons across 188 diagrams). The effort to reverse-
|
|
74
|
+
engineer EA's encryption significantly exceeds the value of
|
|
75
|
+
closing this gap.
|
|
76
|
+
|
|
77
|
+
Recommend: DEFER this work until either:
|
|
78
|
+
- A user provides plaintext MDG exports from EA
|
|
79
|
+
- The `ea` gem adds Wine-based extraction as an optional feature
|
|
80
|
+
- A security researcher publishes the EA encryption scheme
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Examples parity report (2026-07-28)
|
|
2
|
+
|
|
3
|
+
`rake svg:examples` benches every QEA in `examples/qea/` against
|
|
4
|
+
its matching exports/Images directory.
|
|
5
|
+
|
|
6
|
+
## Headline
|
|
7
|
+
|
|
8
|
+
| Example | Matched | Perfect | Notes |
|
|
9
|
+
|---------|---------|---------|-------|
|
|
10
|
+
| simple | 2/2 | **2** | 100% parity |
|
|
11
|
+
| ArcGISWorkspace_template | 5/6 | 5 | Workspace diagram has decorative icons |
|
|
12
|
+
| basic | 19/22 | 8 | Visibility icons + Object instance format missing |
|
|
13
|
+
| test | 1/2 | 1 | Test Model diagram needs visibility icons |
|
|
14
|
+
|
|
15
|
+
**15 of 27 renderable example diagrams are at 100% parity.**
|
|
16
|
+
|
|
17
|
+
## Per-example breakdown
|
|
18
|
+
|
|
19
|
+
### simple.qea — 100% ✓
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
simple 2/2 matched
|
|
23
|
+
rect ours=8 ref=8 delta=0
|
|
24
|
+
path ours=3 ref=3 delta=0
|
|
25
|
+
polygon ours=12 ref=12 delta=0
|
|
26
|
+
text ours=22 ref=22 delta=0
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Both diagrams (`Simple Package Diagram`, `Simple Class Diagram`)
|
|
30
|
+
render byte-identical element counts.
|
|
31
|
+
|
|
32
|
+
### ArcGISWorkspace_template — 5/6 perfect
|
|
33
|
+
|
|
34
|
+
Only `ArcGIS Workspace` diagram has deltas (-2 rect, -7 path).
|
|
35
|
+
The 7 missing paths are decorative "data icon" paths (small
|
|
36
|
+
horizontal lines + dots) inside one element's attribute
|
|
37
|
+
compartment. Canvas height calc is also slightly off (641 vs 600).
|
|
38
|
+
|
|
39
|
+
### basic.qea — 8/22 perfect, 19/22 within tolerance
|
|
40
|
+
|
|
41
|
+
**Perfect diagrams:**
|
|
42
|
+
- Package Contents
|
|
43
|
+
- Package Dependencies
|
|
44
|
+
- Package B
|
|
45
|
+
- Basic Class Diagram with Multiplicities
|
|
46
|
+
- Signals
|
|
47
|
+
- Two Level Class Type Hierarchy with Attributes
|
|
48
|
+
- Two Level Class Composition Hierarchy with Attributes
|
|
49
|
+
- Composition with Substitution
|
|
50
|
+
|
|
51
|
+
**Remaining gaps (concentrated in 3 areas):**
|
|
52
|
+
|
|
53
|
+
1. **Visibility icons** (Test Model diagram in test.qea +
|
|
54
|
+
Package Imports + Object with Value Specifications in basic):
|
|
55
|
+
EA renders 3 elements per attribute row (outer rect 11x14 +
|
|
56
|
+
inner rect 11x4 + horizontal divider path). Implementing this
|
|
57
|
+
would close ~25 rects and ~15 paths across examples.
|
|
58
|
+
|
|
59
|
+
2. **Object instance format** (Objects as Instances of Classes +
|
|
60
|
+
Object with Value Specifications): EA renders
|
|
61
|
+
`Object 01 / roleOne: Class A` and `attribute = value` slot
|
|
62
|
+
format. We render the qualified class name only.
|
|
63
|
+
|
|
64
|
+
3. **Decorative data icons** (ArcGIS Workspace): "Hamburger menu"
|
|
65
|
+
icons (3 horizontal lines + dots). Specific to ArcGIS template.
|
|
66
|
+
|
|
67
|
+
### test.qea — 1/2 perfect
|
|
68
|
+
|
|
69
|
+
- `TestSchema` diagram: 100%
|
|
70
|
+
- `Test Model` diagram: needs visibility icons + Package element
|
|
71
|
+
attribute rendering
|
|
72
|
+
|
|
73
|
+
## How to run
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
bundle exec rake svg:examples
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Outputs per-example bench in a single table. Run after every
|
|
80
|
+
renderer change to catch regressions in any example.
|
|
81
|
+
|
|
82
|
+
## Architecture
|
|
83
|
+
|
|
84
|
+
The `rake svg:examples` task auto-discovers QEA files in
|
|
85
|
+
`examples/qea/` and matches them with ref directories in
|
|
86
|
+
`examples/exports/<name>/{images,Images}/`. Uses the existing
|
|
87
|
+
`Ea::Svg::Parity::Suite` with `Ea::Sources::Qea::IdNormalizer`
|
|
88
|
+
for diagram-id → SVG-filename resolution.
|
|
@@ -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
|