@cda/adapter-xma 0.1.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 (78) hide show
  1. package/README.md +192 -0
  2. package/dist/diagnostics/diagnostics.d.ts +20 -0
  3. package/dist/diagnostics/diagnostics.d.ts.map +1 -0
  4. package/dist/diagnostics/diagnostics.js +19 -0
  5. package/dist/diagnostics/diagnostics.js.map +1 -0
  6. package/dist/diagnostics/errors.d.ts +13 -0
  7. package/dist/diagnostics/errors.d.ts.map +1 -0
  8. package/dist/diagnostics/errors.js +20 -0
  9. package/dist/diagnostics/errors.js.map +1 -0
  10. package/dist/geometry/bendpoints.d.ts +33 -0
  11. package/dist/geometry/bendpoints.d.ts.map +1 -0
  12. package/dist/geometry/bendpoints.js +44 -0
  13. package/dist/geometry/bendpoints.js.map +1 -0
  14. package/dist/geometry/geometry.d.ts +36 -0
  15. package/dist/geometry/geometry.d.ts.map +1 -0
  16. package/dist/geometry/geometry.js +41 -0
  17. package/dist/geometry/geometry.js.map +1 -0
  18. package/dist/index.d.ts +5 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +3 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/infrastructure/id-allocator.d.ts +34 -0
  23. package/dist/infrastructure/id-allocator.d.ts.map +1 -0
  24. package/dist/infrastructure/id-allocator.js +54 -0
  25. package/dist/infrastructure/id-allocator.js.map +1 -0
  26. package/dist/infrastructure/xml-writer.d.ts +20 -0
  27. package/dist/infrastructure/xml-writer.d.ts.map +1 -0
  28. package/dist/infrastructure/xml-writer.js +54 -0
  29. package/dist/infrastructure/xml-writer.js.map +1 -0
  30. package/dist/mapping/element-mapping.d.ts +31 -0
  31. package/dist/mapping/element-mapping.d.ts.map +1 -0
  32. package/dist/mapping/element-mapping.js +112 -0
  33. package/dist/mapping/element-mapping.js.map +1 -0
  34. package/dist/mapping/relationship-mapping.d.ts +21 -0
  35. package/dist/mapping/relationship-mapping.d.ts.map +1 -0
  36. package/dist/mapping/relationship-mapping.js +45 -0
  37. package/dist/mapping/relationship-mapping.js.map +1 -0
  38. package/dist/mapping/scheme-mapping.d.ts +38 -0
  39. package/dist/mapping/scheme-mapping.d.ts.map +1 -0
  40. package/dist/mapping/scheme-mapping.js +39 -0
  41. package/dist/mapping/scheme-mapping.js.map +1 -0
  42. package/dist/mapping/visual-mapping.d.ts +24 -0
  43. package/dist/mapping/visual-mapping.d.ts.map +1 -0
  44. package/dist/mapping/visual-mapping.js +39 -0
  45. package/dist/mapping/visual-mapping.js.map +1 -0
  46. package/dist/serializer/document-writer.d.ts +19 -0
  47. package/dist/serializer/document-writer.d.ts.map +1 -0
  48. package/dist/serializer/document-writer.js +126 -0
  49. package/dist/serializer/document-writer.js.map +1 -0
  50. package/dist/serializer/graphical-writer.d.ts +25 -0
  51. package/dist/serializer/graphical-writer.d.ts.map +1 -0
  52. package/dist/serializer/graphical-writer.js +287 -0
  53. package/dist/serializer/graphical-writer.js.map +1 -0
  54. package/dist/serializer/profile-values.d.ts +8 -0
  55. package/dist/serializer/profile-values.d.ts.map +1 -0
  56. package/dist/serializer/profile-values.js +25 -0
  57. package/dist/serializer/profile-values.js.map +1 -0
  58. package/dist/serializer/relationship-writer.d.ts +15 -0
  59. package/dist/serializer/relationship-writer.d.ts.map +1 -0
  60. package/dist/serializer/relationship-writer.js +83 -0
  61. package/dist/serializer/relationship-writer.js.map +1 -0
  62. package/dist/serializer/rtf.d.ts +9 -0
  63. package/dist/serializer/rtf.d.ts.map +1 -0
  64. package/dist/serializer/rtf.js +50 -0
  65. package/dist/serializer/rtf.js.map +1 -0
  66. package/dist/serializer/semantic-writer.d.ts +36 -0
  67. package/dist/serializer/semantic-writer.d.ts.map +1 -0
  68. package/dist/serializer/semantic-writer.js +91 -0
  69. package/dist/serializer/semantic-writer.js.map +1 -0
  70. package/dist/serializer/serialize-xma.d.ts +29 -0
  71. package/dist/serializer/serialize-xma.d.ts.map +1 -0
  72. package/dist/serializer/serialize-xma.js +80 -0
  73. package/dist/serializer/serialize-xma.js.map +1 -0
  74. package/dist/serializer/view-writer.d.ts +26 -0
  75. package/dist/serializer/view-writer.d.ts.map +1 -0
  76. package/dist/serializer/view-writer.js +147 -0
  77. package/dist/serializer/view-writer.js.map +1 -0
  78. package/package.json +58 -0
package/README.md ADDED
@@ -0,0 +1,192 @@
1
+ # @cda/adapter-xma
2
+
3
+ An XMA output adapter for the [Continuous-Driven Architecture (CDA)](https://github.com/Continuous-DrivenArchitecture) ecosystem.
4
+
5
+ `@cda/adapter-xma` converts the typed `ArchiModel` produced by
6
+ [`@cda/archi-semantic-core`](https://github.com/Continuous-DrivenArchitecture/archi-semantic-core)
7
+ into an XMA document, preserving both **semantics** (elements, relationships,
8
+ names, documentation) and **presentation intent** (views, node geometry,
9
+ default visual styling, graphical relationships, bendpoints, Notes, Groups).
10
+
11
+ ```
12
+ .archimate
13
+
14
+
15
+ @cda/archi-semantic-core (parseArchiModel)
16
+
17
+
18
+ ArchiModel
19
+
20
+
21
+ @cda/adapter-xma (serializeXma)
22
+
23
+
24
+ .xma
25
+ ```
26
+
27
+ This package is a **pure output-format adapter**. It does not re-parse
28
+ `.archimate` XML, does not duplicate `archi-semantic-core`'s parsing logic,
29
+ and does not use the ArchiMate Open Exchange format as an intermediate
30
+ representation (doing so would lose native presentation fidelity). It
31
+ consumes `archi-semantic-core`'s public `ArchiModel` contract only.
32
+
33
+ The runtime is dependency-light and avoids Node-only APIs (`fs`, `path`,
34
+ `process`), so it can run in a browser — e.g. a future client-side CDA
35
+ converter.
36
+
37
+ ## Installation
38
+
39
+ ```
40
+ npm install @cda/archi-semantic-core @cda/adapter-xma
41
+ ```
42
+
43
+ ## Usage
44
+
45
+ ```ts
46
+ import { parseArchiModel } from '@cda/archi-semantic-core';
47
+ import { serializeXma } from '@cda/adapter-xma';
48
+
49
+ const model = parseArchiModel(archimateXml);
50
+
51
+ const xma = serializeXma(model, {
52
+ language: 'en',
53
+ });
54
+ ```
55
+
56
+ `serializeXma` is **strict by default**: if the model contains a construct
57
+ that would cause semantic or presentation loss (an unmapped element type, an
58
+ unconfirmed relationship, more than one view, incomplete geometry, ...) it
59
+ throws `XmaSerializationError` carrying a structured diagnostic for every
60
+ problem found, rather than silently dropping content or fabricating an
61
+ approximate result.
62
+
63
+ To preview what is and isn't supported without throwing:
64
+
65
+ ```ts
66
+ import { inspectXmaSupport } from '@cda/adapter-xma';
67
+
68
+ const diagnostics = inspectXmaSupport(model);
69
+ for (const d of diagnostics) {
70
+ console.log(`[${d.severity}] ${d.code}: ${d.message}`);
71
+ }
72
+ ```
73
+
74
+ ### Options
75
+
76
+ ```ts
77
+ interface XmaSerializeOptions {
78
+ /** Applied to every xml:lang and the default MM_Language. Default: 'en'. Never inferred from element names. */
79
+ language?: string;
80
+ /** The root MM_ModelPackage's display name. Default: a neutral placeholder — no machine/user identity is ever fabricated. */
81
+ packageName?: string;
82
+ /** The model's display name. Default: `model.metadata.name`. */
83
+ modelName?: string;
84
+ }
85
+ ```
86
+
87
+ ## Support matrix
88
+
89
+ This is **initial, evidence-backed XMA serialization support** — not a
90
+ complete, universal XMA converter. Everything below was confirmed against
91
+ two reference `.archimate`/`.xma` fixture pairs (see
92
+ [`tests/fixtures/README.md`](tests/fixtures/README.md)); nothing here is
93
+ extrapolated beyond that evidence.
94
+
95
+ ### Supported
96
+
97
+ - All 60 confirmed ArchiMate element type mappings (Strategy, Business,
98
+ Application, Technology, Physical, Motivation, Implementation & Migration,
99
+ Composite), with confirmed scheme/collection placement and default icon
100
+ decoration presence.
101
+ - Element and view names, and documentation (as RTF profile values).
102
+ - A single ArchiMate view per model: node geometry (exact ×3 scale),
103
+ default per-category fill colors, line color, opacity, and font.
104
+ - Notes and Groups (as `ArchiMate:ViewGraphic`), including Group
105
+ documentation.
106
+ - Three confirmed semantic relationship mappings and their graphical
107
+ representation:
108
+ - `AssignmentRelationship` `BusinessActor` → `BusinessProcess`
109
+ - `ServingRelationship` `ApplicationService` → `BusinessProcess` (XMA
110
+ calls this `...Use`, not `...Serving`)
111
+ - `FlowRelationship` `BusinessProcess` → `BusinessProcess`
112
+ - Manually routed connection bendpoints (source/target-relative offsets,
113
+ cross-checked against each other).
114
+ - A configurable output language, applied consistently — never inferred
115
+ from element names.
116
+ - Direct, lossless mapping of explicit Archi `fillColor`/`lineColor`
117
+ (hex → RGB) and `fontName` overrides, where the source field maps onto
118
+ the exact same structural XMA slot.
119
+
120
+ ### Not yet guaranteed
121
+
122
+ - Relationship type/source/target combinations beyond the three confirmed
123
+ above (reported as a diagnostic, not silently dropped or guessed).
124
+ - More than one view per model (reported as a diagnostic).
125
+ - Nested diagram objects, `DiagramModelReference` ("insert view as
126
+ reference"), and purely visual (non-semantic) connections.
127
+ - Junctions, profiles/specializations, and arbitrary model properties.
128
+ - Explicit font size, bold/italic, line width, font color, or connector
129
+ line color overrides (reported as diagnostics; the confirmed defaults are
130
+ used instead).
131
+ - Manual connector anchor metadata (`mm_fromx`/`mm_fromy`/`mm_tox`/`mm_toy`)
132
+ — only one fixture exhibited these attributes, not enough evidence to
133
+ derive a general formula or confirm they're required for import. They are
134
+ deliberately omitted rather than guessed; see
135
+ `src/serializer/graphical-writer.ts`.
136
+
137
+ ## Architecture
138
+
139
+ ```
140
+ src/
141
+ index.ts public API
142
+
143
+ serializer/ XmlElement tree construction
144
+ serialize-xma.ts orchestrator: plan -> diagnostics/throw -> render
145
+ document-writer.ts MM_Document skeleton, scheme/folder nesting
146
+ semantic-writer.ts per-scheme element collections
147
+ relationship-writer.ts semantic relationship elements
148
+ view-writer.ts AllView: ViewGraphics + RefObjects, validation
149
+ graphical-writer.ts Canvas / MM_Node / MM_DirectedRel
150
+ profile-values.ts MM_ProfileValues (nm/doc) builder
151
+ rtf.ts dependency-free RTF escaping
152
+
153
+ mapping/ immutable mapping DATA (never switch statements)
154
+ element-mapping.ts 60 confirmed Archi type -> XMA type/scheme/collection
155
+ relationship-mapping.ts 3 confirmed (type, source, target) -> XMA relationship
156
+ scheme-mapping.ts scheme container / folder-nesting metadata
157
+ visual-mapping.ts default fill/line colors, font, opacity
158
+
159
+ geometry/
160
+ geometry.ts the ×3 scale rule
161
+ bendpoints.ts bendpoint offset -> absolute point resolution
162
+
163
+ infrastructure/
164
+ id-allocator.ts deterministic numeric XMA id allocation
165
+ xml-writer.ts typed XmlElement tree -> deterministic XML string
166
+
167
+ diagnostics/
168
+ diagnostics.ts XmaDiagnostic, DiagnosticCollector
169
+ errors.ts XmaSerializationError
170
+ ```
171
+
172
+ Every generated XMA id is a deterministic, strictly-increasing integer
173
+ driven by traversal order over the (order-preserving) `ArchiModel` — never
174
+ `Math.random()`, `Date.now()`, or a UUID. Archi's own string ids are never
175
+ reused as XMA ids.
176
+
177
+ Output is fully deterministic: the same `ArchiModel` and options always
178
+ produce byte-identical XML (no timestamps, host names, or environment
179
+ values are ever embedded).
180
+
181
+ ## Development
182
+
183
+ ```
184
+ npm install
185
+ npm run typecheck
186
+ npm run build
187
+ npm test
188
+ ```
189
+
190
+ ## License
191
+
192
+ MIT
@@ -0,0 +1,20 @@
1
+ export type XmaDiagnosticSeverity = 'error' | 'warning';
2
+ export interface XmaDiagnostic {
3
+ /** Stable machine-readable code, e.g. "unsupported-element-type". */
4
+ code: string;
5
+ severity: XmaDiagnosticSeverity;
6
+ message: string;
7
+ /** Id of the offending source entity (Archi element/relationship/view/diagram id), when applicable. */
8
+ entityId?: string;
9
+ /** Kind of the offending source entity, e.g. "ArchiElement", "ArchiRelationship". */
10
+ entityType?: string;
11
+ }
12
+ /** Accumulates diagnostics during a single serialization pass. */
13
+ export declare class DiagnosticCollector {
14
+ private readonly items;
15
+ error(diagnostic: Omit<XmaDiagnostic, 'severity'>): void;
16
+ warning(diagnostic: Omit<XmaDiagnostic, 'severity'>): void;
17
+ get all(): XmaDiagnostic[];
18
+ get hasErrors(): boolean;
19
+ }
20
+ //# sourceMappingURL=diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/diagnostics/diagnostics.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,SAAS,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,qBAAqB,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,uGAAuG;IACvG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,kEAAkE;AAClE,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;IAE7C,KAAK,CAAC,UAAU,EAAE,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,GAAG,IAAI;IAIxD,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,GAAG,IAAI;IAI1D,IAAI,GAAG,IAAI,aAAa,EAAE,CAEzB;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;CACF"}
@@ -0,0 +1,19 @@
1
+ /** Accumulates diagnostics during a single serialization pass. */
2
+ export class DiagnosticCollector {
3
+ constructor() {
4
+ this.items = [];
5
+ }
6
+ error(diagnostic) {
7
+ this.items.push({ ...diagnostic, severity: 'error' });
8
+ }
9
+ warning(diagnostic) {
10
+ this.items.push({ ...diagnostic, severity: 'warning' });
11
+ }
12
+ get all() {
13
+ return [...this.items];
14
+ }
15
+ get hasErrors() {
16
+ return this.items.some((d) => d.severity === 'error');
17
+ }
18
+ }
19
+ //# sourceMappingURL=diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/diagnostics/diagnostics.ts"],"names":[],"mappings":"AAaA,kEAAkE;AAClE,MAAM,OAAO,mBAAmB;IAAhC;QACmB,UAAK,GAAoB,EAAE,CAAC;IAiB/C,CAAC;IAfC,KAAK,CAAC,UAA2C;QAC/C,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,OAAO,CAAC,UAA2C;QACjD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,GAAG;QACL,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC;IACxD,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ import type { XmaDiagnostic } from './diagnostics.js';
2
+ /**
3
+ * Thrown by `serializeXma` whenever serializing would silently lose
4
+ * semantics or presentation intent. Carries the full structured diagnostic
5
+ * list (not just the first failure) so callers can report everything wrong
6
+ * in one pass — see `inspectXmaSupport` to obtain the same list without
7
+ * throwing.
8
+ */
9
+ export declare class XmaSerializationError extends Error {
10
+ readonly diagnostics: XmaDiagnostic[];
11
+ constructor(diagnostics: XmaDiagnostic[]);
12
+ }
13
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/diagnostics/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD;;;;;;GAMG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,WAAW,EAAE,aAAa,EAAE,CAAC;gBAE1B,WAAW,EAAE,aAAa,EAAE;CAYzC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Thrown by `serializeXma` whenever serializing would silently lose
3
+ * semantics or presentation intent. Carries the full structured diagnostic
4
+ * list (not just the first failure) so callers can report everything wrong
5
+ * in one pass — see `inspectXmaSupport` to obtain the same list without
6
+ * throwing.
7
+ */
8
+ export class XmaSerializationError extends Error {
9
+ constructor(diagnostics) {
10
+ const errorCount = diagnostics.filter((d) => d.severity === 'error').length;
11
+ super(`XMA serialization failed: ${errorCount} unsupported construct(s) would cause semantic or presentation loss. ` +
12
+ diagnostics
13
+ .filter((d) => d.severity === 'error')
14
+ .map((d) => `[${d.code}] ${d.message}`)
15
+ .join('; '));
16
+ this.name = 'XmaSerializationError';
17
+ this.diagnostics = diagnostics;
18
+ }
19
+ }
20
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/diagnostics/errors.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAG9C,YAAY,WAA4B;QACtC,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,MAAM,CAAC;QAC5E,KAAK,CACH,6BAA6B,UAAU,uEAAuE;YAC5G,WAAW;iBACR,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC;iBACrC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;iBACtC,IAAI,CAAC,IAAI,CAAC,CAChB,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;CACF"}
@@ -0,0 +1,33 @@
1
+ import type { Point, Rect } from './geometry.js';
2
+ export type BendpointAgreement = 'both' | 'source-only' | 'target-only';
3
+ export interface BendpointResolution {
4
+ /** Resolved absolute point, in Archi (pre-scale) coordinate space. */
5
+ point: Point;
6
+ agreement: BendpointAgreement;
7
+ /** Present only when both source- and target-relative forms were available but disagreed materially. */
8
+ mismatch?: {
9
+ fromSource: Point;
10
+ fromTarget: Point;
11
+ };
12
+ }
13
+ /**
14
+ * Resolves a single Archi bendpoint (stored as offsets from the source and
15
+ * target diagram-object centers) to an absolute point in Archi coordinate
16
+ * space.
17
+ *
18
+ * Confirmed fixture: source bounds x=48,y=180,w=120,h=55 (center 108,207),
19
+ * target bounds x=204,y=276,w=120,h=55 (center 264,303), bendpoint
20
+ * startX=-12,startY=93,endX=-168,endY=-3 resolves to absolute (96, 300) via
21
+ * either offset.
22
+ *
23
+ * When both offsets are present, they are cross-checked against each other;
24
+ * a material disagreement is reported via `mismatch` rather than silently
25
+ * resolved, so the caller can surface a diagnostic instead of guessing.
26
+ */
27
+ export declare function resolveBendpoint(bendpoint: {
28
+ startX: number | null;
29
+ startY: number | null;
30
+ endX: number | null;
31
+ endY: number | null;
32
+ }, sourceBounds: Rect, targetBounds: Rect): BendpointResolution | null;
33
+ //# sourceMappingURL=bendpoints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bendpoints.d.ts","sourceRoot":"","sources":["../../src/geometry/bendpoints.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAKjD,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,aAAa,GAAG,aAAa,CAAC;AAExE,MAAM,WAAW,mBAAmB;IAClC,sEAAsE;IACtE,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,kBAAkB,CAAC;IAC9B,wGAAwG;IACxG,QAAQ,CAAC,EAAE;QACT,UAAU,EAAE,KAAK,CAAC;QAClB,UAAU,EAAE,KAAK,CAAC;KACnB,CAAC;CACH;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE;IAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EACrG,YAAY,EAAE,IAAI,EAClB,YAAY,EAAE,IAAI,GACjB,mBAAmB,GAAG,IAAI,CAgC5B"}
@@ -0,0 +1,44 @@
1
+ import { centerOf } from './geometry.js';
2
+ const AGREEMENT_EPSILON = 0.01;
3
+ /**
4
+ * Resolves a single Archi bendpoint (stored as offsets from the source and
5
+ * target diagram-object centers) to an absolute point in Archi coordinate
6
+ * space.
7
+ *
8
+ * Confirmed fixture: source bounds x=48,y=180,w=120,h=55 (center 108,207),
9
+ * target bounds x=204,y=276,w=120,h=55 (center 264,303), bendpoint
10
+ * startX=-12,startY=93,endX=-168,endY=-3 resolves to absolute (96, 300) via
11
+ * either offset.
12
+ *
13
+ * When both offsets are present, they are cross-checked against each other;
14
+ * a material disagreement is reported via `mismatch` rather than silently
15
+ * resolved, so the caller can surface a diagnostic instead of guessing.
16
+ */
17
+ export function resolveBendpoint(bendpoint, sourceBounds, targetBounds) {
18
+ const hasSourceOffset = bendpoint.startX !== null && bendpoint.startY !== null;
19
+ const hasTargetOffset = bendpoint.endX !== null && bendpoint.endY !== null;
20
+ if (!hasSourceOffset && !hasTargetOffset) {
21
+ return null;
22
+ }
23
+ const sourceCenter = centerOf(sourceBounds);
24
+ const targetCenter = centerOf(targetBounds);
25
+ const fromSource = hasSourceOffset
26
+ ? { x: sourceCenter.x + bendpoint.startX, y: sourceCenter.y + bendpoint.startY }
27
+ : null;
28
+ const fromTarget = hasTargetOffset
29
+ ? { x: targetCenter.x + bendpoint.endX, y: targetCenter.y + bendpoint.endY }
30
+ : null;
31
+ if (fromSource && fromTarget) {
32
+ const deltaX = Math.abs(fromSource.x - fromTarget.x);
33
+ const deltaY = Math.abs(fromSource.y - fromTarget.y);
34
+ if (deltaX > AGREEMENT_EPSILON || deltaY > AGREEMENT_EPSILON) {
35
+ return { point: fromSource, agreement: 'both', mismatch: { fromSource, fromTarget } };
36
+ }
37
+ return { point: fromSource, agreement: 'both' };
38
+ }
39
+ if (fromSource) {
40
+ return { point: fromSource, agreement: 'source-only' };
41
+ }
42
+ return { point: fromTarget, agreement: 'target-only' };
43
+ }
44
+ //# sourceMappingURL=bendpoints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bendpoints.js","sourceRoot":"","sources":["../../src/geometry/bendpoints.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAe/B;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,gBAAgB,CAC9B,SAAqG,EACrG,YAAkB,EAClB,YAAkB;IAElB,MAAM,eAAe,GAAG,SAAS,CAAC,MAAM,KAAK,IAAI,IAAI,SAAS,CAAC,MAAM,KAAK,IAAI,CAAC;IAC/E,MAAM,eAAe,GAAG,SAAS,CAAC,IAAI,KAAK,IAAI,IAAI,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC;IAE3E,IAAI,CAAC,eAAe,IAAI,CAAC,eAAe,EAAE,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,YAAY,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC5C,MAAM,YAAY,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;IAE5C,MAAM,UAAU,GAAiB,eAAe;QAC9C,CAAC,CAAC,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC,GAAI,SAAS,CAAC,MAAiB,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC,GAAI,SAAS,CAAC,MAAiB,EAAE;QACxG,CAAC,CAAC,IAAI,CAAC;IACT,MAAM,UAAU,GAAiB,eAAe;QAC9C,CAAC,CAAC,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC,GAAI,SAAS,CAAC,IAAe,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC,GAAI,SAAS,CAAC,IAAe,EAAE;QACpG,CAAC,CAAC,IAAI,CAAC;IAET,IAAI,UAAU,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QACrD,IAAI,MAAM,GAAG,iBAAiB,IAAI,MAAM,GAAG,iBAAiB,EAAE,CAAC;YAC7D,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,EAAE,CAAC;QACxF,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAClD,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;IACzD,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,UAAmB,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;AAClE,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Confirmed across all catalogue shapes and the relationship fixture: XMA
3
+ * geometry is Archi geometry uniformly scaled by 3 (x, y, width, height,
4
+ * and bendpoint coordinates alike).
5
+ */
6
+ export declare const XMA_SCALE = 3;
7
+ export interface Rect {
8
+ x: number;
9
+ y: number;
10
+ width: number;
11
+ height: number;
12
+ }
13
+ export declare function scaleValue(archiValue: number): number;
14
+ export declare function scaleRect(bounds: Rect): Rect;
15
+ export interface Point {
16
+ x: number;
17
+ y: number;
18
+ }
19
+ export declare function scalePoint(point: Point): Point;
20
+ /**
21
+ * Rect center, floored to a whole pixel — confirmed against the proven
22
+ * bendpoint fixture: a 55px-tall shape's center is Archi's own `180 + 55/2`
23
+ * truncated to `207`, not `207.5`. Using the exact fraction here would
24
+ * throw off every bendpoint resolved against an odd-height/width shape.
25
+ */
26
+ export declare function centerOf(bounds: Rect): Point;
27
+ interface NullableBounds {
28
+ x: number | null;
29
+ y: number | null;
30
+ width: number | null;
31
+ height: number | null;
32
+ }
33
+ /** Type guard: true when every bounds field is set, narrowing to a usable `Rect`. */
34
+ export declare function hasCompleteBounds(bounds: NullableBounds | null): bounds is Rect;
35
+ export {};
36
+ //# sourceMappingURL=geometry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../../src/geometry/geometry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,SAAS,IAAI,CAAC;AAE3B,MAAM,WAAW,IAAI;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,IAAI,GAAG,IAAI,CAO5C;AAED,MAAM,WAAW,KAAK;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAE9C;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,IAAI,GAAG,KAAK,CAK5C;AAED,UAAU,cAAc;IACtB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,GAAG,MAAM,IAAI,IAAI,CAQ/E"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Confirmed across all catalogue shapes and the relationship fixture: XMA
3
+ * geometry is Archi geometry uniformly scaled by 3 (x, y, width, height,
4
+ * and bendpoint coordinates alike).
5
+ */
6
+ export const XMA_SCALE = 3;
7
+ export function scaleValue(archiValue) {
8
+ return archiValue * XMA_SCALE;
9
+ }
10
+ export function scaleRect(bounds) {
11
+ return {
12
+ x: scaleValue(bounds.x),
13
+ y: scaleValue(bounds.y),
14
+ width: scaleValue(bounds.width),
15
+ height: scaleValue(bounds.height),
16
+ };
17
+ }
18
+ export function scalePoint(point) {
19
+ return { x: scaleValue(point.x), y: scaleValue(point.y) };
20
+ }
21
+ /**
22
+ * Rect center, floored to a whole pixel — confirmed against the proven
23
+ * bendpoint fixture: a 55px-tall shape's center is Archi's own `180 + 55/2`
24
+ * truncated to `207`, not `207.5`. Using the exact fraction here would
25
+ * throw off every bendpoint resolved against an odd-height/width shape.
26
+ */
27
+ export function centerOf(bounds) {
28
+ return {
29
+ x: Math.floor(bounds.x + bounds.width / 2),
30
+ y: Math.floor(bounds.y + bounds.height / 2),
31
+ };
32
+ }
33
+ /** Type guard: true when every bounds field is set, narrowing to a usable `Rect`. */
34
+ export function hasCompleteBounds(bounds) {
35
+ return (bounds !== null &&
36
+ bounds.x !== null &&
37
+ bounds.y !== null &&
38
+ bounds.width !== null &&
39
+ bounds.height !== null);
40
+ }
41
+ //# sourceMappingURL=geometry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geometry.js","sourceRoot":"","sources":["../../src/geometry/geometry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAS3B,MAAM,UAAU,UAAU,CAAC,UAAkB;IAC3C,OAAO,UAAU,GAAG,SAAS,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAAY;IACpC,OAAO;QACL,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;QACvB,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;QACvB,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC;QAC/B,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC;KAClC,CAAC;AACJ,CAAC;AAOD,MAAM,UAAU,UAAU,CAAC,KAAY;IACrC,OAAO,EAAE,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAY;IACnC,OAAO;QACL,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;QAC1C,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;KAC5C,CAAC;AACJ,CAAC;AASD,qFAAqF;AACrF,MAAM,UAAU,iBAAiB,CAAC,MAA6B;IAC7D,OAAO,CACL,MAAM,KAAK,IAAI;QACf,MAAM,CAAC,CAAC,KAAK,IAAI;QACjB,MAAM,CAAC,CAAC,KAAK,IAAI;QACjB,MAAM,CAAC,KAAK,KAAK,IAAI;QACrB,MAAM,CAAC,MAAM,KAAK,IAAI,CACvB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { serializeXma, inspectXmaSupport } from './serializer/serialize-xma.js';
2
+ export type { XmaSerializeOptions } from './serializer/serialize-xma.js';
3
+ export { XmaSerializationError } from './diagnostics/errors.js';
4
+ export type { XmaDiagnostic, XmaDiagnosticSeverity } from './diagnostics/diagnostics.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAChF,YAAY,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,YAAY,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { serializeXma, inspectXmaSupport } from './serializer/serialize-xma.js';
2
+ export { XmaSerializationError } from './diagnostics/errors.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAEhF,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Deterministic numeric XMA id allocator.
3
+ *
4
+ * XMA reference documents use small sequential integer ids. We do not (and
5
+ * cannot) reproduce Archi's string ids — instead we hand out ids in strictly
6
+ * increasing order, starting from 1, driven entirely by serializer traversal
7
+ * order. As long as the traversal order over a given `ArchiModel` is stable
8
+ * (it is: every `ArchiModel` collection preserves source document order),
9
+ * the same input always yields the same ids.
10
+ *
11
+ * Never uses Math.random(), Date.now(), or any other non-deterministic or
12
+ * environment-specific source.
13
+ */
14
+ export declare class XmaIdAllocator {
15
+ private counter;
16
+ next(): number;
17
+ }
18
+ /**
19
+ * A registry mapping arbitrary string keys (Archi ids, or synthetic
20
+ * composite keys) to allocated XMA numeric ids, with reference-consistent
21
+ * reuse: asking for the same key twice returns the same id.
22
+ */
23
+ export declare class XmaIdRegistry {
24
+ private readonly allocator;
25
+ private readonly ids;
26
+ constructor(allocator: XmaIdAllocator);
27
+ /** Allocates (or returns the previously allocated) id for `key`. */
28
+ idFor(key: string): number;
29
+ /** Allocates a fresh id not tied to any lookup key (e.g. structural scaffolding elements). */
30
+ fresh(): number;
31
+ has(key: string): boolean;
32
+ get(key: string): number | undefined;
33
+ }
34
+ //# sourceMappingURL=id-allocator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id-allocator.d.ts","sourceRoot":"","sources":["../../src/infrastructure/id-allocator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAK;IAEpB,IAAI,IAAI,MAAM;CAIf;AAED;;;;GAIG;AACH,qBAAa,aAAa;IAGZ,OAAO,CAAC,QAAQ,CAAC,SAAS;IAFtC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA6B;gBAEpB,SAAS,EAAE,cAAc;IAEtD,oEAAoE;IACpE,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAU1B,8FAA8F;IAC9F,KAAK,IAAI,MAAM;IAIf,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;CAGrC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Deterministic numeric XMA id allocator.
3
+ *
4
+ * XMA reference documents use small sequential integer ids. We do not (and
5
+ * cannot) reproduce Archi's string ids — instead we hand out ids in strictly
6
+ * increasing order, starting from 1, driven entirely by serializer traversal
7
+ * order. As long as the traversal order over a given `ArchiModel` is stable
8
+ * (it is: every `ArchiModel` collection preserves source document order),
9
+ * the same input always yields the same ids.
10
+ *
11
+ * Never uses Math.random(), Date.now(), or any other non-deterministic or
12
+ * environment-specific source.
13
+ */
14
+ export class XmaIdAllocator {
15
+ constructor() {
16
+ this.counter = 0;
17
+ }
18
+ next() {
19
+ this.counter += 1;
20
+ return this.counter;
21
+ }
22
+ }
23
+ /**
24
+ * A registry mapping arbitrary string keys (Archi ids, or synthetic
25
+ * composite keys) to allocated XMA numeric ids, with reference-consistent
26
+ * reuse: asking for the same key twice returns the same id.
27
+ */
28
+ export class XmaIdRegistry {
29
+ constructor(allocator) {
30
+ this.allocator = allocator;
31
+ this.ids = new Map();
32
+ }
33
+ /** Allocates (or returns the previously allocated) id for `key`. */
34
+ idFor(key) {
35
+ const existing = this.ids.get(key);
36
+ if (existing !== undefined) {
37
+ return existing;
38
+ }
39
+ const id = this.allocator.next();
40
+ this.ids.set(key, id);
41
+ return id;
42
+ }
43
+ /** Allocates a fresh id not tied to any lookup key (e.g. structural scaffolding elements). */
44
+ fresh() {
45
+ return this.allocator.next();
46
+ }
47
+ has(key) {
48
+ return this.ids.has(key);
49
+ }
50
+ get(key) {
51
+ return this.ids.get(key);
52
+ }
53
+ }
54
+ //# sourceMappingURL=id-allocator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id-allocator.js","sourceRoot":"","sources":["../../src/infrastructure/id-allocator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,cAAc;IAA3B;QACU,YAAO,GAAG,CAAC,CAAC;IAMtB,CAAC;IAJC,IAAI;QACF,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,aAAa;IAGxB,YAA6B,SAAyB;QAAzB,cAAS,GAAT,SAAS,CAAgB;QAFrC,QAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEQ,CAAC;IAE1D,oEAAoE;IACpE,KAAK,CAAC,GAAW;QACf,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QACjC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACtB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,8FAA8F;IAC9F,KAAK;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IAC/B,CAAC;IAED,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Minimal typed XML element tree + deterministic serializer.
3
+ *
4
+ * Business logic builds `XmlElement` trees (attribute order and child order
5
+ * are explicit arrays, controlled entirely by the caller) and this module
6
+ * turns them into text. No implicit ordering, no host/timestamp-dependent
7
+ * output, no third-party XML dependency — keeps the runtime browser-safe.
8
+ */
9
+ export interface XmlElement {
10
+ tag: string;
11
+ attrs?: Array<[string, string]>;
12
+ children?: XmlElement[];
13
+ /** Leaf text content. Mutually exclusive with `children` in practice. */
14
+ text?: string;
15
+ }
16
+ export declare function element(tag: string, attrs?: Array<[string, string]>, children?: XmlElement[]): XmlElement;
17
+ export declare function textElement(tag: string, text: string, attrs?: Array<[string, string]>): XmlElement;
18
+ /** Renders a root element to a complete, deterministic XML document string. */
19
+ export declare function renderXmlDocument(root: XmlElement): string;
20
+ //# sourceMappingURL=xml-writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xml-writer.d.ts","sourceRoot":"","sources":["../../src/infrastructure/xml-writer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAChC,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;IACxB,yEAAyE;IACzE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,OAAO,CACrB,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAC/B,QAAQ,CAAC,EAAE,UAAU,EAAE,GACtB,UAAU,CAEZ;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,UAAU,CAElG;AAsCD,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAI1D"}