@dxos/diagram 0.11.1 → 0.14.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 (171) hide show
  1. package/dist/lib/chunk-parse.mjs +9406 -0
  2. package/dist/lib/chunk-parse.mjs.map +1 -0
  3. package/dist/lib/extension.mjs +204 -0
  4. package/dist/lib/extension.mjs.map +1 -0
  5. package/dist/lib/index.mjs +497 -2846
  6. package/dist/lib/index.mjs.map +1 -1
  7. package/dist/types/src/aesthetics.d.ts +12 -0
  8. package/dist/types/src/aesthetics.d.ts.map +1 -0
  9. package/dist/types/src/aesthetics.test.d.ts +2 -0
  10. package/dist/types/src/aesthetics.test.d.ts.map +1 -0
  11. package/dist/types/src/appeal.d.ts +55 -0
  12. package/dist/types/src/appeal.d.ts.map +1 -0
  13. package/dist/types/src/appeal.test.d.ts +2 -0
  14. package/dist/types/src/appeal.test.d.ts.map +1 -0
  15. package/dist/types/src/architecture.d.ts +86 -0
  16. package/dist/types/src/architecture.d.ts.map +1 -0
  17. package/dist/types/src/architecture.test.d.ts +2 -0
  18. package/dist/types/src/architecture.test.d.ts.map +1 -0
  19. package/dist/types/src/compact.d.ts +39 -0
  20. package/dist/types/src/compact.d.ts.map +1 -0
  21. package/dist/types/src/compact.test.d.ts +2 -0
  22. package/dist/types/src/compact.test.d.ts.map +1 -0
  23. package/dist/types/src/diagnostics.d.ts +70 -3
  24. package/dist/types/src/diagnostics.d.ts.map +1 -1
  25. package/dist/types/src/dsl/cli.d.ts +2 -0
  26. package/dist/types/src/dsl/cli.d.ts.map +1 -0
  27. package/dist/types/src/dsl/compile.d.ts +12 -0
  28. package/dist/types/src/dsl/compile.d.ts.map +1 -0
  29. package/dist/types/src/dsl/convert.d.ts +45 -0
  30. package/dist/types/src/dsl/convert.d.ts.map +1 -0
  31. package/dist/types/src/dsl/convert.test.d.ts +2 -0
  32. package/dist/types/src/dsl/convert.test.d.ts.map +1 -0
  33. package/dist/types/src/dsl/dsl.test.d.ts +2 -0
  34. package/dist/types/src/dsl/dsl.test.d.ts.map +1 -0
  35. package/dist/types/src/dsl/gen/diagram.d.ts +3 -0
  36. package/dist/types/src/dsl/gen/diagram.d.ts.map +1 -0
  37. package/dist/types/src/dsl/index.d.ts +7 -0
  38. package/dist/types/src/dsl/index.d.ts.map +1 -0
  39. package/dist/types/src/dsl/parse.d.ts +49 -0
  40. package/dist/types/src/dsl/parse.d.ts.map +1 -0
  41. package/dist/types/src/dsl/print.d.ts +19 -0
  42. package/dist/types/src/dsl/print.d.ts.map +1 -0
  43. package/dist/types/src/dsl/semantic.test.d.ts +2 -0
  44. package/dist/types/src/dsl/semantic.test.d.ts.map +1 -0
  45. package/dist/types/src/dsl/vocabulary.d.ts +61 -0
  46. package/dist/types/src/dsl/vocabulary.d.ts.map +1 -0
  47. package/dist/types/src/dx-svg.d.ts +12 -0
  48. package/dist/types/src/dx-svg.d.ts.map +1 -0
  49. package/dist/types/src/dx-svg.test.d.ts +2 -0
  50. package/dist/types/src/dx-svg.test.d.ts.map +1 -0
  51. package/dist/types/src/extension/complete.d.ts +3 -0
  52. package/dist/types/src/extension/complete.d.ts.map +1 -0
  53. package/dist/types/src/extension/extension.test.d.ts +2 -0
  54. package/dist/types/src/extension/extension.test.d.ts.map +1 -0
  55. package/dist/types/src/extension/highlight.d.ts +14 -0
  56. package/dist/types/src/extension/highlight.d.ts.map +1 -0
  57. package/dist/types/src/extension/index.d.ts +6 -0
  58. package/dist/types/src/extension/index.d.ts.map +1 -0
  59. package/dist/types/src/extension/language.d.ts +13 -0
  60. package/dist/types/src/extension/language.d.ts.map +1 -0
  61. package/dist/types/src/extension/lint.d.ts +21 -0
  62. package/dist/types/src/extension/lint.d.ts.map +1 -0
  63. package/dist/types/src/extension/syntax.d.ts +3 -0
  64. package/dist/types/src/extension/syntax.d.ts.map +1 -0
  65. package/dist/types/src/index.d.ts +14 -0
  66. package/dist/types/src/index.d.ts.map +1 -1
  67. package/dist/types/src/mermaid-engine.d.ts +40 -1
  68. package/dist/types/src/mermaid-engine.d.ts.map +1 -1
  69. package/dist/types/src/mermaid.d.ts +3 -3
  70. package/dist/types/src/mermaid.d.ts.map +1 -1
  71. package/dist/types/src/nudge.d.ts +30 -0
  72. package/dist/types/src/nudge.d.ts.map +1 -0
  73. package/dist/types/src/nudge.test.d.ts +2 -0
  74. package/dist/types/src/nudge.test.d.ts.map +1 -0
  75. package/dist/types/src/objective.d.ts +4 -0
  76. package/dist/types/src/objective.d.ts.map +1 -1
  77. package/dist/types/src/ortho-router.d.ts +13 -1
  78. package/dist/types/src/ortho-router.d.ts.map +1 -1
  79. package/dist/types/src/ports.d.ts +40 -0
  80. package/dist/types/src/ports.d.ts.map +1 -0
  81. package/dist/types/src/ports.test.d.ts +2 -0
  82. package/dist/types/src/ports.test.d.ts.map +1 -0
  83. package/dist/types/src/relations.test.d.ts +2 -0
  84. package/dist/types/src/relations.test.d.ts.map +1 -0
  85. package/dist/types/src/rules.d.ts +30 -0
  86. package/dist/types/src/rules.d.ts.map +1 -0
  87. package/dist/types/src/scene.d.ts +108 -74
  88. package/dist/types/src/scene.d.ts.map +1 -1
  89. package/dist/types/src/score.d.ts +54 -0
  90. package/dist/types/src/score.d.ts.map +1 -0
  91. package/dist/types/src/score.test.d.ts +2 -0
  92. package/dist/types/src/score.test.d.ts.map +1 -0
  93. package/dist/types/src/semantic-engine.d.ts +41 -0
  94. package/dist/types/src/semantic-engine.d.ts.map +1 -0
  95. package/dist/types/src/semantic-engine.test.d.ts +2 -0
  96. package/dist/types/src/semantic-engine.test.d.ts.map +1 -0
  97. package/dist/types/src/semantic-place.d.ts +81 -0
  98. package/dist/types/src/semantic-place.d.ts.map +1 -0
  99. package/dist/types/src/semantic-route.d.ts +133 -0
  100. package/dist/types/src/semantic-route.d.ts.map +1 -0
  101. package/dist/types/src/semantic.d.ts +164 -0
  102. package/dist/types/src/semantic.d.ts.map +1 -0
  103. package/dist/types/src/uml-grid.d.ts.map +1 -1
  104. package/dist/types/src/uml.d.ts +3 -5
  105. package/dist/types/src/uml.d.ts.map +1 -1
  106. package/dist/types/src/view.d.ts +53 -0
  107. package/dist/types/src/view.d.ts.map +1 -0
  108. package/dist/types/src/view.test.d.ts +2 -0
  109. package/dist/types/src/view.test.d.ts.map +1 -0
  110. package/dist/types/tsconfig.tsbuildinfo +1 -1
  111. package/package.json +23 -5
  112. package/rules/DIAGRAM.mdl +388 -0
  113. package/src/aesthetics.test.ts +89 -0
  114. package/src/aesthetics.ts +148 -0
  115. package/src/appeal.test.ts +144 -0
  116. package/src/appeal.ts +586 -0
  117. package/src/architecture.test.ts +94 -0
  118. package/src/architecture.ts +215 -0
  119. package/src/compact.test.ts +67 -0
  120. package/src/compact.ts +219 -0
  121. package/src/diagnostics.test.ts +207 -1
  122. package/src/diagnostics.ts +481 -37
  123. package/src/dsl/cli.ts +46 -0
  124. package/src/dsl/compile.ts +28 -0
  125. package/src/dsl/convert.test.ts +51 -0
  126. package/src/dsl/convert.ts +98 -0
  127. package/src/dsl/diagram.grammar +195 -0
  128. package/src/dsl/dsl.test.ts +286 -0
  129. package/src/dsl/gen/diagram.ts +22 -0
  130. package/src/dsl/index.ts +44 -0
  131. package/src/dsl/parse.ts +1054 -0
  132. package/src/dsl/print.ts +198 -0
  133. package/src/dsl/semantic.test.ts +216 -0
  134. package/src/dsl/vocabulary.ts +150 -0
  135. package/src/dx-svg.test.ts +44 -0
  136. package/src/dx-svg.ts +77 -0
  137. package/src/extension/complete.ts +105 -0
  138. package/src/extension/extension.test.ts +135 -0
  139. package/src/extension/highlight.ts +23 -0
  140. package/src/extension/index.ts +9 -0
  141. package/src/extension/language.ts +31 -0
  142. package/src/extension/lint.ts +60 -0
  143. package/src/extension/syntax.ts +62 -0
  144. package/src/index.ts +14 -0
  145. package/src/mermaid-engine.test.ts +6 -6
  146. package/src/mermaid-engine.ts +569 -119
  147. package/src/mermaid.test.ts +17 -1
  148. package/src/mermaid.ts +30 -18
  149. package/src/nudge.test.ts +186 -0
  150. package/src/nudge.ts +387 -0
  151. package/src/objective.test.ts +2 -0
  152. package/src/objective.ts +17 -1
  153. package/src/ortho-router.ts +240 -80
  154. package/src/ports.test.ts +157 -0
  155. package/src/ports.ts +186 -0
  156. package/src/relations.test.ts +98 -0
  157. package/src/rules.ts +117 -0
  158. package/src/scene.ts +66 -5
  159. package/src/score.test.ts +64 -0
  160. package/src/score.ts +130 -0
  161. package/src/semantic-engine.test.ts +635 -0
  162. package/src/semantic-engine.ts +891 -0
  163. package/src/semantic-place.ts +1508 -0
  164. package/src/semantic-route.ts +1136 -0
  165. package/src/semantic.ts +278 -0
  166. package/src/typings.d.ts +8 -0
  167. package/src/uml-grid.ts +6 -1
  168. package/src/uml.test.ts +5 -1
  169. package/src/uml.ts +24 -11
  170. package/src/view.test.ts +139 -0
  171. package/src/view.ts +376 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/content.ts","../../src/scene.ts","../../src/dialect.ts","../../src/layout.ts","../../src/diagnostics.ts","../../src/mermaid.ts","../../src/ortho-router.ts","../../src/uml.ts","../../src/uml-grid.ts","../../src/objective.ts","../../src/mermaid-engine.ts","../../src/svg-handler.ts","../../src/ui.ts","../../src/uml-engine.ts","../../src/uml-rules.ts","../../src/uml-search.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Renderer-neutral command application over a canvas content map. Every renderer stores its\n// canvas as `Record<recordId, record>` and stamps DSL identity onto each managed record, so the\n// upsert/remove/move bookkeeping is identical; only the encoding differs. Renderers supply that\n// encoding via `ContentHandler` and inherit the command semantics.\n//\n\nimport { invariant } from '@dxos/invariant';\n\nimport type * as Scene from './scene.ts';\n\n/** Opaque map of record id → renderer record. */\nexport type ContentMap = Record<string, any>;\n\n/** DSL identity stamped onto a managed record. */\nexport type Identity = {\n object: string;\n element: string;\n /** Set on companion records that belong to an element rather than being one (e.g. arrow labels). */\n part?: string;\n};\n\n/** Where an object sits on the canvas: `canvas = origin + local * scale`. */\nexport type Placement = {\n origin: Scene.Point;\n scale: number;\n};\n\n/** An object as accepted by the renderer's compiler; `upsert-elements` supplies only a subset. */\nexport type ObjectInput = Scene.WorldObject | { id: string; elements: readonly Scene.Element[] };\n\n/** A world object as derived from the canvas: placement is always resolved. */\nexport type ReadWorldObject = Scene.WorldObject & Placement;\n\nexport type ReadResult = {\n scene: { objects: ReadWorldObject[] };\n /** Records on the canvas not managed by the DSL (drawn by hand). */\n unmanaged: number;\n};\n\nexport type ApplyResult = {\n /** Object ids created or modified. */\n upserted: string[];\n /** Records removed. */\n removed: number;\n};\n\n/**\n * The renderer-specific half of command application: how records carry identity, how objects\n * compile to records, and any bookkeeping the renderer's store requires.\n */\nexport type ContentHandler = {\n /** DSL identity for a record, or undefined when the record isn't managed by the DSL. */\n identify: (record: any) => Identity | undefined;\n /** Compile an object's elements into records keyed by record id. */\n render: (object: ObjectInput, placement: Placement, content: ContentMap) => ContentMap;\n /** Derive the scene from the content map. */\n read: (content: ContentMap) => ReadResult;\n /** Translate an object move into a per-record mutation. */\n translate: (record: any, delta: Scene.Point) => void;\n /** Create any scaffolding the renderer needs before its first record (e.g. a page). */\n scaffold?: (content: ContentMap) => void;\n /** Merge compiled records into the content map; defaults to a plain assign. */\n merge?: (content: ContentMap, records: ContentMap) => void;\n /** Clean up after deletions (e.g. drop bindings left dangling). */\n prune?: (content: ContentMap) => void;\n};\n\n/** Apply a batch of edit commands to the canvas content (mutates `content`). */\nexport const applyCommands = (\n content: ContentMap,\n commands: readonly Scene.Command[],\n handler: ContentHandler,\n): ApplyResult => {\n handler.scaffold?.(content);\n const upserted = new Set<string>();\n let removed = 0;\n\n const find = (objectId: string) => handler.read(content).scene.objects.find((object) => object.id === objectId);\n\n const merge = (object: ObjectInput, placement: Placement) => {\n const records = handler.render(object, placement, content);\n if (handler.merge) {\n handler.merge(content, records);\n } else {\n Object.assign(content, records);\n }\n };\n\n // Companion records (labels) are deleted alongside their element but aren't themselves\n // elements, so they don't count toward the reported total.\n const remove = (predicate: (identity: Identity) => boolean): number => {\n let count = 0;\n for (const [key, record] of Object.entries(content)) {\n const identity = handler.identify(record);\n if (identity && predicate(identity)) {\n // Read before delete: ECHO proxies dereference lazily, so fields vanish once removed.\n const isPart = identity.part !== undefined;\n delete content[key];\n if (!isPart) {\n count++;\n }\n }\n }\n handler.prune?.(content);\n return count;\n };\n\n for (const command of commands) {\n switch (command.op) {\n case 'upsert-object': {\n const previous = find(command.object.id);\n removed += remove((identity) => identity.object === command.object.id);\n merge(command.object, {\n origin: command.object.origin ?? previous?.origin ?? { x: 0, y: 0 },\n scale: command.object.scale ?? previous?.scale ?? 1,\n });\n upserted.add(command.object.id);\n break;\n }\n\n case 'upsert-elements': {\n const previous = find(command.objectId);\n invariant(previous, `unknown object: ${command.objectId} (use upsert-object to create it)`);\n const ids = new Set(command.elements.map((element) => element.id));\n removed += remove((identity) => identity.object === command.objectId && ids.has(identity.element));\n merge({ id: command.objectId, elements: command.elements }, previous);\n upserted.add(command.objectId);\n break;\n }\n\n case 'remove-elements': {\n const ids = new Set(command.elementIds);\n removed += remove((identity) => identity.object === command.objectId && ids.has(identity.element));\n break;\n }\n\n case 'remove-object': {\n removed += remove((identity) => identity.object === command.objectId);\n break;\n }\n\n case 'move-object': {\n const previous = find(command.objectId);\n invariant(previous, `unknown object: ${command.objectId}`);\n const delta = { x: command.origin.x - previous.origin.x, y: command.origin.y - previous.origin.y };\n for (const record of Object.values(content)) {\n if (handler.identify(record)?.object === command.objectId) {\n handler.translate(record, delta);\n }\n }\n upserted.add(command.objectId);\n break;\n }\n }\n }\n\n return { upserted: [...upserted], removed };\n};\n\n/** Seed a fractional-index counter past any existing `a<n>` indexes. */\nexport const nextIndex = (content: ContentMap, isCounted: (record: any) => boolean = () => true): number => {\n let max = 0;\n let count = 0;\n for (const record of Object.values(content)) {\n if (!record || !isCounted(record)) {\n continue;\n }\n count++;\n const match = /^a(\\d+)$/.exec(record.index ?? '');\n if (match) {\n max = Math.max(max, Number(match[1]));\n }\n }\n return Math.max(max, count);\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Backend-neutral scene DSL: a diagram is a set of named world objects (\"face\", \"hat\"),\n// each composed of graphical elements (rect, ellipse, line, curve, text, arrow, portal)\n// authored in object-local units. A backend's `ContentHandler` (tldraw, excalidraw, the SVG\n// handler here) maps the scene onto its concrete canvas records; see `content.ts`.\n//\n\nimport * as Schema from 'effect/Schema';\n\nexport const Color = Schema.Literals([\n 'black',\n 'grey',\n 'light-violet',\n 'violet',\n 'blue',\n 'light-blue',\n 'yellow',\n 'orange',\n 'green',\n 'light-green',\n 'light-red',\n 'red',\n 'white',\n]);\nexport type Color = Schema.Schema.Type<typeof Color>;\n\nexport const Fill = Schema.Literals(['none', 'solid', 'pattern']);\nexport type Fill = Schema.Schema.Type<typeof Fill>;\n\nexport const Stroke = Schema.Literals(['sketchy', 'solid', 'dashed', 'dotted']);\nexport type Stroke = Schema.Schema.Type<typeof Stroke>;\n\nexport const Weight = Schema.Literals(['s', 'm', 'l', 'xl']);\nexport type Weight = Schema.Schema.Type<typeof Weight>;\n\nexport const Point = Schema.Struct({\n x: Schema.Number,\n y: Schema.Number,\n});\nexport type Point = Schema.Schema.Type<typeof Point>;\n\n/** Style props shared by all elements; every field is optional with sensible defaults. */\nconst styleFields = {\n color: Schema.optional(Color).annotate({ description: 'Stroke/text color.' }),\n fill: Schema.optional(Fill).annotate({ description: 'Interior fill of closed shapes.' }),\n stroke: Schema.optional(Stroke).annotate({ description: 'Stroke rendering; sketchy is hand-drawn.' }),\n weight: Schema.optional(Weight).annotate({ description: 'Stroke weight / text size.' }),\n};\n\nconst id = Schema.String.annotate({\n description: 'Stable element id, unique within the object (e.g. \"left-eye\"). Used to edit or delete the element.',\n});\n\n/** Closed shape drawn inside a local bounding box. */\nexport const Box = Schema.Struct({\n kind: Schema.Literals(['rect', 'ellipse', 'diamond', 'triangle']),\n id,\n x: Schema.Number.annotate({ description: 'Left edge (object-local units).' }),\n y: Schema.Number.annotate({ description: 'Top edge (object-local units).' }),\n w: Schema.Number,\n h: Schema.Number,\n rotation: Schema.optional(Schema.Number).annotate({ description: 'Clockwise rotation in degrees.' }),\n text: Schema.optional(Schema.String).annotate({ description: 'Centered label.' }),\n corners: Schema.optional(Schema.Literals(['top', 'bottom', 'none'])).annotate({\n description: 'Rects only: round just these corners (default all); backends without corner control ignore it.',\n }),\n ...styleFields,\n});\nexport type Box = Schema.Schema.Type<typeof Box>;\n\n/** Circle sugar; reads back as an ellipse. */\nexport const Circle = Schema.Struct({\n kind: Schema.Literal('circle'),\n id,\n cx: Schema.Number.annotate({ description: 'Center x (object-local units).' }),\n cy: Schema.Number.annotate({ description: 'Center y (object-local units).' }),\n r: Schema.Number,\n text: Schema.optional(Schema.String),\n ...styleFields,\n});\nexport type Circle = Schema.Schema.Type<typeof Circle>;\n\n/** Straight segment or open polyline through the given points. */\nexport const Polyline = Schema.Struct({\n kind: Schema.Literal('line'),\n id,\n points: Schema.Array(Point).annotate({ description: 'Two or more points (object-local units).' }),\n closed: Schema.optional(Schema.Boolean).annotate({ description: 'Close the path back to the first point.' }),\n ...styleFields,\n});\nexport type Polyline = Schema.Schema.Type<typeof Polyline>;\n\n/** Smooth curve through the given points (spline). */\nexport const Curve = Schema.Struct({\n kind: Schema.Literal('curve'),\n id,\n points: Schema.Array(Point).annotate({ description: 'Control points the curve passes through.' }),\n ...styleFields,\n});\nexport type Curve = Schema.Schema.Type<typeof Curve>;\n\n/**\n * Circular arc sugar; reads back as a curve. Angles are degrees, measured clockwise from\n * the positive x-axis in screen coordinates (y grows downward): 0–180 is the lower half\n * (a smile), 180–360 the upper half (a frown).\n */\nexport const Arc = Schema.Struct({\n kind: Schema.Literal('arc'),\n id,\n cx: Schema.Number,\n cy: Schema.Number,\n r: Schema.Number,\n startAngle: Schema.Number,\n endAngle: Schema.Number,\n ...styleFields,\n});\nexport type Arc = Schema.Schema.Type<typeof Arc>;\n\n/** Free-standing text. */\nexport const Text = Schema.Struct({\n kind: Schema.Literal('text'),\n id,\n x: Schema.Number,\n y: Schema.Number,\n w: Schema.optional(Schema.Number).annotate({ description: 'Wrap width; omit for auto-size.' }),\n text: Schema.String,\n ...styleFields,\n});\nexport type Text = Schema.Schema.Type<typeof Text>;\n\n/** UML-style end markers: the head sits at the target, the tail at the source. */\nexport const ArrowHead = Schema.Literals(['arrow', 'triangle', 'crowsfoot', 'none']);\nexport type ArrowHead = Schema.Schema.Type<typeof ArrowHead>;\nexport const ArrowTail = Schema.Literals(['none', 'circle']);\nexport type ArrowTail = Schema.Schema.Type<typeof ArrowTail>;\n\n/**\n * Connector. Endpoints are element refs — `\"<elementId>\"` within the same object or\n * `\"<objectId>/<elementId>\"` across objects, either with an optional `#<port>` naming an\n * attachment point on the element — or explicit local points. Bound endpoints track their\n * target when it moves; without a port the renderer picks the attachment point.\n */\nexport const Arrow = Schema.Struct({\n kind: Schema.Literal('arrow'),\n id,\n from: Schema.optional(Schema.String).annotate({ description: 'Source element ref, optionally `#port`.' }),\n to: Schema.optional(Schema.String).annotate({ description: 'Target element ref, optionally `#port`.' }),\n start: Schema.optional(Point).annotate({ description: 'Explicit start (used when `from` is omitted).' }),\n end: Schema.optional(Point).annotate({ description: 'Explicit end (used when `to` is omitted).' }),\n text: Schema.optional(Schema.String).annotate({ description: 'Label at the arrow midpoint.' }),\n head: Schema.optional(ArrowHead).annotate({\n description: 'Marker at the target end (default arrow): triangle for inheritance, crowsfoot for has-many.',\n }),\n tail: Schema.optional(ArrowTail).annotate({\n description: 'Marker at the source end (default none): circle for containment.',\n }),\n ...styleFields,\n});\nexport type Arrow = Schema.Schema.Type<typeof Arrow>;\n\n/** A parsed endpoint ref; `object` is absent for a ref within the same object. */\nexport type ElementRef = {\n object?: string;\n element: string;\n port?: string;\n};\n\n/** Parse `\"[object/]element[#port]\"`; element ids may not contain `/` or `#`. */\nexport const parseRef = (ref: string): ElementRef => {\n const hash = ref.indexOf('#');\n const target = hash === -1 ? ref : ref.slice(0, hash);\n const port = hash === -1 ? undefined : ref.slice(hash + 1);\n const slash = target.indexOf('/');\n return {\n ...(slash === -1 ? {} : { object: target.slice(0, slash) }),\n element: slash === -1 ? target : target.slice(slash + 1),\n ...(port ? { port } : {}),\n };\n};\n\n/** Inverse of {@link parseRef}. */\nexport const formatRef = ({ object, element, port }: ElementRef): string =>\n `${object === undefined ? '' : `${object}/`}${element}${port === undefined ? '' : `#${port}`}`;\n\n/**\n * Canonical `object/element` handle of a ref, resolving a bare element id against the owning\n * object and dropping the port, so renderers without ports bind to the element itself.\n */\nexport const resolveRef = (ref: string, objectId: string): string => {\n const { object = objectId, element } = parseRef(ref);\n return `${object}/${element}`;\n};\n\n/**\n * Window onto another drawing: the referenced scene is rendered inside the box as a nested level\n * of detail. Renderers without nesting ignore it.\n */\nexport const Portal = Schema.Struct({\n kind: Schema.Literal('portal'),\n id,\n x: Schema.Number.annotate({ description: 'Left edge (object-local units).' }),\n y: Schema.Number.annotate({ description: 'Top edge (object-local units).' }),\n w: Schema.Number,\n h: Schema.Number,\n ref: Schema.String.annotate({ description: 'The drawing shown inside the box: an ECHO object reference (DXN).' }),\n text: Schema.optional(Schema.String).annotate({ description: 'Title shown on the frame.' }),\n ...styleFields,\n});\nexport type Portal = Schema.Schema.Type<typeof Portal>;\n\nexport const Element = Schema.Union([Box, Circle, Polyline, Curve, Arc, Text, Arrow, Portal]);\nexport type Element = Schema.Schema.Type<typeof Element>;\n\n/**\n * A semantic group of elements (\"face\", \"hat\") authored in its own local unit space.\n * `origin` (canvas px) and `scale` (px per unit) place it on the canvas:\n * `canvas = origin + local * scale`. On read, `origin` is derived as the top-left of the\n * object's bounding box, so the model survives users dragging shapes around.\n */\nexport const WorldObject = Schema.Struct({\n id: Schema.String.annotate({\n description: 'Stable object id naming the thing depicted (e.g. \"face\", \"hat\").',\n }),\n origin: Schema.optional(Point).annotate({\n description: 'Canvas position (px). Omit on upsert to keep the current position.',\n }),\n scale: Schema.optional(Schema.Number).annotate({ description: 'Canvas px per local unit (default 1).' }),\n index: Schema.optional(Schema.String).annotate({\n description: 'Fractional z-order index (e.g. \"a1\"); objects with one paint above those without, in index order.',\n }),\n ref: Schema.optional(Schema.String).annotate({\n description:\n 'What the object depicts: an ECHO object reference (activating the node opens it) or any other URI or path, carried for tooling.',\n }),\n elements: Schema.Array(Element),\n});\nexport type WorldObject = Schema.Schema.Type<typeof WorldObject>;\n\nexport const Scene = Schema.Struct({\n objects: Schema.Array(WorldObject),\n});\nexport type Scene = Schema.Schema.Type<typeof Scene>;\n\n//\n// Edit commands.\n//\n\nexport const UpsertObject = Schema.Struct({\n op: Schema.Literal('upsert-object'),\n object: WorldObject,\n}).annotate({ description: 'Create an object, or replace an existing one wholesale (same id).' });\n\nexport const UpsertElements = Schema.Struct({\n op: Schema.Literal('upsert-elements'),\n objectId: Schema.String,\n elements: Schema.Array(Element),\n}).annotate({ description: 'Add elements to an existing object, replacing any with matching ids.' });\n\nexport const RemoveElements = Schema.Struct({\n op: Schema.Literal('remove-elements'),\n objectId: Schema.String,\n elementIds: Schema.Array(Schema.String),\n});\n\nexport const RemoveObject = Schema.Struct({\n op: Schema.Literal('remove-object'),\n objectId: Schema.String,\n});\n\nexport const MoveObject = Schema.Struct({\n op: Schema.Literal('move-object'),\n objectId: Schema.String,\n origin: Point.annotate({ description: 'New canvas position (px) for the object top-left.' }),\n});\n\nexport const Command = Schema.Union([UpsertObject, UpsertElements, RemoveElements, RemoveObject, MoveObject]);\nexport type Command = Schema.Schema.Type<typeof Command>;\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Extension point for higher-level diagram languages (mermaid, d2, sequence, uml-class, …).\n// A dialect compiles its input into scene edit commands — owning any layout it needs — so its\n// output lands as ordinary world objects and stays editable by id. Mirrors the architecture\n// shared by Mermaid/D2/Kroki: dialect → intermediate positioned model → renderer.\n//\n\nimport * as Effect from 'effect/Effect';\nimport * as Schema from 'effect/Schema';\n\nimport { invariant } from '@dxos/invariant';\n\nimport * as Scene from './scene.ts';\n\nexport type Dialect<Input = any> = {\n id: string;\n description: string;\n input: Schema.Codec<Input, any>;\n compile: (input: Input) => Effect.Effect<readonly Scene.Command[]>;\n};\n\n/** The core dialect: input is already scene edit commands (identity compile). */\nexport const sceneDialect: Dialect<readonly Scene.Command[]> = {\n id: 'scene',\n description: 'Positioned world objects and elements; the agent does the layout.',\n input: Schema.Array(Scene.Command),\n compile: Effect.succeed,\n};\n\nexport class DialectRegistry {\n readonly #dialects = new Map<string, Dialect>();\n\n constructor(dialects: Dialect[] = [sceneDialect]) {\n dialects.forEach((dialect) => this.register(dialect));\n }\n\n register(dialect: Dialect): void {\n invariant(!this.#dialects.has(dialect.id), `duplicate dialect: ${dialect.id}`);\n this.#dialects.set(dialect.id, dialect);\n }\n\n get(id: string): Dialect | undefined {\n return this.#dialects.get(id);\n }\n\n list(): Dialect[] {\n return [...this.#dialects.values()];\n }\n}\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Shared layered-layout helpers for dialects that compile edge lists without coordinates\n// (mermaid flowchart, UML class). Ranking is longest-path over the forward edges; cycles are\n// broken by ignoring DFS back edges so a loop cannot push a node below its own successors.\n//\n\nimport type * as Scene from './scene.ts';\n\nexport type LayoutEdge = {\n from: string;\n to: string;\n};\n\nexport type FontMetrics = {\n /** Average glyph advance, in scene units at scale 1. */\n charW: number;\n /** Line height, in scene units at scale 1. */\n lineH: number;\n};\n\n/**\n * Empirical text metrics per scene weight, calibrated to tldraw's draw font (`size` s/m/l/xl runs\n * ~18/25/38/48 px): charW ≈ 0.6–0.67 em, lineH ≈ 1.35 em. Dialects size boxes from these so text\n * fits without the renderer growing shapes over their neighbours.\n */\nexport const FONT_METRICS: Record<Scene.Weight, FontMetrics> = {\n s: { charW: 12, lineH: 26 },\n m: { charW: 15, lineH: 34 },\n l: { charW: 23, lineH: 51 },\n xl: { charW: 29, lineH: 65 },\n};\n\n/**\n * Edges that close a cycle, found by DFS: an edge into a node still on the stack points backwards.\n * Ranking ignores them, so `C --> Y --> C` ranks C by its forward predecessors alone instead of\n * chasing the loop.\n */\nexport const backEdges = <Edge extends LayoutEdge>(nodeIds: readonly string[], edges: readonly Edge[]): Set<Edge> => {\n const outgoing = new Map<string, Edge[]>();\n for (const edge of edges) {\n outgoing.set(edge.from, [...(outgoing.get(edge.from) ?? []), edge]);\n }\n\n const back = new Set<Edge>();\n const done = new Set<string>();\n const onStack = new Set<string>();\n\n const visit = (id: string) => {\n onStack.add(id);\n for (const edge of outgoing.get(id) ?? []) {\n if (onStack.has(edge.to)) {\n back.add(edge);\n } else if (!done.has(edge.to)) {\n visit(edge.to);\n }\n }\n onStack.delete(id);\n done.add(id);\n };\n\n // Roots first so the DFS classifies edges along the natural reading order of the diagram.\n const targets = new Set(edges.map((edge) => edge.to));\n for (const id of nodeIds) {\n if (!targets.has(id) && !done.has(id)) {\n visit(id);\n }\n }\n for (const id of nodeIds) {\n if (!done.has(id)) {\n visit(id);\n }\n }\n return back;\n};\n\n/** Assign each node a rank one past its deepest forward predecessor. */\nexport const rank = (nodeIds: readonly string[], edges: readonly LayoutEdge[]): Map<string, number> => {\n const back = backEdges(nodeIds, edges);\n const forward = edges.filter((edge) => !back.has(edge));\n const ranks = new Map(nodeIds.map((id) => [id, 0]));\n for (let pass = 0; pass < nodeIds.length; pass++) {\n let changed = false;\n for (const edge of forward) {\n const next = (ranks.get(edge.from) ?? 0) + 1;\n if (next > (ranks.get(edge.to) ?? 0)) {\n ranks.set(edge.to, next);\n changed = true;\n }\n }\n if (!changed) {\n break;\n }\n }\n return ranks;\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Layout diagnostics: a pure analysis of an emitted scene, independent of the dialect and the\n// placement strategy that produced it. Everything measured here is geometry already present in\n// the scene, so one report covers every dialect, every placement engine, a hand-authored scene,\n// and a scene read back from a renderer after the user dragged it. See `docs/DESIGN.md`.\n//\n\nimport * as Schema from 'effect/Schema';\n\nimport * as Layout from './layout.ts';\nimport type * as Scene from './scene.ts';\n\nexport const Severity = Schema.Literals(['error', 'warning']);\nexport type Severity = Schema.Schema.Type<typeof Severity>;\n\n/**\n * `error` codes are objective defects — the picture is wrong, not merely busy — and gate CI.\n * `warning` codes are quality metrics that trend rather than pass/fail; they are golden-filed so\n * a layout change reads as a reviewable diff instead of a threshold argument.\n */\nexport const Code = Schema.Literals([\n 'node-overlap',\n 'route-through-node',\n 'label-overflow',\n 'edge-crossing',\n 'excessive-bends',\n]);\nexport type Code = Schema.Schema.Type<typeof Code>;\n\nexport const SEVERITY: Record<Code, Severity> = {\n 'node-overlap': 'error',\n 'route-through-node': 'error',\n 'label-overflow': 'error',\n 'edge-crossing': 'warning',\n 'excessive-bends': 'warning',\n};\n\n/** A schema so operations can return diagnostics to the agent — the repair loop. */\nexport const Diagnostic = Schema.Struct({\n code: Code,\n severity: Severity,\n message: Schema.String,\n refs: Schema.Array(Schema.String).annotate({\n description: 'Scene refs implicated: `objectId` or `objectId/elementId`, as `Arrow.from`/`to` spell them.',\n }),\n});\nexport type Diagnostic = Schema.Schema.Type<typeof Diagnostic>;\n\n/** Aggregate counts; the soft ones are the score a layout change is reviewed against. */\nexport type Metrics = {\n nodes: number;\n connectors: number;\n overlaps: number;\n routesThroughNodes: number;\n labelOverflows: number;\n crossings: number;\n bends: number;\n /** Total connector length in scene units; long edges are hard to follow. */\n length: number;\n width: number;\n height: number;\n /** Boxes that enclose another object's box (subgraph / group frames). */\n containers: number;\n /** Smallest gap from a container to its nearest container (Infinity with fewer than two). */\n frameGapMin: number;\n /** Spread (max − min) of each container's nearest-neighbour gap; 0 when gutters are uniform. */\n frameGapSpread: number;\n};\n\nexport type Report = {\n diagnostics: readonly Diagnostic[];\n metrics: Metrics;\n};\n\nexport type Options = {\n /** Bends per connector above which `excessive-bends` is reported (default 3). */\n maxBends?: number;\n};\n\ntype Point = Scene.Point;\ntype Rect = { x: number; y: number; w: number; h: number };\ntype Segment = [Point, Point];\n\n/** Tolerance in scene units; ports land on a half-grid, so this only absorbs float error. */\nconst EPSILON = 0.5;\n\nconst place = (object: Scene.WorldObject, point: Point): Point => {\n const { x = 0, y = 0 } = object.origin ?? {};\n const scale = object.scale ?? 1;\n return { x: x + point.x * scale, y: y + point.y * scale };\n};\n\nconst isBox = (element: Scene.Element): element is Scene.Box =>\n element.kind === 'rect' || element.kind === 'ellipse' || element.kind === 'diamond' || element.kind === 'triangle';\n\ntype Node = { ref: string; rect: Rect; text?: string; weight: Scene.Weight };\n\n/** Absolute rects for every closed shape, keyed by scene ref. */\nconst nodes = (objects: readonly Scene.WorldObject[]): Node[] =>\n objects.flatMap((object) =>\n object.elements.filter(isBox).map((element) => {\n const origin = place(object, { x: element.x, y: element.y });\n const scale = object.scale ?? 1;\n return {\n ref: `${object.id}/${element.id}`,\n rect: { x: origin.x, y: origin.y, w: element.w * scale, h: element.h * scale },\n text: element.text,\n weight: element.weight ?? 'm',\n };\n }),\n );\n\ntype Connector = { ref: string; points: Point[] };\n\n/**\n * Connector paths, rejoining the `line` prefix and `arrow` head the emitters split a routed edge\n * into (`<id>-path` + `<id>`); a plain arrow is a one-segment path.\n */\nconst connectors = (objects: readonly Scene.WorldObject[]): Connector[] => {\n const paths = new Map<string, Connector>();\n for (const object of objects) {\n for (const element of object.elements) {\n if (element.kind === 'line') {\n const id = element.id.replace(/-path$/, '');\n const ref = `${object.id}/${id}`;\n paths.set(ref, { ref, points: element.points.map((point) => place(object, point)) });\n }\n }\n for (const element of object.elements) {\n if (element.kind === 'arrow' && element.start && element.end) {\n const ref = `${object.id}/${element.id}`;\n const head = [place(object, element.start), place(object, element.end)];\n const existing = paths.get(ref);\n // The head's start repeats the polyline's last waypoint; keep one copy.\n paths.set(ref, { ref, points: existing ? [...existing.points.slice(0, -1), ...head] : head });\n }\n }\n }\n return [...paths.values()];\n};\n\nconst segmentsOf = ({ points }: Connector): Segment[] =>\n points.slice(0, -1).map((point, index): Segment => [point, points[index + 1]]);\n\nconst orientation = (origin: Point, a: Point, b: Point) =>\n (a.x - origin.x) * (b.y - origin.y) - (a.y - origin.y) * (b.x - origin.x);\n\nconst coincident = (a: Point, b: Point) => Math.abs(a.x - b.x) < EPSILON && Math.abs(a.y - b.y) < EPSILON;\n\n/** Proper crossing: the segments intersect away from all four endpoints (shared ports do not count). */\nconst properlyCrosses = ([a1, a2]: Segment, [b1, b2]: Segment): boolean => {\n if ([a1, a2].some((a) => [b1, b2].some((b) => coincident(a, b)))) {\n return false;\n }\n const d1 = orientation(a1, a2, b1);\n const d2 = orientation(a1, a2, b2);\n const d3 = orientation(b1, b2, a1);\n const d4 = orientation(b1, b2, a2);\n return d1 > 0 !== d2 > 0 && d3 > 0 !== d4 > 0;\n};\n\n/** Overlap area of two rects; 0 when they merely touch. */\nconst overlapArea = (a: Rect, b: Rect): number => {\n const w = Math.min(a.x + a.w, b.x + b.w) - Math.max(a.x, b.x);\n const h = Math.min(a.y + a.h, b.y + b.h) - Math.max(a.y, b.y);\n return w > EPSILON && h > EPSILON ? w * h : 0;\n};\n\n/**\n * Strict enclosure: the inner rect fits inside AND is smaller. Two identical rects are stacked\n * nodes — the strongest overlap — not a container and its member.\n */\nconst contains = (outer: Rect, inner: Rect): boolean =>\n outer.x - EPSILON <= inner.x &&\n outer.y - EPSILON <= inner.y &&\n outer.x + outer.w + EPSILON >= inner.x + inner.w &&\n outer.y + outer.h + EPSILON >= inner.y + inner.h &&\n (inner.w < outer.w - EPSILON || inner.h < outer.h - EPSILON);\n\n/**\n * Length of the segment's run through the rect's INTERIOR (Liang-Barsky). A connector legitimately\n * terminating at a node only touches its border, so an interior run identifies a route drawn\n * across a node it does not belong to — no knowledge of the edge's terminals required.\n */\nconst interiorRun = ([start, end]: Segment, rect: Rect): number => {\n const dx = end.x - start.x;\n const dy = end.y - start.y;\n // Inset so a route running flush along a border, or into a port, is not counted.\n const box = { x: rect.x + EPSILON, y: rect.y + EPSILON, w: rect.w - EPSILON * 2, h: rect.h - EPSILON * 2 };\n if (box.w <= 0 || box.h <= 0) {\n return 0;\n }\n let enter = 0;\n let exit = 1;\n for (const [p, q] of [\n [-dx, start.x - box.x],\n [dx, box.x + box.w - start.x],\n [-dy, start.y - box.y],\n [dy, box.y + box.h - start.y],\n ]) {\n if (p === 0) {\n if (q < 0) {\n return 0;\n }\n continue;\n }\n const r = q / p;\n if (p < 0) {\n enter = Math.max(enter, r);\n } else {\n exit = Math.min(exit, r);\n }\n }\n return enter >= exit ? 0 : Math.hypot(dx, dy) * (exit - enter);\n};\n\n/** Bends in an orthogonal path: waypoints where the run changes axis. */\nconst bendCount = ({ points }: Connector): number => {\n let bends = 0;\n for (let index = 1; index < points.length - 1; index++) {\n const [previous, point, next] = [points[index - 1], points[index], points[index + 1]];\n const collinear =\n (Math.abs(previous.x - point.x) < EPSILON && Math.abs(point.x - next.x) < EPSILON) ||\n (Math.abs(previous.y - point.y) < EPSILON && Math.abs(point.y - next.y) < EPSILON);\n if (!collinear) {\n bends++;\n }\n }\n return bends;\n};\n\n/**\n * Estimated bounds of a wrapped label, using the shared font metrics the dialects size boxes by.\n * The last line carries no trailing leading: `lineH ≈ 1.35em` (see `FONT_METRICS`), so the glyph\n * block is `(lines − 1) · lineH + em`.\n */\nconst labelFits = ({ rect, text, weight }: Node): boolean => {\n if (!text) {\n return true;\n }\n const font = Layout.FONT_METRICS[weight];\n const perLine = Math.max(1, Math.floor(rect.w / font.charW));\n const lines = text.split('\\n').reduce((total, line) => total + Math.max(1, Math.ceil(line.length / perLine)), 0);\n return (lines - 1) * font.lineH + font.lineH / 1.35 <= rect.h + EPSILON;\n};\n\n/**\n * Analyzes an emitted scene for layout defects and quality metrics. Pure: the same scene always\n * yields the same report, so the soft metrics can be golden-filed and the hard codes asserted.\n */\nexport const analyze = (objects: readonly Scene.WorldObject[], { maxBends = 3 }: Options = {}): Report => {\n const diagnostics: Diagnostic[] = [];\n const allNodes = nodes(objects);\n const allConnectors = connectors(objects);\n const ownerOf = (ref: string) => ref.slice(0, ref.indexOf('/'));\n\n // A box enclosing another object's box is a container (subgraph or group frame): connectors\n // cross its border by design, so it is never an obstacle.\n const containers = new Set(\n allNodes\n .filter((outer) =>\n allNodes.some((inner) => ownerOf(inner.ref) !== ownerOf(outer.ref) && contains(outer.rect, inner.rect)),\n )\n .map(({ ref }) => ref),\n );\n\n // Overlap is compared across objects only: an object's own shapes are composed deliberately\n // (a UML frame behind its title bar), and a container legitimately encloses its members.\n for (let i = 0; i < allNodes.length; i++) {\n for (let j = i + 1; j < allNodes.length; j++) {\n const [left, right] = [allNodes[i], allNodes[j]];\n if (ownerOf(left.ref) === ownerOf(right.ref)) {\n continue;\n }\n if (contains(left.rect, right.rect) || contains(right.rect, left.rect)) {\n continue;\n }\n if (overlapArea(left.rect, right.rect) > 0) {\n diagnostics.push({\n code: 'node-overlap',\n severity: SEVERITY['node-overlap'],\n message: `Nodes \"${left.ref}\" and \"${right.ref}\" overlap.`,\n refs: [left.ref, right.ref],\n });\n }\n }\n }\n\n for (const connector of allConnectors) {\n for (const node of allNodes) {\n // Shapes in the connector's own object are its decoration, not obstacles.\n if (ownerOf(node.ref) === ownerOf(connector.ref) || containers.has(node.ref)) {\n continue;\n }\n const run = segmentsOf(connector).reduce((total, segment) => total + interiorRun(segment, node.rect), 0);\n if (run > EPSILON) {\n diagnostics.push({\n code: 'route-through-node',\n severity: SEVERITY['route-through-node'],\n message: `Connector \"${connector.ref}\" is drawn across node \"${node.ref}\".`,\n refs: [connector.ref, node.ref],\n });\n }\n }\n }\n\n for (const node of allNodes) {\n if (!labelFits(node)) {\n diagnostics.push({\n code: 'label-overflow',\n severity: SEVERITY['label-overflow'],\n message: `Label of \"${node.ref}\" does not fit its shape.`,\n refs: [node.ref],\n });\n }\n }\n\n let crossings = 0;\n for (let i = 0; i < allConnectors.length; i++) {\n for (let j = i + 1; j < allConnectors.length; j++) {\n const [left, right] = [allConnectors[i], allConnectors[j]];\n const crossed = segmentsOf(left).some((a) => segmentsOf(right).some((b) => properlyCrosses(a, b)));\n if (crossed) {\n crossings++;\n diagnostics.push({\n code: 'edge-crossing',\n severity: SEVERITY['edge-crossing'],\n message: `Connectors \"${left.ref}\" and \"${right.ref}\" cross.`,\n refs: [left.ref, right.ref],\n });\n }\n }\n }\n\n let bends = 0;\n let length = 0;\n for (const connector of allConnectors) {\n length += segmentsOf(connector).reduce((total, [a, b]) => total + Math.hypot(b.x - a.x, b.y - a.y), 0);\n const count = bendCount(connector);\n bends += count;\n if (count > maxBends) {\n diagnostics.push({\n code: 'excessive-bends',\n severity: SEVERITY['excessive-bends'],\n message: `Connector \"${connector.ref}\" takes ${count} bends.`,\n refs: [connector.ref],\n });\n }\n }\n\n const xs = allNodes.flatMap(({ rect }) => [rect.x, rect.x + rect.w]);\n const ys = allNodes.flatMap(({ rect }) => [rect.y, rect.y + rect.h]);\n\n // Gutter uniformity between containers: each frame's gap to its nearest frame. Nearest-neighbour\n // (rather than all pairs) so a row of three is judged on its two gutters, not the span across.\n const frameRects = allNodes.filter(({ ref }) => containers.has(ref)).map(({ rect }) => rect);\n const gapBetween = (a: Rect, b: Rect) =>\n Math.max(a.x - (b.x + b.w), b.x - (a.x + a.w), a.y - (b.y + b.h), b.y - (a.y + a.h));\n const nearestGaps = frameRects.flatMap((frame, index) => {\n const gaps = frameRects\n .filter((_, other) => other !== index)\n .map((other) => gapBetween(frame, other))\n .filter((gap) => gap >= 0);\n return gaps.length ? [Math.min(...gaps)] : [];\n });\n\n return {\n diagnostics,\n metrics: {\n nodes: allNodes.length,\n connectors: allConnectors.length,\n overlaps: diagnostics.filter(({ code }) => code === 'node-overlap').length,\n routesThroughNodes: diagnostics.filter(({ code }) => code === 'route-through-node').length,\n labelOverflows: diagnostics.filter(({ code }) => code === 'label-overflow').length,\n crossings,\n bends,\n length,\n width: xs.length ? Math.max(...xs) - Math.min(...xs) : 0,\n height: ys.length ? Math.max(...ys) - Math.min(...ys) : 0,\n containers: frameRects.length,\n frameGapMin: nearestGaps.length ? Math.min(...nearestGaps) : Infinity,\n frameGapSpread: nearestGaps.length >= 2 ? Math.max(...nearestGaps) - Math.min(...nearestGaps) : 0,\n },\n };\n};\n\n/** Errors only — the set that gates CI and that an agent must fix before the diagram is usable. */\nexport const errors = (report: Report): readonly Diagnostic[] =>\n report.diagnostics.filter(({ severity }) => severity === 'error');\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Mermaid flowchart dialect: parses the subset needed for block diagrams (node declarations,\n// subgraphs, directed edges) and compiles it to scene commands with a layered layout. Mermaid\n// carries no coordinates, so the dialect owns placement — see `dialect.ts` for the contract.\n//\n\nimport * as Layout from './layout.ts';\nimport type * as Scene from './scene.ts';\n\nexport type Direction = 'TB' | 'BT' | 'LR' | 'RL';\n\nexport type MermaidNode = {\n id: string;\n label: string;\n /** Enclosing subgraph id, when declared inside one. */\n group?: string;\n /** What the node depicts (DXN or URI), from a `%% ref <id> <target>` directive. */\n ref?: string;\n};\n\nexport type MermaidGroup = {\n id: string;\n label: string;\n children: string[];\n};\n\n/** Relationship kind, from the edge token; drawn with the UML end markers in `markers`. */\nexport type RelationKind = 'reference' | 'inheritance' | 'hasMany' | 'contains';\n\nexport type MermaidEdge = {\n from: string;\n to: string;\n kind: RelationKind;\n label?: string;\n};\n\n/**\n * Edge tokens: mermaid's own arrows read as references; the classDiagram-style `--|>` (hollow\n * triangle) and ER-style `--{` (crow's foot) and `o-->` (circle at the source) extend the flowchart\n * grammar with the UML kinds, at the cost of mermaid.js rejecting those lines.\n */\nconst EDGE_KINDS: Record<string, RelationKind> = {\n '-->': 'reference',\n '---': 'reference',\n '-.->': 'reference',\n '==>': 'reference',\n '--|>': 'inheritance',\n '--{': 'hasMany',\n 'o-->': 'contains',\n};\n\n/** Reference-render labels for the UML kinds, used when the edge carries none of its own. */\nconst UML_LABELS: Record<string, string> = { '--|>': 'extends', '--{': 'has many', 'o-->': 'contains' };\nconst UML_EDGE = /^(\\s*\\S+)\\s*(o-->|--\\|>|--\\{)\\s*(?:\\|(.*?)\\|\\s*)?(\\S+)\\s*$/;\n\n/**\n * Rewrite the UML edge tokens into mermaid-legal labelled arrows, for rendering the source with\n * mermaid.js itself (as a reference beside our layout). Lossy by design: mermaid flowcharts have no\n * triangle or crow's foot, so the kind becomes the label unless the edge already has one; `%% ref`\n * lines are already comments.\n */\nexport const toStandard = (source: string): string =>\n source\n .split('\\n')\n .map((line) => {\n const match = UML_EDGE.exec(line);\n return match ? `${match[1]} -->|${match[3] ?? UML_LABELS[match[2]]}| ${match[4]}` : line;\n })\n .join('\\n');\n\n/** Scene arrow markers for a relationship kind. */\nexport const markers = (kind: RelationKind): Pick<Scene.Arrow, 'head' | 'tail'> => {\n switch (kind) {\n case 'inheritance':\n return { head: 'triangle' };\n case 'hasMany':\n return { head: 'crowsfoot' };\n case 'contains':\n return { tail: 'circle' };\n default:\n return {};\n }\n};\n\nexport type MermaidGraph = {\n direction: Direction;\n nodes: MermaidNode[];\n groups: MermaidGroup[];\n edges: MermaidEdge[];\n};\n\nconst DIRECTIONS: Direction[] = ['TB', 'BT', 'LR', 'RL'];\n\n// `A[Label]`, `A(Label)`, `A{Label}` or a bare `A`.\nconst NODE = /^([A-Za-z0-9_-]+)(?:\\[(.*?)\\]|\\((.*?)\\)|\\{(.*?)\\})?$/;\n// `A --> B`, `A-->|label|B`, `A --- B`, plus the UML kinds `B --|> A`, `X --{ Y`, `A o--> B`.\nconst EDGE = /^(.+?)\\s*(o-->|--\\|>|--\\{|-->|---|-\\.->|==>)\\s*(?:\\|(.*?)\\|\\s*)?(.+)$/;\nconst SUBGRAPH = /^subgraph\\s+([A-Za-z0-9_-]+)(?:\\s*\\[(.*?)\\])?\\s*$/;\n\n// `%% ref A packages/core/echo` — a comment to mermaid proper, so sources stay portable.\nconst REF = /^%%\\s*ref\\s+([A-Za-z0-9_-]+)\\s+(\\S+)\\s*$/;\n\nconst unquote = (value: string) => value.trim().replace(/^\"(.*)\"$/, '$1');\n\n/** Parse a mermaid flowchart into a neutral graph. Unrecognised lines are ignored. */\nexport const parse = (source: string): MermaidGraph => {\n const nodes = new Map<string, MermaidNode>();\n const groups: MermaidGroup[] = [];\n const edges: MermaidEdge[] = [];\n let direction: Direction = 'TB';\n const stack: string[] = [];\n\n const declare = (token: string): string | undefined => {\n const match = NODE.exec(token.trim());\n if (!match) {\n return undefined;\n }\n const [, id, square, round, curly] = match;\n const label = unquote(square ?? round ?? curly ?? id);\n const group = stack[stack.length - 1];\n const existing = nodes.get(id);\n if (existing) {\n // A later declaration with an explicit label wins; the first mention fixes the group.\n if (square ?? round ?? curly) {\n existing.label = label;\n }\n return id;\n }\n nodes.set(id, { id, label, ...(group ? { group } : {}) });\n if (group) {\n groups.find((entry) => entry.id === group)?.children.push(id);\n }\n return id;\n };\n\n const refs = new Map<string, string>();\n for (const raw of source.split('\\n')) {\n const line = raw.trim();\n const ref = REF.exec(line);\n if (ref) {\n refs.set(ref[1], ref[2]);\n continue;\n }\n if (!line || line.startsWith('%%')) {\n continue;\n }\n\n const header = /^(?:flowchart|graph)\\s+([A-Za-z]{2})$/.exec(line);\n if (header) {\n const value = header[1].toUpperCase() as Direction;\n direction = DIRECTIONS.includes(value) ? value : 'TB';\n continue;\n }\n\n const subgraph = SUBGRAPH.exec(line);\n if (subgraph) {\n const [, id, label] = subgraph;\n groups.push({ id, label: unquote(label ?? id), children: [] });\n stack.push(id);\n continue;\n }\n\n if (line === 'end') {\n stack.pop();\n continue;\n }\n\n const edge = EDGE.exec(line);\n if (edge) {\n const [, from, token, label, to] = edge;\n const fromId = declare(from);\n const toId = declare(to);\n if (fromId && toId) {\n edges.push({\n from: fromId,\n to: toId,\n kind: EDGE_KINDS[token] ?? 'reference',\n ...(label ? { label: unquote(label) } : {}),\n });\n }\n continue;\n }\n\n declare(line);\n }\n\n // Directives may precede or follow the node they name.\n return {\n direction,\n nodes: [...nodes.values()].map((node) => (refs.has(node.id) ? { ...node, ref: refs.get(node.id) } : node)),\n groups,\n edges,\n };\n};\n\n/** Layout constants in scene units. */\nconst NODE_W = 100;\nconst NODE_H = 50;\nconst GAP_MAIN = 60;\nconst GAP_CROSS = 40;\nconst GROUP_PAD = 24;\n\n/** Assign each node a rank one past its deepest forward predecessor. */\nconst rank = (graph: MermaidGraph): Map<string, number> =>\n Layout.rank(\n graph.nodes.map((node) => node.id),\n graph.edges,\n );\n\nexport type CompileOptions = {\n /** Canvas position of the diagram's top-left, in canvas px. */\n origin?: Scene.Point;\n /** Canvas px per scene unit. */\n scale?: number;\n /** Gap between ranks along the flow direction, in scene units (default 60). */\n gapMain?: number;\n /** Gap between nodes within a rank, in scene units (default 40). */\n gapCross?: number;\n};\n\n/**\n * Compile a mermaid flowchart into scene commands: one world object per node (element `box`),\n * one per subgraph frame, and an `edges` object holding the connectors as bound arrows.\n */\nexport const compile = (source: string, options: CompileOptions = {}): Scene.Command[] => {\n const graph = parse(source);\n const { origin = { x: 0, y: 0 }, scale = 1, gapMain = GAP_MAIN, gapCross = GAP_CROSS } = options;\n const ranks = rank(graph);\n const horizontal = graph.direction === 'LR' || graph.direction === 'RL';\n\n // Group nodes by rank, preserving declaration order within each.\n const lanes = new Map<number, MermaidNode[]>();\n for (const node of graph.nodes) {\n const value = ranks.get(node.id) ?? 0;\n lanes.set(value, [...(lanes.get(value) ?? []), node]);\n }\n const widest = Math.max(...[...lanes.values()].map((lane) => lane.length), 1);\n\n // Axis-specific node sizes: for LR/RL the main axis advances by width and lanes stack by height.\n const mainSize = horizontal ? NODE_W : NODE_H;\n const crossSize = horizontal ? NODE_H : NODE_W;\n const positions = new Map<string, Scene.Point>();\n for (const [lane, members] of lanes) {\n const span = members.length * crossSize + (members.length - 1) * gapCross;\n const offset = (widest * crossSize + (widest - 1) * gapCross - span) / 2;\n members.forEach((node, index) => {\n const cross = offset + index * (crossSize + gapCross);\n const main = lane * (mainSize + gapMain);\n positions.set(node.id, horizontal ? { x: main, y: cross } : { x: cross, y: main });\n });\n }\n\n const commands: Scene.Command[] = [];\n\n // Frames first so nodes paint above them.\n for (const group of graph.groups) {\n const members = group.children.map((id) => positions.get(id)).filter((point): point is Scene.Point => !!point);\n if (members.length === 0) {\n continue;\n }\n const minX = Math.min(...members.map((point) => point.x)) - GROUP_PAD;\n const minY = Math.min(...members.map((point) => point.y)) - GROUP_PAD;\n const maxX = Math.max(...members.map((point) => point.x)) + NODE_W + GROUP_PAD;\n const maxY = Math.max(...members.map((point) => point.y)) + NODE_H + GROUP_PAD;\n commands.push({\n op: 'upsert-object',\n object: {\n id: group.id,\n origin: { x: origin.x + minX * scale, y: origin.y + minY * scale },\n scale,\n elements: [\n {\n kind: 'rect',\n id: 'frame',\n x: 0,\n y: 0,\n w: maxX - minX,\n h: maxY - minY,\n stroke: 'dashed',\n color: 'grey',\n ...(group.label.trim() ? { text: group.label } : {}),\n },\n ],\n },\n });\n }\n\n for (const node of graph.nodes) {\n const point = positions.get(node.id)!;\n commands.push({\n op: 'upsert-object',\n object: {\n id: node.id,\n origin: { x: origin.x + point.x * scale, y: origin.y + point.y * scale },\n scale,\n ...(node.ref ? { ref: node.ref } : {}),\n elements: [{ kind: 'rect', id: 'box', x: 0, y: 0, w: NODE_W, h: NODE_H, text: node.label }],\n },\n });\n }\n\n if (graph.edges.length > 0) {\n commands.push({\n op: 'upsert-object',\n object: {\n id: 'edges',\n origin,\n scale,\n elements: graph.edges.map((edge) => ({\n kind: 'arrow' as const,\n id: `${edge.from}-${edge.to}`,\n from: `${edge.from}/box`,\n to: `${edge.to}/box`,\n ...markers(edge.kind),\n ...(edge.label ? { text: edge.label } : {}),\n })),\n },\n });\n }\n\n return commands;\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Obstacle-avoiding orthogonal router: A* over a fine grid with a turn-dominant cost, so a\n// connector never crosses a node and takes the fewest bends that avoidance allows (length breaks\n// ties). A shared usage penalty nudges later edges off cells earlier edges already run through.\n// Plugs into the dialects via the `Router` contract (`uml-grid.ts`).\n//\n\nimport type * as Scene from './scene.ts';\nimport type { Rect, RoutedRelation, Router } from './uml-grid.ts';\n\n/** Clearance kept between a route and any node border, in steps. */\nconst CLEARANCE = 1;\n/** One bend costs as much as this many steps — turns dominate, distance breaks ties. */\nconst TURN_COST = 1000;\n/** Traversing a cell another edge already used costs this many extra steps. */\nconst USED_COST = 24;\n/** Margin around the diagram bounds the search may roam into, in steps. */\nconst MARGIN = 8;\n\ntype Point = Scene.Point;\n\n/** Directions: right, down, left, up. */\nconst DX = [1, 0, -1, 0];\nconst DY = [0, 1, 0, -1];\n\nexport type AvoidingRouterOptions = {\n /** Search-cell size (scene px): a fraction of the layout grid, so routes can hug node borders. */\n step: number;\n};\n\n/**\n * Creates a router that avoids the given node rects. Stateful across edges: earlier routes\n * penalize (not block) the cells they occupy, spreading parallel runs apart. `fallback` handles\n * the (fenced-in) edges the search cannot reach. The step is passed in rather than derived from\n * `uml-grid`'s `GRID`, which keeps this module free of a value import cycle with the dialects.\n */\nexport const makeAvoidingRouter = (\n obstacles: Rect[],\n fallback: Router,\n { step: STEP }: AvoidingRouterOptions,\n): Router => {\n const xs = obstacles.flatMap((rect) => [rect.x, rect.x + rect.w]);\n const ys = obstacles.flatMap((rect) => [rect.y, rect.y + rect.h]);\n const bounds = {\n x0: Math.floor(Math.min(...xs) / STEP) - MARGIN,\n y0: Math.floor(Math.min(...ys) / STEP) - MARGIN,\n x1: Math.ceil(Math.max(...xs) / STEP) + MARGIN,\n y1: Math.ceil(Math.max(...ys) / STEP) + MARGIN,\n };\n const width = bounds.x1 - bounds.x0 + 1;\n const height = bounds.y1 - bounds.y0 + 1;\n const inBounds = (x: number, y: number) => x >= bounds.x0 && x <= bounds.x1 && y >= bounds.y0 && y <= bounds.y1;\n const cellIndex = (x: number, y: number) => (y - bounds.y0) * width + (x - bounds.x0);\n\n // Flat grids in place of per-cell string keys: the search touches every cell many times over and\n // the string building was half its running time.\n const blockedGrid = new Uint8Array(width * height);\n for (const rect of obstacles) {\n const x0 = Math.floor(rect.x / STEP) - CLEARANCE;\n const y0 = Math.floor(rect.y / STEP) - CLEARANCE;\n const x1 = Math.ceil((rect.x + rect.w) / STEP) + CLEARANCE;\n const y1 = Math.ceil((rect.y + rect.h) / STEP) + CLEARANCE;\n for (let y = Math.max(bounds.y0, y0 + 1); y < Math.min(bounds.y1 + 1, y1); y++) {\n for (let x = Math.max(bounds.x0, x0 + 1); x < Math.min(bounds.x1 + 1, x1); x++) {\n blockedGrid[cellIndex(x, y)] = 1;\n }\n }\n }\n const blocked = (x: number, y: number) => inBounds(x, y) && blockedGrid[cellIndex(x, y)] !== 0;\n const usedGrid = new Uint8Array(width * height);\n const isUsed = (x: number, y: number) => inBounds(x, y) && usedGrid[cellIndex(x, y)] !== 0;\n const markUsed = (x: number, y: number) => {\n if (inBounds(x, y)) {\n usedGrid[cellIndex(x, y)] = 1;\n }\n };\n // Settled costs per (cell, heading), reused across searches through a generation stamp so no\n // search pays to clear them.\n const settledCost = new Float64Array(width * height * 4);\n const settledGen = new Int32Array(width * height * 4);\n let generation = 0;\n\n /** `f` is cost + estimate, the heap's key. */\n type State = { x: number; y: number; dir: number; cost: number; f: number; prev?: State };\n type Terminal = { point: Point; dir: number };\n type Found = { cost: number; cells: Point[] };\n\n /** Binary min-heap on cost + estimate, so each pop is O(log n) instead of a frontier scan. */\n const heapPush = (heap: State[], state: State) => {\n heap.push(state);\n let index = heap.length - 1;\n while (index > 0) {\n const parent = (index - 1) >> 1;\n if (heap[parent].f <= heap[index].f) {\n break;\n }\n [heap[parent], heap[index]] = [heap[index], heap[parent]];\n index = parent;\n }\n };\n const heapPop = (heap: State[]): State => {\n const top = heap[0];\n const last = heap.pop()!;\n if (heap.length > 0) {\n heap[0] = last;\n let index = 0;\n for (;;) {\n const left = index * 2 + 1;\n const right = left + 1;\n let smallest = index;\n if (left < heap.length && heap[left].f < heap[smallest].f) {\n smallest = left;\n }\n if (right < heap.length && heap[right].f < heap[smallest].f) {\n smallest = right;\n }\n if (smallest === index) {\n break;\n }\n [heap[smallest], heap[index]] = [heap[index], heap[smallest]];\n index = smallest;\n }\n }\n return top;\n };\n\n /**\n * Fewest turns any path from (x, y) heading `dir` needs to reach the target: none while aligned\n * and heading at it, two when heading away along its axis, otherwise one. Admissible, and since\n * a turn costs as much as a thousand steps it is what makes the search converge on a diagram\n * hundreds of cells across — distance alone leaves it exploring almost uniformly.\n */\n const turnsNeeded = (x: number, y: number, dir: number, target: Point): number => {\n const dx = target.x - x;\n const dy = target.y - y;\n if (dx !== 0 && dy !== 0) {\n return 1;\n }\n if (dx === 0 && dy === 0) {\n return 0;\n }\n const towards = dx !== 0 ? (dx > 0 ? 0 : 2) : dy > 0 ? 1 : 3;\n return dir === towards ? 0 : (dir + 2) % 4 === towards ? 2 : 1;\n };\n\n const estimateFrom = (x: number, y: number, dir: number, target: Point): number =>\n Math.abs(target.x - x) + Math.abs(target.y - y) + turnsNeeded(x, y, dir, target) * TURN_COST;\n\n // Every cell in every heading, so a reachable target is never abandoned on a large diagram.\n const budget = Math.max(50_000, (bounds.x1 - bounds.x0) * (bounds.y1 - bounds.y0) * 4);\n\n /**\n * Bounded A* between two stub ends (grid coordinates). Successors already dominated by a\n * settled state are pruned before pushing; undefined when the target is unreachable.\n */\n const search = (source: Point, startDir: number, target: Point, endDir: number): Found | undefined => {\n const open: State[] = [\n { x: source.x, y: source.y, dir: startDir, cost: 0, f: estimateFrom(source.x, source.y, startDir, target) },\n ];\n generation++;\n const settledAt = (index: number) => (settledGen[index] === generation ? settledCost[index] : undefined);\n let found: State | undefined;\n\n for (let iterations = 0; open.length > 0 && iterations < budget; iterations++) {\n const current = heapPop(open);\n if (current.x === target.x && current.y === target.y) {\n found = current;\n break;\n }\n const stateIndex = cellIndex(current.x, current.y) * 4 + current.dir;\n const seen = settledAt(stateIndex);\n if (seen !== undefined && seen <= current.cost) {\n continue;\n }\n settledGen[stateIndex] = generation;\n settledCost[stateIndex] = current.cost;\n\n for (let dir = 0; dir < 4; dir++) {\n if ((dir + 2) % 4 === current.dir) {\n continue;\n }\n const x = current.x + DX[dir];\n const y = current.y + DY[dir];\n if (!inBounds(x, y)) {\n continue;\n }\n const cell = cellIndex(x, y);\n if (blockedGrid[cell] !== 0) {\n continue;\n }\n const cost =\n current.cost +\n 1 +\n (dir === current.dir ? 0 : TURN_COST) +\n (usedGrid[cell] !== 0 ? USED_COST : 0) +\n // Entering the target off-axis forces one more bend at arrival; fold it in.\n (x === target.x && y === target.y && dir !== endDir ? TURN_COST : 0);\n const dominated = settledAt(cell * 4 + dir);\n if (dominated !== undefined && dominated <= cost) {\n continue;\n }\n heapPush(open, { x, y, dir, cost, f: cost + estimateFrom(x, y, dir, target), prev: current });\n }\n }\n\n if (!found) {\n return undefined;\n }\n const cells: Point[] = [];\n for (let state: State | undefined = found; state; state = state.prev) {\n cells.unshift({ x: state.x, y: state.y });\n }\n return { cost: found.cost, cells };\n };\n\n return (edge: RoutedRelation): Point[] => {\n const { from, to, horizontal, ports } = edge;\n // Flow-axis faces mirror the Z-router (and the port assignment in `emit`).\n const sameLane = horizontal ? from.x === to.x : from.y === to.y;\n const alongY = horizontal ? sameLane : !sameLane;\n\n const down = to.y >= from.y;\n const right = to.x >= from.x;\n const flowStart: Terminal = alongY\n ? { point: { x: ports?.start ?? from.x + from.w / 2, y: down ? from.y + from.h : from.y }, dir: down ? 1 : 3 }\n : { point: { x: right ? from.x + from.w : from.x, y: ports?.start ?? from.y + from.h / 2 }, dir: right ? 0 : 2 };\n const flowEnd: Terminal = alongY\n ? { point: { x: ports?.end ?? to.x + to.w / 2, y: down ? to.y : to.y + to.h }, dir: down ? 1 : 3 }\n : { point: { x: right ? to.x : to.x + to.w, y: ports?.end ?? to.y + to.h / 2 }, dir: right ? 0 : 2 };\n // Cross-axis faces enable single-bend Ls when the displacement is diagonal — a fixed\n // flow-face pair forces a Z between laterally offset nodes.\n const crossStart: Terminal = alongY\n ? { point: { x: right ? from.x + from.w : from.x, y: from.y + from.h / 2 }, dir: right ? 0 : 2 }\n : { point: { x: from.x + from.w / 2, y: down ? from.y + from.h : from.y }, dir: down ? 1 : 3 };\n const crossEnd: Terminal = alongY\n ? { point: { x: right ? to.x : to.x + to.w, y: to.y + to.h / 2 }, dir: right ? 0 : 2 }\n : { point: { x: to.x + to.w / 2, y: down ? to.y : to.y + to.h }, dir: down ? 1 : 3 };\n\n const diagonal = alongY ? flowStart.point.x !== flowEnd.point.x : flowStart.point.y !== flowEnd.point.y;\n const configurations: [Terminal, Terminal][] = diagonal\n ? [\n [flowStart, flowEnd],\n [crossStart, flowEnd],\n [flowStart, crossEnd],\n ]\n : [[flowStart, flowEnd]];\n\n // Stubs step from the border past the clearance zone; A* runs between the stub ends.\n // Rounded to whole cells: ports may sit on exact fractional coordinates (collision fallback),\n // and a fractional goal cell would never match — the visible sub-cell offset lives in the\n // first/last segment.\n const stub = (point: Point, dir: number, out: boolean): Point => {\n const sign = out ? 1 : -1;\n return {\n x: Math.round(point.x / STEP) + DX[dir] * (CLEARANCE + 1) * sign,\n y: Math.round(point.y / STEP) + DY[dir] * (CLEARANCE + 1) * sign,\n };\n };\n\n let start: Point | undefined;\n let end: Point | undefined;\n let best: Found | undefined;\n for (const [startTerminal, endTerminal] of configurations) {\n const result = search(\n stub(startTerminal.point, startTerminal.dir, true),\n startTerminal.dir,\n stub(endTerminal.point, endTerminal.dir, false),\n endTerminal.dir,\n );\n if (result && (!best || result.cost < best.cost)) {\n best = result;\n start = startTerminal.point;\n end = endTerminal.point;\n }\n }\n if (!best || !start || !end) {\n return fallback(edge);\n }\n\n // Reconstruct and collapse collinear points; usage is marked from the FINAL path below, so\n // the centering pass can distinguish foreign channels from this edge's own cells.\n const points: Point[] = [start, ...best.cells.map((cell) => ({ x: cell.x * STEP, y: cell.y * STEP })), end];\n const simplified: Point[] = [points[0]];\n for (let index = 1; index < points.length - 1; index++) {\n const previous = simplified[simplified.length - 1];\n const next = points[index + 1];\n const point = points[index];\n const collinear =\n (previous.x === point.x && point.x === next.x) || (previous.y === point.y && point.y === next.y);\n if (!collinear) {\n simplified.push(point);\n }\n }\n simplified.push(points[points.length - 1]);\n\n // A single-jog Z centers its middle run equidistant from the two node borders — the A* path\n // is turn-minimal but expansion order lets it hug one node. Keep the shift only if the\n // adjusted segments avoid every obstacle AND every cell earlier edges already run through,\n // so parallel channels stay separated.\n const clearRun = (a: Point, b: Point): boolean => {\n const ax = Math.round(a.x / STEP);\n const ay = Math.round(a.y / STEP);\n const bx = Math.round(b.x / STEP);\n const by = Math.round(b.y / STEP);\n const steps = Math.max(Math.abs(bx - ax), Math.abs(by - ay));\n const dx = Math.sign(bx - ax);\n const dy = Math.sign(by - ay);\n for (let step = 0; step <= steps; step++) {\n if (blocked(ax + dx * step, ay + dy * step) || isUsed(ax + dx * step, ay + dy * step)) {\n return false;\n }\n }\n return true;\n };\n // Stub checks start past the terminal's own clearance zone, which is legitimately \"blocked\".\n const past = (from: Point, to: Point): Point => ({\n x: from.x + Math.sign(to.x - from.x) * (CLEARANCE + 1) * STEP,\n y: from.y + Math.sign(to.y - from.y) * (CLEARANCE + 1) * STEP,\n });\n if (simplified.length === 4) {\n const [p0, p1, p2, p3] = simplified;\n if (p1.y === p2.y && p0.y !== p3.y) {\n const mid = Math.round((p0.y + p3.y) / 2 / STEP) * STEP;\n const shifted = [\n { x: p1.x, y: mid },\n { x: p2.x, y: mid },\n ];\n if (\n clearRun(shifted[0], shifted[1]) &&\n clearRun(past(p0, shifted[0]), shifted[0]) &&\n clearRun(shifted[1], past(p3, shifted[1]))\n ) {\n simplified[1] = shifted[0];\n simplified[2] = shifted[1];\n }\n } else if (p1.x === p2.x && p0.x !== p3.x) {\n const mid = Math.round((p0.x + p3.x) / 2 / STEP) * STEP;\n const shifted = [\n { x: mid, y: p1.y },\n { x: mid, y: p2.y },\n ];\n if (\n clearRun(shifted[0], shifted[1]) &&\n clearRun(past(p0, shifted[0]), shifted[0]) &&\n clearRun(shifted[1], past(p3, shifted[1]))\n ) {\n simplified[1] = shifted[0];\n simplified[2] = shifted[1];\n }\n }\n }\n\n // Mark the final path's cells so later edges route (and center) around it.\n for (let index = 0; index < simplified.length - 1; index++) {\n const a = simplified[index];\n const b = simplified[index + 1];\n const ax = Math.round(a.x / STEP);\n const ay = Math.round(a.y / STEP);\n const steps = Math.max(Math.abs(Math.round(b.x / STEP) - ax), Math.abs(Math.round(b.y / STEP) - ay));\n const dx = Math.sign(b.x - a.x);\n const dy = Math.sign(b.y - a.y);\n for (let step = 0; step <= steps; step++) {\n markUsed(ax + dx * step, ay + dy * step);\n }\n }\n return simplified;\n };\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Mermaid class-diagram dialect: parses the subset needed for UML class diagrams (class blocks\n// with members, stereotypes, and the standard relation arrows) and compiles it to scene commands\n// with a layered layout — supertypes above subtypes. Mermaid carries no coordinates, so the\n// dialect owns placement; see `dialect.ts` for the contract.\n//\n\nimport * as Layout from './layout.ts';\nimport type * as Scene from './scene.ts';\n\nexport type Direction = 'TB' | 'BT' | 'LR' | 'RL';\n\nexport type UmlClass = {\n id: string;\n label: string;\n /** e.g. \"interface\", \"abstract\", \"enumeration\". */\n stereotype?: string;\n attributes: string[];\n methods: string[];\n};\n\nexport type RelationKind = 'inheritance' | 'realization' | 'composition' | 'aggregation' | 'association' | 'dependency';\n\n/** Rendered arrow direction: subtype → supertype, whole → part, source → target. */\nexport type UmlRelation = {\n from: string;\n to: string;\n kind: RelationKind;\n label?: string;\n fromCardinality?: string;\n toCardinality?: string;\n};\n\nexport type UmlModel = {\n direction: Direction;\n classes: UmlClass[];\n relations: UmlRelation[];\n};\n\nconst DIRECTIONS: Direction[] = ['TB', 'BT', 'LR', 'RL'];\n\n// `class Name`, `class Name[\"Label\"]`, `class Name {`.\nconst CLASS = /^class\\s+([A-Za-z0-9_~<>-]+)(?:\\s*\\[\\s*\"(.*?)\"\\s*\\])?\\s*(\\{)?\\s*$/;\n// `Name : +member` inline member declaration.\nconst INLINE_MEMBER = /^([A-Za-z0-9_~<>-]+)\\s*:\\s*(.+)$/;\nconst STEREOTYPE = /^<<\\s*(.*?)\\s*>>$/;\n\n/**\n * Relation arrows, normalized to (kind, whether the LEFT side is the arrow target).\n * `A <|-- B` reads \"B inherits A\": the parent is on the flat side of the triangle.\n */\nconst RELATIONS: [token: string, kind: RelationKind, leftIsTarget: boolean][] = [\n ['<|--', 'inheritance', true],\n ['--|>', 'inheritance', false],\n ['<|..', 'realization', true],\n ['..|>', 'realization', false],\n ['*--', 'composition', false],\n ['--*', 'composition', true],\n ['o--', 'aggregation', false],\n ['--o', 'aggregation', true],\n ['-->', 'association', false],\n ['<--', 'association', true],\n ['..>', 'dependency', false],\n ['<..', 'dependency', true],\n ['..', 'dependency', false],\n ['--', 'association', false],\n];\n\n// `A \"1\" <|-- \"many\" B : label` — cardinalities and the trailing label are optional.\nconst RELATION = new RegExp(\n '^([A-Za-z0-9_~<>-]+)\\\\s*(?:\"([^\"]*)\"\\\\s*)?' +\n `(${RELATIONS.map(([token]) => token.replace(/[|*.>-]/g, '\\\\$&')).join('|')})` +\n '\\\\s*(?:\"([^\"]*)\"\\\\s*)?([A-Za-z0-9_~<>-]+)\\\\s*(?::\\\\s*(.+))?$',\n);\n\n/** Mermaid generics use `~T~`; render them as `<T>`. */\nconst genericLabel = (id: string) => id.replace(/~([^~]*)~/g, '<$1>');\n\n/** Parse a mermaid class diagram into a neutral model. Unrecognised lines are ignored. */\nexport const parse = (source: string): UmlModel => {\n const classes = new Map<string, UmlClass>();\n const relations: UmlRelation[] = [];\n let direction: Direction = 'TB';\n let open: UmlClass | undefined;\n\n const declare = (id: string): UmlClass => {\n let entry = classes.get(id);\n if (!entry) {\n entry = { id, label: genericLabel(id), attributes: [], methods: [] };\n classes.set(id, entry);\n }\n return entry;\n };\n\n const addMember = (entry: UmlClass, raw: string) => {\n const member = raw.trim();\n const stereotype = STEREOTYPE.exec(member);\n if (stereotype) {\n entry.stereotype = stereotype[1];\n return;\n }\n if (member) {\n // A parameter list marks a method; everything else is an attribute.\n (member.includes('(') ? entry.methods : entry.attributes).push(member);\n }\n };\n\n for (const raw of source.split('\\n')) {\n const line = raw.trim();\n if (!line || line.startsWith('%%') || /^classDiagram(-v2)?$/.test(line)) {\n continue;\n }\n\n if (open) {\n if (line === '}') {\n open = undefined;\n } else {\n addMember(open, line);\n }\n continue;\n }\n\n const header = /^direction\\s+([A-Za-z]{2})$/.exec(line);\n if (header) {\n const value = header[1].toUpperCase() as Direction;\n direction = DIRECTIONS.includes(value) ? value : 'TB';\n continue;\n }\n\n const cls = CLASS.exec(line);\n if (cls) {\n const [, id, label, brace] = cls;\n const entry = declare(id);\n if (label) {\n entry.label = label;\n }\n if (brace) {\n open = entry;\n }\n continue;\n }\n\n const relation = RELATION.exec(line);\n if (relation) {\n const [, left, leftCardinality, token, rightCardinality, right, label] = relation;\n declare(left);\n declare(right);\n const [, kind, leftIsTarget] = RELATIONS.find(([candidate]) => candidate === token)!;\n const [from, to] = leftIsTarget ? [right, left] : [left, right];\n const [fromCardinality, toCardinality] = leftIsTarget\n ? [rightCardinality, leftCardinality]\n : [leftCardinality, rightCardinality];\n relations.push({\n from,\n to,\n kind,\n ...(label ? { label: label.trim() } : {}),\n ...(fromCardinality ? { fromCardinality } : {}),\n ...(toCardinality ? { toCardinality } : {}),\n });\n continue;\n }\n\n const inline = INLINE_MEMBER.exec(line);\n if (inline) {\n const [, id, member] = inline;\n addMember(declare(id), member);\n }\n }\n\n return { direction, classes: [...classes.values()], relations };\n};\n\n/**\n * Box geometry in scene units; text sizes come from the shared per-weight metrics table\n * (`Layout.FONT_METRICS`): the title renders at the default weight (m), members at s.\n */\nconst TITLE_FONT = Layout.FONT_METRICS.m;\nconst MEMBER_FONT = Layout.FONT_METRICS.s;\nconst MIN_W = 160;\nconst MAX_W = 400;\nconst PAD_X = 24;\nconst TITLE_PAD = 10;\nconst SECTION_PAD = 14;\nconst GAP_MAIN = 90;\nconst GAP_CROSS = 60;\n\ntype ClassBox = {\n entry: UmlClass;\n w: number;\n h: number;\n titleH: number;\n attributesH: number;\n methodsH: number;\n};\n\n/** Compartment sizes derived from member counts and line lengths, per compartment font. */\nconst measure = (entry: UmlClass, maxWidth: number): ClassBox => {\n const titleW = Math.max(entry.label.length, (entry.stereotype?.length ?? 0) + 2) * TITLE_FONT.charW;\n const memberW =\n Math.max(0, ...[...entry.attributes, ...entry.methods].map((line) => line.length)) * MEMBER_FONT.charW;\n const w = Math.min(maxWidth, Math.max(MIN_W, Math.ceil(Math.max(titleW, memberW)) + PAD_X));\n // Lines wider than the clamped box wrap in the renderer; count the extra lines so the\n // compartment is tall enough and tldraw does not grow it over the one below.\n const lines = (text: string, font: Layout.FontMetrics) =>\n Math.max(1, Math.ceil((text.length * font.charW) / (w - PAD_X)));\n const memberH = (members: string[]) =>\n members.length\n ? members.reduce((sum, line) => sum + lines(line, MEMBER_FONT), 0) * MEMBER_FONT.lineH + SECTION_PAD\n : 0;\n const titleH = (lines(entry.label, TITLE_FONT) + (entry.stereotype ? 1 : 0)) * TITLE_FONT.lineH + TITLE_PAD;\n const attributesH = memberH(entry.attributes);\n const methodsH = memberH(entry.methods);\n return { entry, w, h: titleH + attributesH + methodsH, titleH, attributesH, methodsH };\n};\n\n/** Arrow styling per relation kind; dependency and realization render dashed, as in UML. */\nexport const relationStyle = (kind: RelationKind): { stroke?: Scene.Stroke } =>\n kind === 'dependency' || kind === 'realization' ? { stroke: 'dashed' } : {};\n\n/** Mid-arrow label: cardinalities and the diamond glyph UML puts at the whole end. */\nexport const relationText = (relation: UmlRelation): string | undefined => {\n const glyph = relation.kind === 'composition' ? '◆' : relation.kind === 'aggregation' ? '◇' : undefined;\n const text = [relation.fromCardinality, relation.label ?? glyph, relation.toCardinality].filter(Boolean).join(' ');\n return text || undefined;\n};\n\n/**\n * Rank so arrows read upward where UML convention points at abstractions — inheritance,\n * realization, and dependency targets sit above their sources; containment and association\n * flow downward (whole/source above part/target).\n */\nexport const relationRanks = (model: UmlModel): Map<string, number> =>\n Layout.rank(\n model.classes.map((entry) => entry.id),\n model.relations.map((relation) =>\n relation.kind === 'inheritance' || relation.kind === 'realization' || relation.kind === 'dependency'\n ? { from: relation.to, to: relation.from }\n : { from: relation.from, to: relation.to },\n ),\n );\n\nexport type CompileOptions = {\n /** Canvas position of the diagram's top-left, in canvas px. */\n origin?: Scene.Point;\n /** Canvas px per scene unit. */\n scale?: number;\n /** Gap between ranks along the flow direction, in scene units (default 90). */\n gapMain?: number;\n /** Gap between classes within a rank, in scene units (default 60). */\n gapCross?: number;\n /** Maximum class-box width, in scene units (default 400); longer lines wrap. */\n maxWidth?: number;\n};\n\n/**\n * Compile a mermaid class diagram into scene commands: one world object per class (compartment\n * rects `title`/`attributes`/`methods`) and an `edges` object holding the relations as bound\n * arrows. Supertypes rank above subtypes, so inheritance reads downward.\n */\nexport const compile = (source: string, options: CompileOptions = {}): Scene.Command[] => {\n const model = parse(source);\n const { origin = { x: 0, y: 0 }, scale = 1, gapMain = GAP_MAIN, gapCross = GAP_CROSS, maxWidth = MAX_W } = options;\n const horizontal = model.direction === 'LR' || model.direction === 'RL';\n\n const ranks = relationRanks(model);\n\n const boxes = new Map(model.classes.map((entry) => [entry.id, measure(entry, maxWidth)]));\n\n // Group classes by rank, preserving declaration order within each lane.\n const lanes = new Map<number, ClassBox[]>();\n for (const entry of model.classes) {\n const value = ranks.get(entry.id) ?? 0;\n lanes.set(value, [...(lanes.get(value) ?? []), boxes.get(entry.id)!]);\n }\n\n const cross = (box: ClassBox) => (horizontal ? box.h : box.w);\n const main = (box: ClassBox) => (horizontal ? box.w : box.h);\n const laneSpan = (members: ClassBox[]) =>\n members.reduce((sum, box) => sum + cross(box), 0) + (members.length - 1) * gapCross;\n const widest = Math.max(...[...lanes.values()].map(laneSpan), 0);\n\n // Lanes advance along the main axis by their tallest member; members center on the widest lane.\n const positions = new Map<string, Scene.Point>();\n let mainOffset = 0;\n for (const lane of [...lanes.keys()].sort((left, right) => left - right)) {\n const members = lanes.get(lane)!;\n let crossOffset = (widest - laneSpan(members)) / 2;\n for (const box of members) {\n positions.set(box.entry.id, horizontal ? { x: mainOffset, y: crossOffset } : { x: crossOffset, y: mainOffset });\n crossOffset += cross(box) + gapCross;\n }\n mainOffset += Math.max(...members.map(main)) + gapMain;\n }\n\n // Arrow terminals clip at the bound compartment, so each endpoint binds to the compartment\n // nearest the peer's center — the arrow meets the box's outer edge instead of crossing the\n // compartments between that edge and the title, and mid-arrow labels land in the rank gap.\n const facing = (id: string, peerId: string): string => {\n const box = boxes.get(id)!;\n const peer = boxes.get(peerId)!;\n const targetY = positions.get(peerId)!.y + peer.h / 2;\n const baseY = positions.get(id)!.y;\n const compartments: [elementId: string, centerY: number][] = [['title', box.titleH / 2]];\n if (box.attributesH) {\n compartments.push(['attributes', box.titleH + box.attributesH / 2]);\n }\n if (box.methodsH) {\n compartments.push(['methods', box.titleH + box.attributesH + box.methodsH / 2]);\n }\n return compartments.reduce((best, candidate) =>\n Math.abs(baseY + candidate[1] - targetY) < Math.abs(baseY + best[1] - targetY) ? candidate : best,\n )[0];\n };\n\n const commands: Scene.Command[] = [];\n\n for (const entry of model.classes) {\n const box = boxes.get(entry.id)!;\n const point = positions.get(entry.id)!;\n const title = entry.stereotype ? `«${entry.stereotype}»\\n${entry.label}` : entry.label;\n const elements: Scene.Element[] = [\n { kind: 'rect', id: 'title', x: 0, y: 0, w: box.w, h: box.titleH, text: title, fill: 'solid' },\n ];\n if (box.attributesH) {\n elements.push({\n kind: 'rect',\n id: 'attributes',\n x: 0,\n y: box.titleH,\n w: box.w,\n h: box.attributesH,\n text: entry.attributes.join('\\n'),\n weight: 's',\n });\n }\n if (box.methodsH) {\n elements.push({\n kind: 'rect',\n id: 'methods',\n x: 0,\n y: box.titleH + box.attributesH,\n w: box.w,\n h: box.methodsH,\n text: entry.methods.join('\\n'),\n weight: 's',\n });\n }\n commands.push({\n op: 'upsert-object',\n object: {\n id: entry.id,\n origin: { x: origin.x + point.x * scale, y: origin.y + point.y * scale },\n scale,\n elements,\n },\n });\n }\n\n if (model.relations.length > 0) {\n commands.push({\n op: 'upsert-object',\n object: {\n id: 'edges',\n origin,\n scale,\n elements: model.relations.map((relation, index) => {\n const text = relationText(relation);\n return {\n kind: 'arrow' as const,\n id: `${relation.from}-${relation.to}-${index}`,\n from: `${relation.from}/${facing(relation.from, relation.to)}`,\n to: `${relation.to}/${facing(relation.to, relation.from)}`,\n ...relationStyle(relation.kind),\n ...(text ? { text } : {}),\n };\n }),\n },\n });\n }\n\n return commands;\n};\n\n/** True when the mermaid source declares a class diagram rather than a flowchart. */\nexport const isClassDiagram = (source: string): boolean => /^\\s*classDiagram(-v2)?\\b/m.test(source);\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Grid variant of the UML class-diagram dialect: every class renders as an equal-size node\n// (uniform cell sized to the largest class) placed on a fixed grid, and relations render as\n// orthogonally routed connectors. Routing is pluggable via `CompileOptions.route` so callers\n// can substitute channel assignment or full obstacle-avoiding routers later.\n//\n\nimport * as Layout from './layout.ts';\nimport { makeAvoidingRouter } from './ortho-router.ts';\nimport type * as Scene from './scene.ts';\nimport { type UmlModel, type UmlRelation, parse, relationRanks, relationStyle, relationText } from './uml.ts';\n\n/**\n * Snap unit for cells, gaps, and positions, chosen so node edges land on the grid lines tldraw\n * renders at working zoom (it draws lines at power-of-two multiples of its document gridSize).\n */\nexport const GRID = 32;\n\n/** Half-cell minor grid, used for sub-cell nudges (ports, channel separation, label offsets). */\nconst GRID_FINE = GRID / 2;\n\nconst MIN_W = GRID * 2;\nconst MAX_W = GRID * 6;\n\nconst MIN_H = GRID * 2;\nconst MAX_H = GRID * 5;\n\nconst MIN_TITLE_H = GRID;\nconst MAX_TITLE_H = GRID * 2;\n\nconst TITLE_PAD = GRID / 2;\nconst TEXT_PAD = GRID_FINE * 1;\nconst PAD_X = GRID * 2;\nconst SECTION_PAD = GRID / 2;\nconst GAP_MAIN = GRID * 4;\nconst GAP_CROSS = GRID * 4;\n\nconst TITLE_FONT = Layout.FONT_METRICS.m;\nconst MEMBER_FONT = Layout.FONT_METRICS.s;\n\nconst snap = (value: number) => Math.ceil(value / GRID) * GRID;\n\n/** Node rect in scene units. */\nexport type Rect = {\n x: number;\n y: number;\n w: number;\n h: number;\n};\n\nexport type RoutedRelation = {\n /** The edge being routed; routers read only its endpoints, so any dialect's edge type fits. */\n relation: Layout.LayoutEdge;\n from: Rect;\n to: Rect;\n /** True when the diagram flows LR/RL, so ranks stack along x. */\n horizontal: boolean;\n /** Channel slot among relations sharing a gutter, centered on it (shift = offset × GRID_FINE). */\n offset: number;\n /** Terminal cross-axis coordinates (port positions); node-edge centers when omitted. */\n ports?: { start?: number; end?: number };\n};\n\n/**\n * Produces the connector waypoints for one relation, in scene units. The returned polyline is\n * rendered verbatim (last segment carries the arrowhead), so a router fully controls the path.\n */\nexport type Router = (edge: RoutedRelation) => Scene.Point[];\n\n/** Z route along y: leave the facing horizontal edge, run a channel at mid, enter the peer's. */\nconst routeAlongY = (from: Rect, to: Rect, shift: number, ports?: RoutedRelation['ports']): Scene.Point[] => {\n const down = to.y >= from.y;\n const start = { x: ports?.start ?? from.x + from.w / 2, y: down ? from.y + from.h : from.y };\n const end = { x: ports?.end ?? to.x + to.w / 2, y: down ? to.y : to.y + to.h };\n if (start.x === end.x) {\n // Aligned terminals: a straight line, shifted sideways so parallel edges stay distinct.\n return [\n { x: start.x + shift, y: start.y },\n { x: end.x + shift, y: end.y },\n ];\n }\n const mid = snap((start.y + end.y) / 2) + shift;\n return [start, { x: start.x, y: mid }, { x: end.x, y: mid }, end];\n};\n\n/** Z route along x; mirror of `routeAlongY`. */\nconst routeAlongX = (from: Rect, to: Rect, shift: number, ports?: RoutedRelation['ports']): Scene.Point[] => {\n const right = to.x >= from.x;\n const start = { x: right ? from.x + from.w : from.x, y: ports?.start ?? from.y + from.h / 2 };\n const end = { x: right ? to.x : to.x + to.w, y: ports?.end ?? to.y + to.h / 2 };\n if (start.y === end.y) {\n return [\n { x: start.x, y: start.y + shift },\n { x: end.x, y: end.y + shift },\n ];\n }\n const mid = snap((start.x + end.x) / 2) + shift;\n return [start, { x: mid, y: start.y }, { x: mid, y: end.y }, end];\n};\n\n/**\n * Default router: an orthogonal Z along the flow axis — rank-crossing edges route through the\n * inter-rank gutter (channel shifted per parallel edge); same-rank edges route out the side.\n */\nexport const zRouter: Router = ({ from, to, offset, horizontal, ports }) => {\n const sameLane = horizontal ? from.x === to.x : from.y === to.y;\n const alongY = horizontal ? sameLane : !sameLane;\n return (alongY ? routeAlongY : routeAlongX)(from, to, offset * GRID_FINE, ports);\n};\n\n/**\n * Pull strength per relation kind when aligning columns: parts stick to their whole's column\n * before subtypes, which in turn beat loose dependencies/associations.\n */\nconst COLUMN_WEIGHT: Record<UmlRelation['kind'], number> = {\n composition: 4,\n aggregation: 3,\n inheritance: 2,\n realization: 2,\n dependency: 1,\n association: 1,\n};\n\n/**\n * Assign each node an integer column: the first lane keeps declaration order, later lanes pull\n * each node toward the weighted mean column of its already-placed neighbours. The strongest-tied\n * node picks its column first, so a part claims the column under its whole even when weaker\n * relations compete for it; collisions take the free column nearest the desired mean. Aligned\n * columns turn rank-crossing connectors into straight lines.\n */\nconst assignColumns = (\n model: UmlModel,\n ranks: Map<string, number>,\n lanes: Map<number, string[]>,\n): Map<string, number> => {\n type Link = { peer: string; weight: number };\n const neighbors = new Map<string, Link[]>();\n for (const relation of model.relations) {\n const weight = COLUMN_WEIGHT[relation.kind];\n neighbors.set(relation.from, [...(neighbors.get(relation.from) ?? []), { peer: relation.to, weight }]);\n neighbors.set(relation.to, [...(neighbors.get(relation.to) ?? []), { peer: relation.from, weight }]);\n }\n\n const columns = new Map<string, number>();\n const laneOrder = [...lanes.keys()].sort((left, right) => left - right);\n laneOrder.forEach((lane, position) => {\n const members = lanes.get(lane)!;\n const desired = members.map((id, index) => {\n const placed = (neighbors.get(id) ?? []).filter((link) => columns.has(link.peer));\n const pull = placed.reduce((sum, link) => sum + link.weight, 0);\n const mean =\n position > 0 && pull > 0\n ? placed.reduce((sum, link) => sum + link.weight * columns.get(link.peer)!, 0) / pull\n : index;\n return { id, mean, pull, index };\n });\n desired.sort((left, right) => right.pull - left.pull || left.index - right.index);\n const used = new Set<number>();\n for (const entry of desired) {\n // Round half toward the left so a node between two equal parents aligns with the first;\n // on collision take the free column nearest the desired mean.\n const base = Math.ceil(entry.mean - 0.5);\n let column = base;\n for (let step = 1; used.has(column); step++) {\n const left = base - step;\n const right = base + step;\n if (!used.has(left) && (used.has(right) || Math.abs(left - entry.mean) <= Math.abs(right - entry.mean))) {\n column = left;\n } else if (!used.has(right)) {\n column = right;\n }\n }\n used.add(column);\n columns.set(entry.id, column);\n }\n });\n\n // Normalize so the leftmost column is 0.\n const min = Math.min(...columns.values(), 0);\n return new Map([...columns].map(([id, column]) => [id, column - min]));\n};\n\n/** Fixed cell size, in scene units; omitted dimensions are measured from content. */\nexport type CellSize = { w?: number; h?: number };\n\nexport type Cell = { w: number; h: number; titleH: number };\n\nexport type MeasureOptions = {\n maxWidth: number;\n cell?: CellSize;\n titleHeight?: number;\n};\n\n/** One cell fits the largest class: widest line (wrapped at maxWidth) and tallest member list. */\nexport const measureCell = (model: UmlModel, { maxWidth, cell: override = {}, titleHeight }: MeasureOptions): Cell => {\n const memberLines = (entry: UmlModel['classes'][number]) => [...entry.attributes, ...entry.methods];\n const titleW =\n Math.max(0, ...model.classes.map((entry) => Math.max(entry.label.length, (entry.stereotype?.length ?? 0) + 2))) *\n TITLE_FONT.charW;\n const memberW =\n Math.max(0, ...model.classes.flatMap((entry) => memberLines(entry).map((line) => line.length))) * MEMBER_FONT.charW;\n const w = snap(override.w ?? Math.min(maxWidth, Math.max(MIN_W, Math.ceil(Math.max(titleW, memberW)) + PAD_X)));\n const wrapped = (length: number, font: Layout.FontMetrics) =>\n Math.max(1, Math.ceil((length * font.charW) / (w - TEXT_PAD * 2)));\n const titleLines = Math.max(\n 1,\n ...model.classes.map((entry) => wrapped(entry.label.length, TITLE_FONT) + (entry.stereotype ? 1 : 0)),\n );\n const bodyLines = Math.max(\n 1,\n ...model.classes.map(\n (entry) =>\n memberLines(entry).reduce((sum, line) => sum + wrapped(line.length, MEMBER_FONT), 0) +\n // The emitted body inserts a blank separator line between attributes and methods.\n (entry.attributes.length && entry.methods.length ? 1 : 0),\n ),\n );\n // A fixed header snaps to the fine grid so it can sit below one GRID cell; the measured\n // default clamps to the GRID-derived title bounds.\n const titleH =\n titleHeight !== undefined\n ? Math.ceil(titleHeight / GRID_FINE) * GRID_FINE\n : Math.min(MAX_TITLE_H, Math.max(MIN_TITLE_H, snap(titleLines * TITLE_FONT.lineH + TITLE_PAD)));\n const bodyH = snap(bodyLines * MEMBER_FONT.lineH + SECTION_PAD);\n // Measured height clamps to the GRID-derived bounds (very large classes cap at MAX_H and may\n // elide content); an explicit override wins, still reserving the title bar.\n const measured = Math.min(MAX_H, Math.max(MIN_H, titleH + bodyH));\n const h = override.h !== undefined ? Math.max(snap(override.h), titleH + GRID) : measured;\n return { w, h, titleH };\n};\n\nexport type CompileOptions = {\n /** Canvas position of the diagram's top-left, in canvas px. */\n origin?: Scene.Point;\n /** Canvas px per scene unit. */\n scale?: number;\n /** Gap between ranks along the flow direction, in scene units (default GRID × 4, snapped). */\n gapMain?: number;\n /** Gap between classes within a rank, in scene units (default GRID × 4, snapped). */\n gapCross?: number;\n /** Maximum cell width, in scene units (default GRID × 6); longer lines wrap. */\n maxWidth?: number;\n /** Fixed cell size (snapped to GRID); overrides measurement per dimension. */\n cell?: CellSize;\n /** Fixed header height, in scene units (snapped to the fine grid); measured when unset. */\n titleHeight?: number;\n /** Connector routing (default `zRouter`). */\n route?: Router;\n};\n\n/** A placed diagram: the parsed model plus per-class node rects (scene units). */\nexport type Placement = {\n model: UmlModel;\n cell: Cell;\n rects: Map<string, Rect>;\n ranks: Map<string, number>;\n};\n\nexport type EmitOptions = {\n origin?: Scene.Point;\n scale?: number;\n route?: Router;\n};\n\n/**\n * Compile a mermaid class diagram into scene commands with equal-size grid-aligned nodes: per\n * class a `title` bar plus a `body` compartment filling the cell, and an `edges` object holding\n * orthogonal connector paths (polyline waypoints, an arrowhead segment, and a floating label).\n */\nexport const compile = (source: string, options: CompileOptions = {}): Scene.Command[] => {\n const model = parse(source);\n const { origin = { x: 0, y: 0 }, scale = 1, maxWidth = MAX_W, route } = options;\n const gapMain = snap(options.gapMain ?? GAP_MAIN);\n const gapCross = snap(options.gapCross ?? GAP_CROSS);\n const horizontal = model.direction === 'LR' || model.direction === 'RL';\n const cell = measureCell(model, { maxWidth, cell: options.cell, titleHeight: options.titleHeight });\n const ranks = relationRanks(model);\n\n const lanes = new Map<number, string[]>();\n for (const entry of model.classes) {\n const value = ranks.get(entry.id) ?? 0;\n lanes.set(value, [...(lanes.get(value) ?? []), entry.id]);\n }\n\n // Uniform cells make lanes a plain grid: nodes take shared integer columns (aligned via their\n // neighbours) so as many connectors as possible run straight through the gutters.\n const cross = horizontal ? cell.h : cell.w;\n const main = horizontal ? cell.w : cell.h;\n const columns = assignColumns(model, ranks, lanes);\n const rects = new Map<string, Rect>();\n for (const [lane, members] of lanes) {\n for (const id of members) {\n const crossOffset = columns.get(id)! * (cross + gapCross);\n const mainOffset = lane * (main + gapMain);\n rects.set(id, {\n x: horizontal ? mainOffset : crossOffset,\n y: horizontal ? crossOffset : mainOffset,\n w: cell.w,\n h: cell.h,\n });\n }\n }\n\n return emit({ model, cell, rects, ranks }, { origin, scale, route });\n};\n\n/**\n * Emit scene commands from a placed model — the shared back half of `compile`, also used by the\n * engine-backed dialects (`uml-engine.ts`) which supply their own placement.\n */\nexport const emit = (\n { model, cell, rects, ranks }: Placement,\n { origin = { x: 0, y: 0 }, scale = 1, route }: EmitOptions = {},\n): Scene.Command[] => {\n const horizontal = model.direction === 'LR' || model.direction === 'RL';\n // Default routing avoids every node (fewest turns), falling back to the Z-router per edge.\n const router = route ?? makeAvoidingRouter([...rects.values()], zRouter, { step: GRID / 4 });\n const commands: Scene.Command[] = [];\n\n for (const entry of model.classes) {\n const rect = rects.get(entry.id)!;\n const title = entry.stereotype ? `«${entry.stereotype}»\\n${entry.label}` : entry.label;\n const members = [\n ...entry.attributes,\n ...(entry.attributes.length && entry.methods.length ? [''] : []),\n ...entry.methods,\n ].join('\\n');\n commands.push({\n op: 'upsert-object',\n object: {\n id: entry.id,\n origin: { x: origin.x + rect.x * scale, y: origin.y + rect.y * scale },\n scale,\n // One rounded frame encapsulates the node; the header rounds only its top corners so it\n // sits flush against the frame, and members render as free left-aligned text below it.\n elements: [\n { kind: 'rect', id: 'frame', x: 0, y: 0, w: cell.w, h: cell.h },\n {\n kind: 'rect',\n id: 'title',\n x: 0,\n y: 0,\n w: cell.w,\n h: cell.titleH,\n text: title,\n fill: 'solid',\n corners: 'top',\n },\n ...(members\n ? [\n {\n kind: 'text',\n id: 'body',\n x: TEXT_PAD,\n y: cell.titleH + SECTION_PAD / 2,\n w: cell.w - TEXT_PAD * 2,\n text: members,\n weight: 's',\n } satisfies Scene.Text,\n ]\n : []),\n ],\n },\n });\n }\n\n if (model.relations.length > 0) {\n // A route's channel run sits on the gutter line at the midpoint between its terminals, so ALL\n // edges sharing that line — not just those between the same rank pair — must take distinct\n // channels or their runs overlap. Straight edges (aligned terminals) share the column/row line\n // instead, and the router shifts them sideways. Offsets center each block on its line.\n const gutterOf = (relation: UmlRelation): string => {\n const from = rects.get(relation.from)!;\n const to = rects.get(relation.to)!;\n const sameLane = horizontal ? from.x === to.x : from.y === to.y;\n const alongY = horizontal ? sameLane : !sameLane;\n if (alongY) {\n if (from.x + from.w / 2 === to.x + to.w / 2) {\n return `v:${from.x + from.w / 2}`;\n }\n const startY = to.y >= from.y ? from.y + from.h : from.y;\n const endY = to.y >= from.y ? to.y : to.y + to.h;\n return `y:${snap((startY + endY) / 2)}`;\n }\n if (from.y + from.h / 2 === to.y + to.h / 2) {\n return `h:${from.y + from.h / 2}`;\n }\n const startX = to.x >= from.x ? from.x + from.w : from.x;\n const endX = to.x >= from.x ? to.x : to.x + to.w;\n return `x:${snap((startX + endX) / 2)}`;\n };\n\n const gutters = new Map<string, number>();\n for (const relation of model.relations) {\n const gutter = gutterOf(relation);\n gutters.set(gutter, (gutters.get(gutter) ?? 0) + 1);\n }\n\n // Port distribution: terminals attaching to the same node side spread across it (ordered by\n // peer position) instead of stacking on the center — the final approach segments of distinct\n // relations would otherwise coincide exactly.\n type PortSlot = { relation: UmlRelation; end: boolean; order: number };\n const portGroups = new Map<string, PortSlot[]>();\n const addSlot = (key: string, slot: PortSlot) => portGroups.set(key, [...(portGroups.get(key) ?? []), slot]);\n for (const relation of model.relations) {\n const from = rects.get(relation.from)!;\n const to = rects.get(relation.to)!;\n const sameLane = horizontal ? from.x === to.x : from.y === to.y;\n const alongY = horizontal ? sameLane : !sameLane;\n if (alongY) {\n const down = to.y >= from.y;\n addSlot(`${relation.from}:${down ? 'bottom' : 'top'}`, { relation, end: false, order: to.x + to.w / 2 });\n addSlot(`${relation.to}:${down ? 'top' : 'bottom'}`, { relation, end: true, order: from.x + from.w / 2 });\n } else {\n const right = to.x >= from.x;\n addSlot(`${relation.from}:${right ? 'right' : 'left'}`, { relation, end: false, order: to.y + to.h / 2 });\n addSlot(`${relation.to}:${right ? 'left' : 'right'}`, { relation, end: true, order: from.y + from.h / 2 });\n }\n }\n const ports = new Map<UmlRelation, { start?: number; end?: number }>();\n for (const [key, slots] of portGroups) {\n if (slots.length < 2) {\n continue;\n }\n const nodeId = key.slice(0, key.lastIndexOf(':'));\n const rect = rects.get(nodeId)!;\n const across = key.endsWith(':top') || key.endsWith(':bottom');\n slots.sort((left, right) => left.order - right.order);\n // Dense sides can round two slots onto the same minor-grid line; fall back to the exact\n // fractional coordinate so ports stay collision-free (and monotone in slot order).\n const taken = new Set<number>();\n slots.forEach((slot, index) => {\n const fraction = (index + 1) / (slots.length + 1);\n const exact = across ? rect.x + rect.w * fraction : rect.y + rect.h * fraction;\n const rounded = Math.round(exact / GRID_FINE) * GRID_FINE;\n const coord = taken.has(rounded) ? exact : rounded;\n taken.add(coord);\n const entry = ports.get(slot.relation) ?? {};\n entry[slot.end ? 'end' : 'start'] = coord;\n ports.set(slot.relation, entry);\n });\n }\n\n // Straightening: when a relation's nodes overlap on the cross axis, snap both terminals to a\n // shared free coordinate so the connector runs straight — a jog between stacked (or abreast)\n // nodes reads as noise. The spread ports above are the collision set; singles sit on centers.\n const takenBySide = new Map<string, Map<UmlRelation, number>>();\n for (const [key, slots] of portGroups) {\n const nodeId = key.slice(0, key.lastIndexOf(':'));\n const rect = rects.get(nodeId)!;\n const across = key.endsWith(':top') || key.endsWith(':bottom');\n const coords = new Map<UmlRelation, number>();\n for (const slot of slots) {\n const port = ports.get(slot.relation)?.[slot.end ? 'end' : 'start'];\n coords.set(slot.relation, port ?? (across ? rect.x + rect.w / 2 : rect.y + rect.h / 2));\n }\n takenBySide.set(key, coords);\n }\n const fineSnap = (value: number) => Math.round(value / GRID_FINE) * GRID_FINE;\n for (const relation of model.relations) {\n const from = rects.get(relation.from)!;\n const to = rects.get(relation.to)!;\n const sameLane = horizontal ? from.x === to.x : from.y === to.y;\n const alongY = horizontal ? sameLane : !sameLane;\n const lo = alongY ? Math.max(from.x, to.x) + GRID_FINE : Math.max(from.y, to.y) + GRID_FINE;\n const hi = alongY\n ? Math.min(from.x + from.w, to.x + to.w) - GRID_FINE\n : Math.min(from.y + from.h, to.y + to.h) - GRID_FINE;\n if (lo > hi) {\n continue;\n }\n const startKey = alongY\n ? `${relation.from}:${to.y >= from.y ? 'bottom' : 'top'}`\n : `${relation.from}:${to.x >= from.x ? 'right' : 'left'}`;\n const endKey = alongY\n ? `${relation.to}:${to.y >= from.y ? 'top' : 'bottom'}`\n : `${relation.to}:${to.x >= from.x ? 'left' : 'right'}`;\n const entry = ports.get(relation) ?? {};\n const startCoord = entry.start ?? (alongY ? from.x + from.w / 2 : from.y + from.h / 2);\n const endCoord = entry.end ?? (alongY ? to.x + to.w / 2 : to.y + to.h / 2);\n const isFree = (coord: number) =>\n ![startKey, endKey].some((side) =>\n [...(takenBySide.get(side) ?? new Map<UmlRelation, number>())].some(\n ([peer, taken]) => peer !== relation && Math.abs(taken - coord) < GRID_FINE,\n ),\n );\n const base = Math.min(hi, Math.max(lo, fineSnap((startCoord + endCoord) / 2)));\n let chosen: number | undefined;\n for (let step = 0; step <= Math.ceil((hi - lo) / GRID_FINE) && chosen === undefined; step++) {\n for (const candidate of step === 0 ? [base] : [base - step * GRID_FINE, base + step * GRID_FINE]) {\n if (candidate >= lo && candidate <= hi && isFree(candidate)) {\n chosen = candidate;\n break;\n }\n }\n }\n if (chosen === undefined) {\n continue;\n }\n entry.start = chosen;\n entry.end = chosen;\n ports.set(relation, entry);\n takenBySide.get(startKey)?.set(relation, chosen);\n takenBySide.get(endKey)?.set(relation, chosen);\n }\n\n const assigned = new Map<string, number>();\n const elements: Scene.Element[] = [];\n model.relations.forEach((relation, index) => {\n const gutter = gutterOf(relation);\n const position = assigned.get(gutter) ?? 0;\n assigned.set(gutter, position + 1);\n // Integer slots so every jog stays on the minor grid (shift = offset × GRID_FINE).\n const offset = position - Math.floor((gutters.get(gutter)! - 1) / 2);\n const points = router({\n relation,\n from: rects.get(relation.from)!,\n to: rects.get(relation.to)!,\n horizontal,\n offset,\n ports: ports.get(relation),\n });\n const id = `${relation.from}-${relation.to}-${index}`;\n const style = relationStyle(relation.kind);\n // The final segment renders as an arrow for the head; earlier waypoints as a polyline.\n if (points.length > 2) {\n elements.push({ kind: 'line', id: `${id}-path`, points: points.slice(0, -1), ...style });\n }\n elements.push({\n kind: 'arrow',\n id,\n start: points[points.length - 2],\n end: points[points.length - 1],\n ...style,\n });\n const text = relationText(relation);\n if (text) {\n // Label sits just above the middle segment (the channel run on a routed path).\n const head = points[Math.floor(points.length / 2) - 1];\n const tail = points[Math.floor(points.length / 2)];\n elements.push({\n kind: 'text',\n id: `${id}-label`,\n x: (head.x + tail.x) / 2 + GRID_FINE / 2,\n y: (head.y + tail.y) / 2 - MEMBER_FONT.lineH,\n text,\n weight: 's',\n });\n }\n });\n commands.push({ op: 'upsert-object', object: { id: 'edges', origin, scale, elements } });\n }\n\n return commands;\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// The layout objective: how heuristics are expressed. A heuristic is either a CONSTRAINT (hard —\n// a layout that violates it is not acceptable) or a COST TERM (soft — weighted, minimized). Both\n// are evaluated over the emitted scene through `Diagnostics`, so the objective that picks a layout\n// and the report that grades one are the same measurements. Engines and rules are candidate\n// generators; the objective is the judge. See `docs/DESIGN.md`.\n//\n\nimport { invariant } from '@dxos/invariant';\n\nimport type * as Diagnostics from './diagnostics.ts';\nimport type * as Scene from './scene.ts';\nimport { GRID } from './uml-grid.ts';\n\n/** A candidate layout: the scene plus its analysis. */\nexport type Layout = {\n objects: readonly Scene.WorldObject[];\n report: Diagnostics.Report;\n};\n\n/** Hard requirement; `violations` names each way the layout breaks it, empty when it holds. */\nexport type Constraint = {\n id: string;\n description: string;\n violations: (layout: Layout) => readonly string[];\n};\n\n/** Soft preference; `measure` is in the term's natural unit and `weight` converts it to cost. */\nexport type CostTerm = {\n id: string;\n description: string;\n weight: number;\n measure: (layout: Layout) => number;\n};\n\nexport type Objective = {\n constraints: readonly Constraint[];\n costs: readonly CostTerm[];\n};\n\nexport type Evaluation = {\n violations: readonly { constraint: string; message: string }[];\n /** Weighted sum of the cost terms. */\n cost: number;\n terms: readonly { id: string; value: number; weighted: number }[];\n};\n\nexport const evaluate = (objective: Objective, layout: Layout): Evaluation => {\n const violations = objective.constraints.flatMap((constraint) =>\n constraint.violations(layout).map((message) => ({ constraint: constraint.id, message })),\n );\n const terms = objective.costs.map((term) => {\n const value = term.measure(layout);\n return { id: term.id, value, weighted: value * term.weight };\n });\n return { violations, cost: terms.reduce((total, term) => total + term.weighted, 0), terms };\n};\n\nexport type Ranked<T> = { candidate: T; evaluation: Evaluation };\n\n/**\n * Picks the best candidate: fewest constraint violations first (so an infeasible set still yields\n * the least-bad layout rather than nothing), then lowest cost. Stable on ties, so the generator's\n * own order breaks them.\n */\nexport const select = <T extends { layout: Layout }>(\n objective: Objective,\n candidates: readonly T[],\n): { chosen: Ranked<T>; ranked: readonly Ranked<T>[] } => {\n invariant(candidates.length > 0, 'select needs at least one candidate');\n const ranked = candidates\n .map((candidate) => ({ candidate, evaluation: evaluate(objective, candidate.layout) }))\n .sort(\n (left, right) =>\n left.evaluation.violations.length - right.evaluation.violations.length ||\n left.evaluation.cost - right.evaluation.cost,\n );\n return { chosen: ranked[0], ranked };\n};\n\n//\n// Built-in constraints and cost terms. Weights are in \"one crossing ≈ three bends\" units; the\n// corpus snapshots are where a weight change shows its consequences.\n//\n\n/** Every `error` diagnostic is a violation: overlaps, routes through nodes, labels that do not fit. */\nexport const noHardDefects: Constraint = {\n id: 'no-hard-defects',\n description: 'No node overlaps, no connector through a node, every label fits its shape.',\n violations: ({ report }) =>\n report.diagnostics.filter(({ severity }) => severity === 'error').map(({ message }) => message),\n};\n\n/** Containers keep at least `gap` between them, so packages read as separate. */\nexport const framesApart = (gap: number = GRID): Constraint => ({\n id: 'frames-apart',\n description: `Frames are at least ${gap} apart.`,\n violations: ({ report }) =>\n report.metrics.containers >= 2 && report.metrics.frameGapMin < gap\n ? [`Frames are ${report.metrics.frameGapMin} apart; at least ${gap} required.`]\n : [],\n});\n\nexport const crossings: CostTerm = {\n id: 'crossings',\n description: 'Connector pairs that cross.',\n weight: 3,\n measure: ({ report }) => report.metrics.crossings,\n};\n\nexport const bends: CostTerm = {\n id: 'bends',\n description: 'Turns taken by connectors.',\n weight: 1,\n measure: ({ report }) => report.metrics.bends,\n};\n\n/**\n * Uneven gutters between frames, in grid units. Weighted so a whole cell of unevenness costs about\n * half a crossing: on the pipeline corpus diagram a weight of 2 made the objective accept three\n * crossings to even out a 7-unit spread, which no reader would.\n */\nexport const unevenFrameGaps: CostTerm = {\n id: 'uneven-frame-gaps',\n description: 'Spread of the gaps between neighbouring frames.',\n weight: 0.5,\n measure: ({ report }) => report.metrics.frameGapSpread / GRID,\n};\n\n/**\n * Total connector length in grid units: a long edge is hard to follow even when it is straight.\n * Weighted so ~100 grid units of extra connector cost one crossing — at 0.1 the objective traded\n * crossings for shorter edges on the compute and edge corpus diagrams.\n */\nexport const connectorLength: CostTerm = {\n id: 'connector-length',\n description: 'Total connector length.',\n weight: 0.03,\n measure: ({ report }) => report.metrics.length / GRID,\n};\n\n/** Bounding perimeter in grid units; a light preference for the tighter of otherwise-equal layouts. */\nexport const compactness: CostTerm = {\n id: 'compactness',\n description: 'Bounding width + height.',\n weight: 0.05,\n measure: ({ report }) => (report.metrics.width + report.metrics.height) / GRID,\n};\n\nexport const DEFAULT: Objective = {\n constraints: [noHardDefects, framesApart()],\n costs: [crossings, bends, connectorLength, unevenFrameGaps, compactness],\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Engine-backed mermaid flowchart dialect. ELK lays out the graph as a compound graph (subgraphs\n// are hierarchical nodes), node origins are quantized to a lattice of the cell size so neighbours\n// align exactly, and connectors take the shared obstacle-avoiding router with straightened ports.\n// Placement and emission are candidate generators — lattice × sibling order × inheritance bus —\n// and the `Objective` picks the layout. Parsing stays in `mermaid.ts`; see `docs/DESIGN.md`.\n//\n\nimport ELK, { type ElkNode } from 'elkjs/lib/elk.bundled.js';\n\nimport { invariant } from '@dxos/invariant';\n\nimport * as Diagnostics from './diagnostics.ts';\nimport * as Layout from './layout.ts';\nimport { type Direction, type MermaidEdge, type MermaidGraph, markers, parse } from './mermaid.ts';\nimport * as Objective from './objective.ts';\nimport { makeAvoidingRouter } from './ortho-router.ts';\nimport type * as Scene from './scene.ts';\nimport { GRID, type Rect, type Router, zRouter } from './uml-grid.ts';\n\nconst MIN_W = GRID * 3;\nconst MAX_W = GRID * 6;\nconst MIN_H = GRID * 2;\nconst PAD_X = GRID;\nconst PAD_Y = GRID / 2;\n/** Frame inset around a subgraph's members; the top also holds the frame label. */\nconst FRAME_PAD = GRID;\nconst FRAME_LABEL_H = GRID;\n/** Clear space between two frames, so packages read as separate even when their nodes are adjacent. */\nconst FRAME_GAP = GRID;\nconst GRID_FINE = GRID / 2;\n\nconst FONT = Layout.FONT_METRICS.m;\nconst LABEL_FONT = Layout.FONT_METRICS.s;\n\nconst ELK_DIRECTION: Record<Direction, string> = { TB: 'DOWN', BT: 'UP', LR: 'RIGHT', RL: 'LEFT' };\n\nconst snapUp = (value: number) => Math.ceil(value / GRID) * GRID;\nconst fineSnap = (value: number) => Math.round(value / GRID_FINE) * GRID_FINE;\n\n/** How ELK orders siblings within a layer. */\nexport type Order = 'model' | 'free';\n\n/**\n * How groups relate: `layered` lays the whole hierarchy out in one flow (groups stack along it);\n * `columns` lays each group out in the flow direction and arranges the groups side by side\n * across it, so cross-package edges run sideways instead of stacking packages.\n */\nexport type Arrangement = 'layered' | 'columns';\n\n/**\n * How a plain reference ranks its ends. Inheritance always ranks the base above, has-many and\n * containment the owner above; a reference has no such convention, so it is a candidate axis:\n * `down` — the referenced sits below, ELK's reading of an arrow; `up` — the referenced sits above,\n * as the abstraction does, so a node many others point at heads its package; `free` — a reference\n * ranks nothing and its ends may share a row. Between packages a reference always orders the packages.\n */\nexport type Layering = 'down' | 'up' | 'free';\n\n/**\n * How packages sit along the flow in `columns`: `none` keeps ELK's placement; `edges` shifts each\n * package by whole rows to where its cross-package edges meet their partners' rows, so those edges\n * run straight instead of jogging between a short package and a tall one.\n */\nexport type Alignment = 'none' | 'edges';\n\nconst LATTICES: readonly number[] = [1.5, 2];\nconst ORDERS: readonly Order[] = ['model', 'free'];\nconst ARRANGEMENTS: readonly Arrangement[] = ['layered', 'columns'];\nconst LAYERINGS: readonly Layering[] = ['down', 'up', 'free'];\nconst ALIGNMENTS: readonly Alignment[] = ['none', 'edges'];\n\n/** The direction perpendicular to the flow, for arranging groups across it. */\nconst ACROSS: Record<Direction, string> = { TB: 'RIGHT', BT: 'RIGHT', LR: 'DOWN', RL: 'DOWN' };\n\nexport type CompileOptions = {\n /** Canvas position of the diagram's top-left, in canvas px. */\n origin?: Scene.Point;\n /** Canvas px per scene unit. */\n scale?: number;\n /**\n * Pitch of the placement lattice as a multiple of the cell size. Node origins snap to lattice\n * points, so nodes that ELK placed roughly in line share an axis exactly and their connectors\n * run straight; the gutter between neighbours is `(lattice − 1) × cell`. A list names the\n * candidates the objective chooses among (default `[1.5, 2]`); a number fixes it.\n */\n lattice?: number | readonly number[];\n /** ELK sibling ordering candidates (default both): declaration order, or free to minimize crossings. */\n order?: readonly Order[];\n /** Group arrangement candidates (default both when the graph has two or more groups). */\n arrangement?: readonly Arrangement[];\n /** How references rank their ends (default all three candidates). */\n layering?: readonly Layering[];\n /** Package alignment candidates along the flow, in `columns` (default both). */\n alignment?: readonly Alignment[];\n /**\n * Inheritance bus candidates (default both): with `true`, subtypes on one row that share a base\n * connect through one horizontal bus and a single triangle-headed trunk instead of parallel arrows.\n */\n bus?: readonly boolean[];\n /** Objective that picks among candidates (default `Objective.DEFAULT`). */\n objective?: Objective.Objective;\n /** Maximum cell width, in scene units (default GRID × 6); longer labels wrap. */\n maxWidth?: number;\n /** Connector router (default: obstacle-avoiding A* with the Z-router as fallback). */\n route?: Router;\n};\n\n/** One generated layout with the objective's verdict on it. */\nexport type Candidate = {\n lattice: number;\n order: Order;\n arrangement: Arrangement;\n layering: Layering;\n alignment: Alignment;\n bus: boolean;\n commands: Scene.Command[];\n layout: Objective.Layout;\n};\n\nexport type Result = {\n commands: Scene.Command[];\n chosen: Objective.Ranked<Candidate>;\n /** Every candidate, best first. */\n ranked: readonly Objective.Ranked<Candidate>[];\n};\n\ntype Cell = { w: number; h: number };\ntype Pitch = { x: number; y: number };\n\n/** One cell size for every node, sized to the longest label wrapped at `maxWidth`. */\nconst measureCell = (graph: MermaidGraph, maxWidth: number): Cell => {\n const longest = Math.max(0, ...graph.nodes.map((node) => node.label.length));\n const w = snapUp(Math.min(maxWidth, Math.max(MIN_W, longest * FONT.charW + PAD_X * 2)));\n const perLine = Math.max(1, Math.floor((w - PAD_X) / FONT.charW));\n const lines = Math.max(1, ...graph.nodes.map((node) => Math.ceil(node.label.length / perLine)));\n const h = snapUp(Math.max(MIN_H, (lines - 1) * FONT.lineH + FONT.lineH / 1.35 + PAD_Y * 2));\n return { w, h };\n};\n\n/**\n * Lattice pitch for a cell. With groups, the gutter between lattice rows must also hold two frame\n * borders, a label band, and clear space between the frames, or adjacent frames touch or overlap\n * after quantization — so that clearance is a floor on the pitch.\n */\nconst pitchFor = (graph: MermaidGraph, cell: Cell, lattice: number): Pitch => {\n const framed = graph.groups.some((group) => group.children.length > 0);\n return {\n x: snapUp(Math.max(cell.w * lattice, framed ? cell.w + FRAME_PAD * 2 + FRAME_GAP : 0)),\n y: snapUp(Math.max(cell.h * lattice, framed ? cell.h + FRAME_PAD * 2 + FRAME_LABEL_H + FRAME_GAP : 0)),\n };\n};\n\ntype Placement = {\n nodes: Map<string, Rect>;\n frames: Map<string, Rect>;\n};\n\n/**\n * Quantize ELK's positions to the lattice. Each node takes the nearest lattice point; when two\n * nodes claim the same point, the later one slides along the cross axis to the nearest free slot,\n * so quantization can never stack nodes.\n */\nconst quantize = (positions: Map<string, Scene.Point>, pitch: Pitch, horizontal: boolean): Map<string, Scene.Point> => {\n const taken = new Set<string>();\n const result = new Map<string, Scene.Point>();\n // Place in reading order so a slide pushes the later node, not an earlier one.\n const ordered = [...positions.entries()].sort(([, a], [, b]) =>\n horizontal ? a.x - b.x || a.y - b.y : a.y - b.y || a.x - b.x,\n );\n for (const [id, point] of ordered) {\n const col = Math.round(point.x / pitch.x);\n const row = Math.round(point.y / pitch.y);\n for (let step = 0; ; step++) {\n // Alternate sides so the node stays as close as possible to where ELK wanted it.\n const offset = step === 0 ? 0 : (step % 2 ? 1 : -1) * Math.ceil(step / 2);\n const cell = horizontal ? { col, row: row + offset } : { col: col + offset, row };\n const key = `${cell.col}:${cell.row}`;\n if (!taken.has(key)) {\n taken.add(key);\n result.set(id, { x: cell.col * pitch.x, y: cell.row * pitch.y });\n break;\n }\n }\n }\n return result;\n};\n\n/**\n * Close surplus gutters between groups along the cross axis. ELK spaces compound nodes by their\n * own padded extents, so after quantization two groups can sit a whole lattice pitch further apart\n * than the frame clearance needs while another pair sits at the minimum — the uneven gaps a reader\n * notices first. Groups are walked in cross-axis order and each, with everything beyond it, is\n * pulled back by whole pitches while its gap to the previous group stays above the clearance, so\n * every node remains on the lattice and cross-group connectors stay straight.\n */\nconst compactGroups = (\n graph: MermaidGraph,\n positions: Map<string, Scene.Point>,\n cell: Cell,\n pitch: Pitch,\n horizontal: boolean,\n): Map<string, Scene.Point> => {\n const axis = horizontal ? 'y' : 'x';\n const step = horizontal ? pitch.y : pitch.x;\n const size = horizontal ? cell.h : cell.w;\n const groups = graph.groups\n .filter((group) => group.children.some((id) => positions.has(id)))\n .map((group) => {\n const coords = group.children.flatMap((id) => (positions.has(id) ? [positions.get(id)![axis]] : []));\n return { ids: group.children, start: Math.min(...coords), end: Math.max(...coords) };\n })\n .sort((left, right) => left.start - right.start);\n\n const result = new Map(positions);\n for (let index = 1; index < groups.length; index++) {\n const previous = groups[index - 1];\n const current = groups[index];\n // Gap between the two frames: last member's far edge plus pad, to first member's near edge less pad.\n const gap = current.start - FRAME_PAD - (previous.end + size + FRAME_PAD);\n let surplus = Math.floor((gap - FRAME_GAP) / step) * step;\n if (surplus <= 0) {\n continue;\n }\n // Everything at or beyond this group's start shifts together, so relative order is preserved —\n // but only onto free lattice points: an ungrouped node moving with the block must not land on\n // a node that stays put.\n const moving = [...result].filter(([, point]) => point[axis] >= current.start);\n const staying = new Set(\n [...result].filter(([, point]) => point[axis] < current.start).map(([, point]) => `${point.x}:${point.y}`),\n );\n const collides = (shift: number) =>\n moving.some(([, point]) =>\n staying.has(`${axis === 'x' ? point.x - shift : point.x}:${axis === 'y' ? point.y - shift : point.y}`),\n );\n while (surplus > 0 && collides(surplus)) {\n surplus -= step;\n }\n if (surplus <= 0) {\n continue;\n }\n for (const [id, point] of moving) {\n result.set(id, { ...point, [axis]: point[axis] - surplus });\n }\n for (const later of groups.slice(index)) {\n later.start -= surplus;\n later.end -= surplus;\n }\n }\n return result;\n};\n\ntype ElkEdge = { id: string; sources: string[]; targets: string[] };\n\n/**\n * Edges for ELK's layering. Inheritance points at the abstraction, which ranks ABOVE its\n * subtypes — so those edges are reversed, as `relationRanks` does for class diagrams; has-many\n * and containment already flow owner-above-owned. In `columns`, the root lays out groups without\n * seeing inside them (`SEPARATE_CHILDREN`), so every edge is lifted to its endpoints' root-level\n * representatives — the group, or the node itself when ungrouped — and the groups fall into\n * dependency order; edges within one group stay where they are for that group's own layout.\n * A reference between packages always orders the packages; within one it ranks per `layering`.\n */\nconst layeringEdges = (graph: MermaidGraph, arrangement: Arrangement, layering: Layering): ElkEdge[] => {\n const groupOf = new Map(graph.groups.flatMap((group) => group.children.map((id) => [id, group.id] as const)));\n const betweenGroups = (edge: MermaidEdge) =>\n groupOf.has(edge.from) && groupOf.has(edge.to) && groupOf.get(edge.from) !== groupOf.get(edge.to);\n const oriented = graph.edges.flatMap((edge) => {\n if (edge.kind === 'inheritance') {\n return [{ from: edge.to, to: edge.from }];\n }\n if (edge.kind !== 'reference' || layering === 'down' || betweenGroups(edge)) {\n return [{ from: edge.from, to: edge.to }];\n }\n return layering === 'up' ? [{ from: edge.to, to: edge.from }] : [];\n });\n if (arrangement === 'layered') {\n return oriented.map((edge, index) => ({ id: `edge-${index}`, sources: [edge.from], targets: [edge.to] }));\n }\n const edges: ElkEdge[] = [];\n const seen = new Set<string>();\n oriented.forEach((edge, index) => {\n const from = groupOf.get(edge.from);\n const to = groupOf.get(edge.to);\n if (from !== undefined && from === to) {\n edges.push({ id: `edge-${index}`, sources: [edge.from], targets: [edge.to] });\n return;\n }\n const lifted = { from: from ?? edge.from, to: to ?? edge.to };\n const key = `${lifted.from}->${lifted.to}`;\n if (lifted.from !== lifted.to && !seen.has(key)) {\n seen.add(key);\n edges.push({ id: `group-edge-${index}`, sources: [lifted.from], targets: [lifted.to] });\n }\n });\n return edges;\n};\n\n/**\n * ELK compound layout. Groups become hierarchical nodes whose children ELK lays out inside\n * them; positions come back parent-relative and are flattened here. Node origins are then\n * quantized to the lattice and frames recomputed from their quantized members, so quantization\n * can never break containment.\n */\nconst place = async (\n graph: MermaidGraph,\n cell: Cell,\n pitch: Pitch,\n order: Order,\n arrangement: Arrangement,\n layering: Layering,\n): Promise<Map<string, Scene.Point>> => {\n const horizontal = graph.direction === 'LR' || graph.direction === 'RL';\n const grouped = new Set(graph.groups.flatMap((group) => group.children));\n const leaf = (id: string): ElkNode => ({ id, width: cell.w, height: cell.h });\n // Spacing is per compound node, not inherited: left unset, ELK packs a group's members at its\n // 20px default — inside the router's clearance — and every route through that group is fenced.\n // Matching the lattice gutters keeps ELK's output close to lattice points before quantization.\n const spacing = {\n 'elk.layered.spacing.nodeNodeBetweenLayers': String(horizontal ? pitch.x - cell.w : pitch.y - cell.h),\n 'elk.spacing.nodeNode': String(horizontal ? pitch.y - cell.h : pitch.x - cell.w),\n };\n const flow = {\n 'elk.algorithm': 'layered',\n 'elk.direction': ELK_DIRECTION[graph.direction],\n 'elk.layered.nodePlacement.strategy': 'BRANDES_KOEPF',\n 'elk.layered.considerModelOrder.strategy': order === 'model' ? 'PREFER_NODES' : 'NONE',\n };\n const children: ElkNode[] = [\n ...graph.nodes.filter((node) => !grouped.has(node.id)).map((node) => leaf(node.id)),\n ...graph.groups\n .filter((group) => group.children.length > 0)\n .map((group) => ({\n id: group.id,\n layoutOptions: {\n ...spacing,\n // Columns: each group is its own flow; the root only arranges the groups.\n ...(arrangement === 'columns' ? flow : {}),\n 'elk.padding': `[top=${FRAME_PAD + FRAME_LABEL_H},left=${FRAME_PAD},bottom=${FRAME_PAD},right=${FRAME_PAD}]`,\n },\n children: group.children.map(leaf),\n })),\n ];\n\n const elk = new ELK();\n const result = await elk.layout({\n id: 'root',\n layoutOptions:\n arrangement === 'columns'\n ? {\n // Groups side by side across the flow, each laid out internally first.\n ...flow,\n 'elk.direction': ACROSS[graph.direction],\n 'elk.hierarchyHandling': 'SEPARATE_CHILDREN',\n ...spacing,\n }\n : {\n ...flow,\n // Lay out the whole hierarchy in one pass so edges crossing group borders still order layers.\n 'elk.hierarchyHandling': 'INCLUDE_CHILDREN',\n ...spacing,\n },\n children,\n edges: layeringEdges(graph, arrangement, layering),\n });\n\n const raw = new Map<string, Scene.Point>();\n const visit = (node: ElkNode, offset: Scene.Point) => {\n for (const child of node.children ?? []) {\n const x = offset.x + (child.x ?? 0);\n const y = offset.y + (child.y ?? 0);\n if (child.children?.length) {\n visit(child, { x, y });\n } else {\n raw.set(child.id, { x, y });\n }\n }\n };\n visit(result, { x: 0, y: 0 });\n\n return compactGroups(graph, quantize(raw, pitch, horizontal), cell, pitch, horizontal);\n};\n\n/**\n * Align each package to its cross-package edges: among the whole-row shifts that put one of its\n * members on the row of that member's partner, take the one leaving its edges the least total row\n * offset (nearest to no shift on a tie), onto free lattice points only. Two sweeps, since a partner\n * may itself move in the first.\n */\nconst alignGroups = (\n graph: MermaidGraph,\n positions: Map<string, Scene.Point>,\n direction: Direction,\n alignment: Alignment,\n): Map<string, Scene.Point> => {\n if (alignment === 'none') {\n return positions;\n }\n const axis = direction === 'LR' || direction === 'RL' ? 'x' : 'y';\n const groupOf = new Map(graph.groups.flatMap((group) => group.children.map((id) => [id, group.id] as const)));\n const result = new Map(positions);\n for (let sweep = 0; sweep < 2; sweep++) {\n for (const group of graph.groups) {\n const members = new Set(group.children.filter((id) => result.has(id)));\n // Each cross-package edge, as the member's coordinate and the partner's along the flow.\n const pairs = graph.edges.flatMap((edge) => {\n const [member, partner] = members.has(edge.from) ? [edge.from, edge.to] : [edge.to, edge.from];\n const here = result.get(member);\n const there = result.get(partner);\n return members.has(member) && !members.has(partner) && groupOf.has(partner) && here && there\n ? [{ here: here[axis], there: there[axis] }]\n : [];\n });\n if (pairs.length === 0) {\n continue;\n }\n const offset = (shift: number) => pairs.reduce((sum, pair) => sum + Math.abs(pair.here + shift - pair.there), 0);\n const shifts = [...new Set([0, ...pairs.map((pair) => pair.there - pair.here)])].sort(\n (left, right) => offset(left) - offset(right) || Math.abs(left) - Math.abs(right),\n );\n const others = new Set(\n [...result].filter(([id]) => !members.has(id)).map(([, point]) => `${point.x}:${point.y}`),\n );\n const shift = shifts.find(\n (candidate) =>\n ![...members].some((id) => {\n const point = result.get(id);\n return (\n point &&\n others.has(\n `${axis === 'x' ? point.x + candidate : point.x}:${axis === 'y' ? point.y + candidate : point.y}`,\n )\n );\n }),\n );\n if (!shift) {\n continue;\n }\n for (const id of members) {\n const point = result.get(id);\n if (point) {\n result.set(id, { ...point, [axis]: point[axis] + shift });\n }\n }\n }\n }\n return result;\n};\n\n/** Node rects at the origin plus the frame around each group's members. */\nconst frame = (graph: MermaidGraph, positions: Map<string, Scene.Point>, cell: Cell): Placement => {\n const minX = Math.min(0, ...[...positions.values()].map((point) => point.x));\n const minY = Math.min(0, ...[...positions.values()].map((point) => point.y));\n const nodes = new Map<string, Rect>(\n [...positions].map(([id, point]) => [id, { x: point.x - minX, y: point.y - minY, w: cell.w, h: cell.h }]),\n );\n\n const frames = new Map<string, Rect>();\n for (const group of graph.groups) {\n const members = group.children.flatMap((id) => nodes.get(id) ?? []);\n if (members.length === 0) {\n continue;\n }\n const x = Math.min(...members.map((rect) => rect.x)) - FRAME_PAD;\n const y = Math.min(...members.map((rect) => rect.y)) - FRAME_PAD - FRAME_LABEL_H;\n const right = Math.max(...members.map((rect) => rect.x + rect.w)) + FRAME_PAD;\n const bottom = Math.max(...members.map((rect) => rect.y + rect.h)) + FRAME_PAD;\n frames.set(group.id, { x, y, w: right - x, h: bottom - y });\n }\n\n return { nodes, frames };\n};\n\ntype Ports = { start?: number; end?: number };\n\n/**\n * Straightened ports: when an edge's nodes overlap on the cross axis, both terminals take one\n * shared coordinate inside the overlap, so the connector is a single straight run instead of a\n * jog between nearly aligned nodes. Distinct edges leaving the same node side take distinct\n * coordinates. Mirrors the straightening pass in the UML emitter.\n */\nconst straighten = (\n edges: readonly MermaidEdge[],\n nodes: Map<string, Rect>,\n isHorizontal: (edge: MermaidEdge) => boolean,\n): Map<MermaidEdge, Ports> => {\n const ports = new Map<MermaidEdge, Ports>();\n const taken = new Map<string, number[]>();\n for (const edge of edges) {\n const from = nodes.get(edge.from);\n const to = nodes.get(edge.to);\n if (!from || !to) {\n continue;\n }\n const horizontal = isHorizontal(edge);\n const sameLane = horizontal ? from.x === to.x : from.y === to.y;\n const alongY = horizontal ? sameLane : !sameLane;\n const lo = (alongY ? Math.max(from.x, to.x) : Math.max(from.y, to.y)) + GRID_FINE;\n const hi = (alongY ? Math.min(from.x + from.w, to.x + to.w) : Math.min(from.y + from.h, to.y + to.h)) - GRID_FINE;\n if (lo > hi) {\n continue;\n }\n const sides = alongY\n ? [`${edge.from}:${to.y >= from.y ? 'bottom' : 'top'}`, `${edge.to}:${to.y >= from.y ? 'top' : 'bottom'}`]\n : [`${edge.from}:${to.x >= from.x ? 'right' : 'left'}`, `${edge.to}:${to.x >= from.x ? 'left' : 'right'}`];\n const center = alongY ? (from.x + from.w / 2 + to.x + to.w / 2) / 2 : (from.y + from.h / 2 + to.y + to.h / 2) / 2;\n const base = Math.min(hi, Math.max(lo, fineSnap(center)));\n const isFree = (coord: number) =>\n sides.every((side) => (taken.get(side) ?? []).every((used) => Math.abs(used - coord) >= GRID_FINE));\n let chosen: number | undefined;\n for (let step = 0; step <= Math.ceil((hi - lo) / GRID_FINE) && chosen === undefined; step++) {\n for (const candidate of step === 0 ? [base] : [base - step * GRID_FINE, base + step * GRID_FINE]) {\n if (candidate >= lo && candidate <= hi && isFree(candidate)) {\n chosen = candidate;\n break;\n }\n }\n }\n if (chosen === undefined) {\n continue;\n }\n ports.set(edge, { start: chosen, end: chosen });\n for (const side of sides) {\n taken.set(side, [...(taken.get(side) ?? []), chosen]);\n }\n }\n return ports;\n};\n\n/**\n * Inheritance bus (TB only): subtypes of one base that sit on one row above which the base sits\n * connect through a shared horizontal bus and a single triangle-headed trunk, the UML tree\n * connector. Returns the elements and the edges it consumed; edges that do not qualify are left\n * to the per-edge router.\n */\nconst inheritanceBuses = (\n edges: readonly MermaidEdge[],\n nodes: Map<string, Rect>,\n): { elements: Scene.Element[]; consumed: Set<MermaidEdge> } => {\n const elements: Scene.Element[] = [];\n const consumed = new Set<MermaidEdge>();\n const byBase = new Map<string, MermaidEdge[]>();\n for (const edge of edges) {\n // A labelled edge keeps its own connector: the bus has no place to put its text.\n if (edge.kind === 'inheritance' && !edge.label) {\n byBase.set(edge.to, [...(byBase.get(edge.to) ?? []), edge]);\n }\n }\n for (const [baseId, group] of byBase) {\n const base = nodes.get(baseId);\n const subs = group.map((edge) => nodes.get(edge.from));\n if (!base || group.length < 2 || subs.some((sub) => !sub)) {\n continue;\n }\n const rects = subs as Rect[];\n const row = rects[0].y;\n if (rects.some((sub) => sub.y !== row) || base.y + base.h >= row) {\n continue;\n }\n const busY = fineSnap((base.y + base.h + row) / 2);\n const trunkX = fineSnap(base.x + base.w / 2);\n const centers = rects.map((sub) => fineSnap(sub.x + sub.w / 2));\n const span = [Math.min(trunkX, ...centers), Math.max(trunkX, ...centers)];\n elements.push({\n kind: 'line',\n id: `${baseId}-bus`,\n points: [\n { x: span[0], y: busY },\n { x: span[1], y: busY },\n ],\n });\n group.forEach((edge, index) => {\n elements.push({\n kind: 'line',\n id: `${edge.from}-${baseId}-stub-${index}`,\n points: [\n { x: centers[index], y: row },\n { x: centers[index], y: busY },\n ],\n });\n consumed.add(edge);\n });\n elements.push({\n kind: 'arrow',\n id: `${baseId}-inherit`,\n start: { x: trunkX, y: busY },\n end: { x: trunkX, y: base.y + base.h },\n head: 'triangle',\n });\n }\n return { elements, consumed };\n};\n\ntype EmitOptions = {\n origin: Scene.Point;\n scale: number;\n bus: boolean;\n arrangement: Arrangement;\n route?: Router;\n};\n\n/**\n * Scene commands for a placement: one world object per subgraph frame (painted first) and per\n * node, plus an `edges` object of connectors.\n */\nconst emit = (\n graph: MermaidGraph,\n cell: Cell,\n { nodes, frames }: Placement,\n { origin, scale, bus, arrangement, route }: EmitOptions,\n): Scene.Command[] => {\n const horizontal = graph.direction === 'LR' || graph.direction === 'RL';\n const at = (rect: Rect): Scene.Point => ({ x: origin.x + rect.x * scale, y: origin.y + rect.y * scale });\n const commands: Scene.Command[] = [];\n\n for (const group of graph.groups) {\n const frame = frames.get(group.id);\n if (!frame) {\n continue;\n }\n commands.push({\n op: 'upsert-object',\n object: {\n id: group.id,\n origin: at(frame),\n scale,\n elements: [\n { kind: 'rect', id: 'frame', x: 0, y: 0, w: frame.w, h: frame.h, stroke: 'dashed', color: 'grey' },\n // The label sits in the frame's top band rather than centered, where members would cover it.\n ...(group.label.trim()\n ? [\n {\n kind: 'text',\n id: 'label',\n x: FRAME_PAD / 2,\n y: (FRAME_LABEL_H - LABEL_FONT.lineH) / 2,\n text: group.label,\n weight: 's',\n color: 'grey',\n } satisfies Scene.Text,\n ]\n : []),\n ],\n },\n });\n }\n\n for (const node of graph.nodes) {\n const rect = nodes.get(node.id);\n if (!rect) {\n continue;\n }\n commands.push({\n op: 'upsert-object',\n object: {\n id: node.id,\n origin: at(rect),\n scale,\n ...(node.ref ? { ref: node.ref } : {}),\n elements: [{ kind: 'rect', id: 'box', x: 0, y: 0, w: cell.w, h: cell.h, text: node.label }],\n },\n });\n }\n\n if (graph.edges.length > 0) {\n // Frames are containers, not obstacles: only node rects block routes.\n const router = route ?? makeAvoidingRouter([...nodes.values()], zRouter, { step: GRID / 4 });\n const buses = bus && !horizontal ? inheritanceBuses(graph.edges, nodes) : { elements: [], consumed: new Set() };\n const routed = graph.edges.filter((edge) => !buses.consumed.has(edge));\n // In columns the root level runs across the flow, so an edge between two of its members — groups\n // or ungrouped nodes — runs across it too.\n const groupOf = new Map(graph.groups.flatMap((group) => group.children.map((id) => [id, group.id] as const)));\n const rootOf = (id: string) => groupOf.get(id) ?? id;\n const isHorizontal = (edge: MermaidEdge) =>\n arrangement === 'columns' && rootOf(edge.from) !== rootOf(edge.to) ? !horizontal : horizontal;\n const ports = straighten(routed, nodes, isHorizontal);\n const elements: Scene.Element[] = [...buses.elements];\n // Terminals already placed, per node, with their role. Edges are routed independently (and an\n // internal edge and a cross-group edge may even route in different modes), so a later edge can\n // land its terminal on an earlier one. Only an exit on an entry is a defect — it reads as a\n // crossing — so a slot is taken by the opposite role alone: two exits (a fork) or two entries (a\n // merge) share a trunk, as a bus does. Such an edge is re-routed with the port nudged to a free\n // slot on that side, preferring the nudge that keeps the route straightest.\n type Role = 'exit' | 'entry';\n const terminals = new Map<string, { point: Scene.Point; role: Role }[]>();\n const taken = (nodeId: string, point: Scene.Point, role: Role) =>\n (terminals.get(nodeId) ?? []).some(\n (other) =>\n other.role !== role &&\n Math.abs(other.point.x - point.x) < GRID_FINE &&\n Math.abs(other.point.y - point.y) < GRID_FINE,\n );\n // Paired nudges first: both ends move together, so a straight edge stays straight; single-ended\n // ones for when only one end is crowded.\n const NUDGES: [number, number][] = [\n [0, 0],\n [1, 1],\n [-1, -1],\n [2, 2],\n [-2, -2],\n [1, 0],\n [-1, 0],\n [0, 1],\n [0, -1],\n ];\n const routeEdge = (edge: MermaidEdge, from: Rect, to: Rect): Scene.Point[] => {\n const horizontal = isHorizontal(edge);\n const sameLane = horizontal ? from.x === to.x : from.y === to.y;\n const alongY = horizontal ? sameLane : !sameLane;\n const base = ports.get(edge) ?? {};\n const center = (rect: Rect) => (alongY ? rect.x + rect.w / 2 : rect.y + rect.h / 2);\n const within = (rect: Rect, value: number) =>\n alongY\n ? Math.min(rect.x + rect.w - GRID_FINE, Math.max(rect.x + GRID_FINE, value))\n : Math.min(rect.y + rect.h - GRID_FINE, Math.max(rect.y + GRID_FINE, value));\n const route = ([startNudge, endNudge]: [number, number]) =>\n router({\n relation: edge,\n from,\n to,\n horizontal,\n offset: 0,\n ports: {\n start: within(from, (base.start ?? center(from)) + startNudge * GRID_FINE),\n end: within(to, (base.end ?? center(to)) + endNudge * GRID_FINE),\n },\n });\n const free = (points: Scene.Point[]) =>\n !taken(edge.from, points[0], 'exit') && !taken(edge.to, points[points.length - 1], 'entry');\n const direct = route(NUDGES[0]);\n if (free(direct)) {\n return direct;\n }\n let best: Scene.Point[] | undefined;\n for (const nudge of NUDGES.slice(1)) {\n const attempt = route(nudge);\n if (free(attempt) && (!best || attempt.length < best.length)) {\n best = attempt;\n }\n }\n return best ?? direct;\n };\n routed.forEach((edge, index) => {\n const from = nodes.get(edge.from);\n const to = nodes.get(edge.to);\n if (!from || !to) {\n return;\n }\n const points = routeEdge(edge, from, to);\n terminals.set(edge.from, [...(terminals.get(edge.from) ?? []), { point: points[0], role: 'exit' }]);\n terminals.set(edge.to, [...(terminals.get(edge.to) ?? []), { point: points[points.length - 1], role: 'entry' }]);\n const id = `${edge.from}-${edge.to}-${index}`;\n if (points.length > 2) {\n elements.push({ kind: 'line', id: `${id}-path`, points: points.slice(0, -1) });\n }\n elements.push({\n kind: 'arrow',\n id,\n start: points[points.length - 2],\n end: points[points.length - 1],\n ...markers(edge.kind),\n });\n if (edge.label) {\n const head = points[Math.floor(points.length / 2) - 1];\n const tail = points[Math.floor(points.length / 2)];\n elements.push({\n kind: 'text',\n id: `${id}-label`,\n x: (head.x + tail.x) / 2 + GRID / 4,\n y: (head.y + tail.y) / 2 - LABEL_FONT.lineH,\n text: edge.label,\n weight: 's',\n });\n }\n });\n commands.push({ op: 'upsert-object', object: { id: 'edges', origin, scale, elements } });\n }\n\n return commands;\n};\n\nconst objectsOf = (commands: readonly Scene.Command[]): Scene.WorldObject[] =>\n commands.flatMap((command) => (command.op === 'upsert-object' ? [command.object] : []));\n\n/**\n * Lay out a mermaid flowchart: place once per lattice × ordering, emit with and without the\n * inheritance bus, analyze every candidate, and let the objective choose. All candidates come back\n * ranked so a bench can show what lost and why. Async because ELK is.\n */\nexport const layout = async (source: string, options: CompileOptions = {}): Promise<Result> => {\n const graph = parse(source);\n const { origin = { x: 0, y: 0 }, scale = 1, maxWidth = MAX_W, objective = Objective.DEFAULT, route } = options;\n const cell = measureCell(graph, maxWidth);\n const lattices = typeof options.lattice === 'number' ? [options.lattice] : (options.lattice ?? LATTICES);\n const orders = options.order ?? ORDERS;\n const buses = options.bus ?? [true, false];\n // Columns only mean something with two or more groups to arrange.\n const grouped = graph.groups.filter((group) => group.children.length > 0).length;\n const arrangements = options.arrangement ?? (grouped >= 2 ? ARRANGEMENTS : ['layered']);\n const layerings = options.layering ?? LAYERINGS;\n const alignments = options.alignment ?? ALIGNMENTS;\n invariant(\n lattices.length > 0 &&\n orders.length > 0 &&\n buses.length > 0 &&\n arrangements.length > 0 &&\n layerings.length > 0 &&\n alignments.length > 0,\n 'every candidate axis needs a value',\n );\n\n const candidates: Candidate[] = [];\n // Knobs often reach the same placement (a graph with no in-package references layers the same\n // either way; equal-height packages align the same every way); each is routed and graded once.\n const seen = new Set<string>();\n for (const lattice of lattices) {\n for (const order of orders) {\n for (const arrangement of arrangements) {\n for (const layering of layerings) {\n const pitch = pitchFor(graph, cell, lattice);\n const positions = await place(graph, cell, pitch, order, arrangement, layering);\n // Alignment moves packages relative to each other, which only columns set side by side.\n for (const alignment of arrangement === 'columns' ? alignments : (['none'] as const)) {\n const placement = frame(graph, alignGroups(graph, positions, graph.direction, alignment), cell);\n const key = [...placement.nodes]\n .map(([id, rect]) => `${id}:${rect.x}:${rect.y}`)\n .sort()\n .join(' ');\n for (const bus of buses) {\n if (seen.has(`${arrangement}|${bus}|${key}`)) {\n continue;\n }\n seen.add(`${arrangement}|${bus}|${key}`);\n const commands = emit(graph, cell, placement, { origin, scale, bus, arrangement, route });\n const objects = objectsOf(commands);\n candidates.push({\n lattice,\n order,\n arrangement,\n layering,\n alignment,\n bus,\n commands,\n layout: { objects, report: Diagnostics.analyze(objects) },\n });\n }\n }\n }\n }\n }\n }\n\n const { chosen, ranked } = Objective.select(objective, candidates);\n return { commands: chosen.candidate.commands, chosen, ranked };\n};\n\n/** The chosen layout's scene commands; see {@link layout} for the candidates and verdicts. */\nexport const compile = async (source: string, options: CompileOptions = {}): Promise<Scene.Command[]> =>\n (await layout(source, options)).commands;\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// SVG variant content handler: the scene DSL is the persistence format. Each element is stored\n// verbatim as one record carrying its DSL identity and its object's placement, so\n// `applyCommands` provides upsert/remove/move and `read` reconstructs the scene losslessly —\n// there is no renderer-native encoding to compile to. The plugin binds it to ECHO as `SvgBuilder`.\n//\n\nimport { type ContentHandler, type ContentMap, type ReadWorldObject } from './content.ts';\nimport type * as Scene from './scene.ts';\n\n/** Discriminates the base `Drawing.Canvas` as SVG-rendered scene content. */\nexport const SVG_SCHEMA = 'dxos.org/svg/1';\n\ntype SvgRecord = {\n object: string;\n element: string;\n /** Insertion order, so `read` reproduces element paint order. */\n order: number;\n placement: { origin: Scene.Point; scale: number };\n /** The object's `ref`, repeated on each of its records so `read` restores it. */\n ref?: string;\n /** The object's fractional z-order `index`, repeated like `ref`. */\n index?: string;\n data: Scene.Element;\n};\n\nconst isSvgRecord = (record: any): record is SvgRecord =>\n typeof record?.object === 'string' && typeof record?.element === 'string' && record?.data !== undefined;\n\n/** Objects without an index paint first, in insertion order; indexed objects follow in index order. */\nconst byIndex = (left: ReadWorldObject, right: ReadWorldObject): number =>\n left.index === undefined\n ? right.index === undefined\n ? 0\n : -1\n : right.index === undefined\n ? 1\n : left.index < right.index\n ? -1\n : left.index > right.index\n ? 1\n : 0;\n\nexport const SvgHandler: ContentHandler = {\n identify: (record) => (isSvgRecord(record) ? { object: record.object, element: record.element } : undefined),\n\n render: (object, placement, content) => {\n // Past the max, not the count: deletions leave gaps, and a reused order makes paint order\n // ambiguous on read.\n let order =\n Math.max(\n -1,\n ...Object.values(content)\n .filter(isSvgRecord)\n .map((record) => record.order),\n ) + 1;\n // `upsert-elements` supplies only elements; the object's ref and index then come from its\n // existing records.\n const existing = Object.values(content).find((record) => isSvgRecord(record) && record.object === object.id);\n const ref = ('ref' in object && object.ref) || existing?.ref;\n const index = ('index' in object && object.index) || existing?.index;\n const records: ContentMap = {};\n for (const element of object.elements) {\n records[`${object.id}/${element.id}`] = {\n object: object.id,\n element: element.id,\n order: order++,\n placement: { origin: { ...placement.origin }, scale: placement.scale },\n ...(ref ? { ref } : {}),\n ...(index ? { index } : {}),\n // Structured clone: scene elements are plain data, and the record must not alias the input.\n data: JSON.parse(JSON.stringify(element)),\n } satisfies SvgRecord;\n }\n return records;\n },\n\n read: (content) => {\n const records = Object.values(content)\n .filter(isSvgRecord)\n .sort((left, right) => left.order - right.order);\n const objects = new Map<string, ReadWorldObject>();\n let unmanaged = 0;\n for (const record of Object.values(content)) {\n if (!isSvgRecord(record)) {\n unmanaged++;\n }\n }\n for (const record of records) {\n let object = objects.get(record.object);\n if (!object) {\n object = {\n id: record.object,\n origin: { ...record.placement.origin },\n scale: record.placement.scale,\n ...(record.ref ? { ref: record.ref } : {}),\n ...(record.index ? { index: record.index } : {}),\n elements: [],\n };\n objects.set(record.object, object);\n }\n (object.elements as Scene.Element[]).push(record.data);\n }\n return { scene: { objects: [...objects.values()].sort(byIndex) }, unmanaged };\n },\n\n translate: (record, delta) => {\n if (isSvgRecord(record)) {\n record.placement.origin = {\n x: record.placement.origin.x + delta.x,\n y: record.placement.origin.y + delta.y,\n };\n }\n },\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// MOSAIC (Model-Oriented System for Adaptive Interface Composition) UI-schematic dialect:\n// renders low-fidelity UI wireframes from the declarative app model. Phase 1 scope: a single\n// schema compiles to a form drawing — the recursive structure (nested objects, arrays) with each\n// control (input, switch, checkbox, select) as a rectangle and its label as text above — wrapped\n// in the app-ontology containers (deck > plank > panel > form). Two renderers share the model:\n// ASCII (tests, chat) and scene commands (tldraw, via the standard dialect contract). Unrelated\n// to `react-ui-mosaic`. See `dialect.ts` for the extension mechanism this follows (mermaid is\n// the sibling precedent).\n//\n\nimport type * as Schema from 'effect/Schema';\nimport * as SchemaAST from 'effect/SchemaAST';\n\nimport type * as Scene from './scene.ts';\n\n//\n// Drawing model. Plain data (one discriminated tree) — the intermediate model between the app\n// model (schema today; app-graph later) and the renderers.\n//\n\nexport type ControlKind = 'input' | 'switch' | 'checkbox' | 'select';\n\nexport type Control = {\n kind: 'control';\n control: ControlKind;\n label: string;\n /** Dotted schema path; doubles as the element id so drawn controls stay addressable. */\n path: string;\n};\n\n/** Nested object: a labeled group of fields. */\nexport type Group = {\n kind: 'group';\n label: string;\n path: string;\n children: FormChild[];\n};\n\n/** Array: a labeled repetition of one item template. */\nexport type ArrayGroup = {\n kind: 'array';\n label: string;\n path: string;\n /** The element template, rendered once with a trailing \"+\" affordance. */\n item: FormChild;\n};\n\nexport type FormChild = Control | Group | ArrayGroup;\n\n/** A form has no title of its own — the schema title belongs to the enclosing container. */\nexport type Form = { kind: 'form'; children: FormChild[] };\nexport type Panel = { kind: 'panel'; label?: string; child: Form };\nexport type Plank = { kind: 'plank'; label?: string; child: Panel };\nexport type Deck = { kind: 'deck'; planks: Plank[] };\n\nexport type UiNode = Deck | Plank | Panel | Form | FormChild;\n\n//\n// Schema → drawing. Minimal v4 AST walking, self-contained (see @dxos/effect SchemaEx for the\n// full-featured helpers): properties live on `Objects` nodes, `Schema.optional` is a\n// `T | undefined` union, arrays are `Arrays` with a single rest element.\n//\n\nexport type FromSchemaOptions = {\n /** Recursion guard for self-referential schemas. */\n maxDepth?: number;\n};\n\nconst unwrapSuspend = (ast: SchemaAST.AST): SchemaAST.AST =>\n SchemaAST.isSuspend(ast) ? unwrapSuspend(ast.thunk()) : ast;\n\nconst unwrapOptional = (ast: SchemaAST.AST): SchemaAST.AST => {\n let node = ast;\n while (SchemaAST.isUnion(node) && node.types.length === 2 && SchemaAST.isUndefined(node.types[1])) {\n node = node.types[0];\n }\n return node;\n};\n\nconst propertiesOf = (ast: SchemaAST.AST): ReadonlyArray<SchemaAST.PropertySignature> => {\n const node = unwrapSuspend(ast);\n return node._tag === 'Objects' ? node.propertySignatures : [];\n};\n\nconst isLiteralUnion = (node: SchemaAST.AST): boolean =>\n SchemaAST.isUnion(node) && node.types.length > 0 && node.types.every(SchemaAST.isLiteral);\n\nconst arrayElementOf = (node: SchemaAST.AST): SchemaAST.AST | undefined =>\n SchemaAST.isArrays(node) && node.elements.length === 0 && node.rest.length === 1 ? node.rest[0] : undefined;\n\nconst titleOf = (ast: SchemaAST.AST): string | undefined => {\n const title = (ast.annotations?.title ?? SchemaAST.resolve(ast)?.title) as string | undefined;\n return typeof title === 'string' ? title : undefined;\n};\n\nconst label = (name: PropertyKey, type: SchemaAST.AST): string => titleOf(type) ?? String(name);\n\nconst controlOf = (type: SchemaAST.AST, name: PropertyKey, path: string): Control => {\n const control: ControlKind = isLiteralUnion(type) ? 'select' : type._tag === 'Boolean' ? 'checkbox' : 'input';\n return { kind: 'control', control, label: label(name, type), path };\n};\n\nconst childOf = (type: SchemaAST.AST, name: PropertyKey, path: string, depth: number): FormChild => {\n const base = unwrapOptional(unwrapSuspend(type));\n\n const element = arrayElementOf(base);\n if (element && depth > 0) {\n // The array frame already names the collection; an item template carries no label of its own.\n const item = { ...childOf(element, '', `${path}[]`, depth - 1), label: '' };\n return { kind: 'array', label: label(name, base), path, item };\n }\n\n // Nested struct: recurse. Declarations (refs, opaque types) fall through to a plain control —\n // walking into them risks unbounded recursion and they render as pickers anyway.\n if (depth > 0 && !isLiteralUnion(base)) {\n const properties = propertiesOf(base);\n if (properties.length > 0) {\n return {\n kind: 'group',\n label: label(name, base),\n path,\n children: properties.map((property) =>\n childOf(property.type, property.name, `${path}.${String(property.name)}`, depth - 1),\n ),\n };\n }\n }\n\n return controlOf(base, name, path);\n};\n\n/** Convert a schema into a form drawing: the phase-1 slice of the app model. */\nexport const fromSchema = (schema: Schema.Top, options: FromSchemaOptions = {}): Form => {\n const { maxDepth = 4 } = options;\n const children = propertiesOf(schema.ast)\n .filter((property) => property.name !== 'id')\n .map((property) => childOf(property.type, property.name, String(property.name), maxDepth));\n return { kind: 'form', children };\n};\n\n/** The schema's title annotation — container chrome, not form content. */\nexport const schemaTitle = (schema: Schema.Top): string | undefined => titleOf(schema.ast);\n\n/** Wrap a form in the app-ontology containers for a full schematic. */\nexport const deckOf = (form: Form, title?: string): Deck => ({\n kind: 'deck',\n planks: [{ kind: 'plank', label: title, child: { kind: 'panel', child: form } }],\n});\n\n//\n// Scene layout. Vertical flow; containers pad and frame their content. Units are scene units\n// (the caller scales), mirroring the mermaid dialect.\n//\n\nconst CONTROL_W = 200;\nconst CONTROL_H = 28;\nconst TOGGLE_W = 28;\nconst LABEL_H = 18;\nconst GAP = 12;\nconst PAD = 16;\nconst TITLE_H = 22;\nconst PLUS_H = 20;\n\ntype Emit = { commands: Scene.Command[]; elements: Scene.Element[] };\n\nconst controlHeight = (node: Control) => (node.label ? LABEL_H : 0) + CONTROL_H;\n\nconst heightOf = (node: UiNode): number => {\n switch (node.kind) {\n case 'control':\n return controlHeight(node);\n case 'group':\n // An anonymous group (an array's item template) flows its children without chrome.\n if (!node.label) {\n return node.children.reduce((sum, child, index) => sum + heightOf(child) + (index > 0 ? GAP : 0), 0);\n }\n return TITLE_H + node.children.reduce((sum, child) => sum + heightOf(child) + GAP, 0) + PAD;\n case 'array':\n return TITLE_H + heightOf(node.item) + PAD;\n case 'form':\n return node.children.reduce((sum, child, index) => sum + heightOf(child) + (index > 0 ? GAP : 0), 0);\n case 'panel':\n return heightOf(node.child) + PAD * 2 + TITLE_H;\n case 'plank':\n return heightOf(node.child) + PAD * 2 + (node.label ? TITLE_H : 0);\n case 'deck':\n return Math.max(...node.planks.map(heightOf), 0) + PAD * 2;\n }\n};\n\nconst widthOf = (node: UiNode): number => {\n switch (node.kind) {\n case 'control':\n return CONTROL_W;\n case 'group':\n return Math.max(...node.children.map(widthOf), CONTROL_W) + (node.label ? PAD : 0);\n case 'array':\n return Math.max(widthOf(node.item), CONTROL_W) + PAD;\n case 'form':\n return Math.max(...node.children.map(widthOf), CONTROL_W);\n case 'panel':\n return widthOf(node.child) + PAD * 2;\n case 'plank':\n return widthOf(node.child) + PAD * 2;\n case 'deck':\n return node.planks.reduce((sum, plank, index) => sum + widthOf(plank) + (index > 0 ? GAP : 0), 0) + PAD * 2;\n }\n};\n\n/** Qualify a node id with its container, so two planks over the same schema stay addressable. */\nconst qualify = (prefix: string, path: string): string => (prefix ? `${prefix}.${path}` : path);\n\n/** One world object per control (id = container path), so drawn controls stay individually addressable. */\nconst emitControl = (node: Control, x: number, y: number, emit: Emit, prefix: string): void => {\n const top = node.label ? LABEL_H : 0;\n const elements: Scene.Element[] = node.label\n ? [{ kind: 'text', id: 'label', x: 0, y: 0, text: node.label, weight: 's', color: 'grey' }]\n : [];\n switch (node.control) {\n case 'checkbox':\n case 'switch':\n elements.push({ kind: 'rect', id: 'box', x: 0, y: top, w: TOGGLE_W, h: CONTROL_H, stroke: 'solid' });\n break;\n case 'select':\n elements.push(\n { kind: 'rect', id: 'box', x: 0, y: top, w: CONTROL_W, h: CONTROL_H, stroke: 'solid' },\n { kind: 'text', id: 'caret', x: CONTROL_W - 20, y: top + 4, text: '*', weight: 's', color: 'grey' },\n );\n break;\n case 'input':\n elements.push({ kind: 'rect', id: 'box', x: 0, y: top, w: CONTROL_W, h: CONTROL_H, stroke: 'solid' });\n break;\n }\n emit.commands.push({ op: 'upsert-object', object: { id: qualify(prefix, node.path), origin: { x, y }, elements } });\n};\n\nconst frame = (id: string, x: number, y: number, w: number, h: number, title: string | undefined, emit: Emit): void => {\n const elements: Scene.Element[] = [{ kind: 'rect', id: 'frame', x: 0, y: 0, w, h, stroke: 'dashed', color: 'grey' }];\n if (title) {\n elements.push({ kind: 'text', id: 'title', x: PAD / 2, y: 2, text: title, weight: 's' });\n }\n emit.commands.push({ op: 'upsert-object', object: { id, origin: { x, y }, elements } });\n};\n\nconst emitNode = (node: UiNode, x: number, y: number, emit: Emit, prefix = ''): void => {\n switch (node.kind) {\n case 'control':\n emitControl(node, x, y, emit, prefix);\n break;\n\n case 'group': {\n const anonymous = !node.label;\n if (!anonymous) {\n frame(qualify(prefix, node.path), x, y, widthOf(node), heightOf(node), node.label, emit);\n }\n let cursor = y + (anonymous ? 0 : TITLE_H);\n for (const child of node.children) {\n emitNode(child, x + (anonymous ? 0 : PAD), cursor, emit, prefix);\n cursor += heightOf(child) + GAP;\n }\n break;\n }\n\n case 'array': {\n const width = widthOf(node);\n const id = qualify(prefix, node.path);\n frame(id, x, y, width, heightOf(node), node.label, emit);\n // The add button sits on the header line, where the array marker reads in ASCII.\n emit.commands.push({\n op: 'upsert-object',\n object: {\n id: `${id}.add`,\n origin: { x: x + width - TOGGLE_W - 4, y: y + 2 },\n elements: [{ kind: 'rect', id: 'box', x: 0, y: 0, w: TOGGLE_W, h: PLUS_H, text: '+', stroke: 'solid' }],\n },\n });\n emitNode(node.item, x + PAD, y + TITLE_H, emit, prefix);\n break;\n }\n\n case 'form': {\n let cursor = y;\n for (const child of node.children) {\n emitNode(child, x, cursor, emit, prefix);\n cursor += heightOf(child) + GAP;\n }\n break;\n }\n\n case 'panel': {\n const id = qualify(prefix, 'panel');\n frame(id, x, y, widthOf(node), heightOf(node), node.label ?? 'panel', emit);\n emitNode(node.child, x + PAD, y + TITLE_H + PAD, emit, id);\n break;\n }\n\n case 'plank': {\n const id = prefix || 'plank';\n frame(id, x, y, widthOf(node), heightOf(node), node.label, emit);\n emitNode(node.child, x + PAD, y + PAD + (node.label ? TITLE_H : 0), emit, id);\n break;\n }\n\n case 'deck': {\n const id = qualify(prefix, 'deck');\n frame(id, x, y, widthOf(node), heightOf(node), undefined, emit);\n let cursor = x + PAD;\n // Index, not label: an unlabeled plank must still get a distinct id.\n node.planks.forEach((plank, index) => {\n emitNode(plank, cursor, y + PAD, emit, `${id}.plank${index}`);\n cursor += widthOf(plank) + GAP;\n });\n break;\n }\n }\n};\n\nexport type CompileOptions = {\n /** Canvas position of the schematic's top-left, in canvas px. */\n origin?: Scene.Point;\n /** Canvas px per scene unit. */\n scale?: number;\n};\n\n/** Compile a UI drawing into scene commands (frames first, controls above them). */\nexport const compile = (node: UiNode, options: CompileOptions = {}): Scene.Command[] => {\n const { origin = { x: 0, y: 0 }, scale = 1 } = options;\n const emit: Emit = { commands: [], elements: [] };\n emitNode(node, 0, 0, emit);\n return emit.commands.map((command) =>\n command.op === 'upsert-object'\n ? {\n ...command,\n object: {\n ...command.object,\n scale,\n origin: {\n x: origin.x + (command.object.origin?.x ?? 0) * scale,\n y: origin.y + (command.object.origin?.y ?? 0) * scale,\n },\n },\n }\n : command,\n );\n};\n\n//\n// ASCII renderer — the interim/low-cost target over the same model.\n//\n\nconst GLYPHS: Record<ControlKind, string> = {\n input: '[__________]',\n select: '[_________*]',\n checkbox: '[ ]',\n switch: '(o )',\n};\n\nconst indent = (lines: string[], prefix: string): string[] => lines.map((line) => (prefix + line).trimEnd());\n\n/** Wrap lines in a +--- box, optionally titled. */\nconst boxed = (lines: string[], title?: string): string[] => {\n const width = Math.max(...lines.map((line) => line.length), (title?.length ?? 0) + 4, 12);\n const top = title\n ? `+- ${title} ${'-'.repeat(Math.max(width - title.length - 1, 1))}+`\n : `+${'-'.repeat(width + 2)}+`;\n return [top, ...lines.map((line) => `| ${line.padEnd(width)} |`), `+${'-'.repeat(width + 2)}+`];\n};\n\nconst asciiLines = (node: UiNode): string[] => {\n switch (node.kind) {\n case 'control':\n return node.label ? [node.label, GLYPHS[node.control]] : [GLYPHS[node.control]];\n case 'group': {\n const children = node.children.flatMap((child, index) =>\n index > 0 ? ['', ...asciiLines(child)] : asciiLines(child),\n );\n return node.label ? [node.label, ...indent(children, ' ')] : children;\n }\n case 'array':\n return [`${node.label} [+]`, ...indent(asciiLines(node.item), ' ')];\n case 'form':\n return node.children.flatMap((child, index) => (index > 0 ? ['', ...asciiLines(child)] : asciiLines(child)));\n case 'panel':\n return boxed(asciiLines(node.child), node.label);\n case 'plank':\n return boxed(asciiLines(node.child), node.label);\n case 'deck':\n return node.planks.flatMap((plank, index) => (index > 0 ? ['', ...asciiLines(plank)] : asciiLines(plank)));\n }\n};\n\n/** Render a UI drawing as ASCII art. */\nexport const renderAscii = (node: UiNode): string => asciiLines(node).join('\\n');\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Engine-backed placement for the grid UML dialect: dagre or ELK replace the hand-rolled\n// lane/column pass (proper crossing minimization and straightness-seeking coordinate\n// assignment), while parsing, cell measurement, grid snapping, routing, and emission stay\n// shared with `uml-grid.ts`. See `docs/DESIGN.md`.\n//\n\nimport { layout as dagreLayout, graphlib } from '@dagrejs/dagre';\nimport ELK from 'elkjs/lib/elk.bundled.js';\n\nimport type * as Scene from './scene.ts';\nimport {\n type Cell,\n GRID,\n type CompileOptions as GridCompileOptions,\n type Rect,\n emit,\n measureCell,\n} from './uml-grid.ts';\nimport { type Direction, type UmlModel, parse, relationRanks } from './uml.ts';\n\nexport type Engine = 'dagre' | 'elk';\n\nexport type CompileOptions = Omit<GridCompileOptions, 'route'> & {\n /** Placement engine (default 'elk'). */\n engine?: Engine;\n};\n\nconst GAP_MAIN = GRID * 4;\nconst GAP_CROSS = GRID * 4;\n\nconst snap = (value: number) => Math.round(value / GRID) * GRID;\n\ntype PlaceOptions = {\n cell: Cell;\n gapMain: number;\n gapCross: number;\n direction: Direction;\n};\n\nconst DAGRE_DIRECTION: Record<Direction, string> = { TB: 'TB', BT: 'BT', LR: 'LR', RL: 'RL' };\nconst ELK_DIRECTION: Record<Direction, string> = { TB: 'DOWN', BT: 'UP', LR: 'RIGHT', RL: 'LEFT' };\n\n/**\n * Edges oriented for layering: inheritance, realization, and dependency point at abstractions,\n * which rank ABOVE their sources — so those edges are reversed for the engine (which lays out\n * source-above-target), matching `relationRanks`.\n */\nconst orientedEdges = (model: UmlModel): { from: string; to: string }[] =>\n model.relations.map((relation) =>\n relation.kind === 'inheritance' || relation.kind === 'realization' || relation.kind === 'dependency'\n ? { from: relation.to, to: relation.from }\n : { from: relation.from, to: relation.to },\n );\n\n/** Snap engine output to the document grid and normalize the top-left to (0, 0). */\nconst snapRects = (rects: Map<string, Rect>): Map<string, Rect> => {\n const snapped = new Map([...rects].map(([id, rect]) => [id, { ...rect, x: snap(rect.x), y: snap(rect.y) }]));\n const minX = Math.min(...[...snapped.values()].map((rect) => rect.x), 0);\n const minY = Math.min(...[...snapped.values()].map((rect) => rect.y), 0);\n return new Map([...snapped].map(([id, rect]) => [id, { ...rect, x: rect.x - minX, y: rect.y - minY }]));\n};\n\n/** dagre: network-simplex layering + median-sweep crossing minimization. Sync. */\nconst dagrePlace = (model: UmlModel, { cell, gapMain, gapCross, direction }: PlaceOptions): Map<string, Rect> => {\n const graph = new graphlib.Graph();\n graph.setGraph({\n rankdir: DAGRE_DIRECTION[direction],\n ranker: 'network-simplex',\n ranksep: gapMain,\n nodesep: gapCross,\n edgesep: gapCross / 2,\n });\n graph.setDefaultEdgeLabel(() => ({}));\n for (const entry of model.classes) {\n graph.setNode(entry.id, { width: cell.w, height: cell.h });\n }\n for (const edge of orientedEdges(model)) {\n graph.setEdge(edge.from, edge.to);\n }\n dagreLayout(graph);\n\n // dagre reports node centers.\n const rects = new Map<string, Rect>(\n model.classes.map((entry) => {\n const node = graph.node(entry.id);\n return [entry.id, { x: node.x - cell.w / 2, y: node.y - cell.h / 2, w: cell.w, h: cell.h }];\n }),\n );\n return snapRects(rects);\n};\n\n/** ELK layered: layer-sweep crossing minimization + Brandes-Köpf placement. Async. */\nconst elkPlace = async (\n model: UmlModel,\n { cell, gapMain, gapCross, direction }: PlaceOptions,\n): Promise<Map<string, Rect>> => {\n const elk = new ELK();\n const result = await elk.layout({\n id: 'root',\n layoutOptions: {\n 'elk.algorithm': 'layered',\n 'elk.direction': ELK_DIRECTION[direction],\n 'elk.layered.spacing.nodeNodeBetweenLayers': String(gapMain),\n 'elk.spacing.nodeNode': String(gapCross),\n // Favors long straight chains over balanced centering — fewer jagged connectors.\n 'elk.layered.nodePlacement.strategy': 'BRANDES_KOEPF',\n // Keeps declaration order among otherwise-unconstrained siblings, so peers stay gathered.\n 'elk.layered.considerModelOrder.strategy': 'PREFER_NODES',\n },\n children: model.classes.map((entry) => ({ id: entry.id, width: cell.w, height: cell.h })),\n edges: orientedEdges(model).map((edge, index) => ({\n id: `edge-${index}`,\n sources: [edge.from],\n targets: [edge.to],\n })),\n });\n\n const rects = new Map<string, Rect>(\n (result.children ?? []).map((child) => [child.id, { x: child.x ?? 0, y: child.y ?? 0, w: cell.w, h: cell.h }]),\n );\n return snapRects(rects);\n};\n\n/**\n * Compile a mermaid class diagram with engine-backed placement; identical output structure to\n * `UmlGrid.compile` (equal-size grid cells, orthogonal Z-routed connectors), but node positions\n * come from dagre/ELK. Async because ELK is.\n */\nexport const compile = async (source: string, options: CompileOptions = {}): Promise<Scene.Command[]> => {\n const { origin, scale, maxWidth = GRID * 6, engine = 'elk' } = options;\n const model = parse(source);\n const cell = measureCell(model, { maxWidth, cell: options.cell, titleHeight: options.titleHeight });\n const place: PlaceOptions = {\n cell,\n gapMain: snap(options.gapMain ?? GAP_MAIN),\n gapCross: snap(options.gapCross ?? GAP_CROSS),\n direction: model.direction,\n };\n const rects = engine === 'dagre' ? dagrePlace(model, place) : await elkPlace(model, place);\n return emit({ model, cell, rects, ranks: relationRanks(model) }, { origin, scale });\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Rule-based pluggable layout: prioritized rules claim disjoint node GROUPS and lay each out in\n// group-local coordinates; groups then pack as super-nodes (ranked by their cross-group edges)\n// with non-overlapping borders, and the shared router connects nodes across them. Rules capture\n// domain shape the generic engines cannot: an inheritance tree reads as a tree, a call chain as\n// a column. See `docs/DESIGN.md`.\n//\n\nimport * as Layout from './layout.ts';\nimport type * as Scene from './scene.ts';\nimport {\n type Cell,\n GRID,\n type CompileOptions as GridCompileOptions,\n type Rect,\n emit,\n measureCell,\n} from './uml-grid.ts';\nimport { type UmlModel, parse, relationRanks } from './uml.ts';\n\nconst GAP = GRID * 2;\nconst GROUP_GAP = GRID * 3;\nconst FRAME_PAD = GRID;\n\nconst snap = (value: number) => Math.round(value / GRID) * GRID;\n\n/** A laid-out group: member rects in group-local coordinates plus the packed bounds. */\nexport type Group = {\n id: string;\n /** Rule that claimed the group (frame label; singletons carry none). */\n rule?: string;\n rects: Map<string, Rect>;\n w: number;\n h: number;\n};\n\n/**\n * A layout rule: claims disjoint groups from the still-unclaimed nodes and lays each out\n * internally. Rules run in priority order; unclaimed nodes fall through to singleton groups.\n */\nexport type GroupRule = {\n id: string;\n apply: (model: UmlModel, unclaimed: Set<string>, cell: Cell) => Group[];\n};\n\n/** Relations oriented so the target should sit ABOVE the source (arrows read upward). */\nconst upEdges = (model: UmlModel): { from: string; to: string }[] =>\n model.relations.map((relation) =>\n relation.kind === 'inheritance' || relation.kind === 'realization' || relation.kind === 'dependency'\n ? { from: relation.from, to: relation.to }\n : { from: relation.to, to: relation.from },\n );\n\n/**\n * Inheritance trees: each supertype with claimable subtypes forms a group — the hierarchy stacks\n * vertically (root on top, arrows up) and peers share a horizontal axis, packed as a tidy tree\n * (each parent centered over its subtree).\n */\nexport const inheritanceTreeRule: GroupRule = {\n id: 'inheritance',\n apply: (model, unclaimed, cell) => {\n const children = new Map<string, string[]>();\n const hasParent = new Set<string>();\n for (const relation of model.relations) {\n if (\n (relation.kind === 'inheritance' || relation.kind === 'realization') &&\n unclaimed.has(relation.from) &&\n unclaimed.has(relation.to)\n ) {\n // relation: subtype → supertype.\n children.set(relation.to, [...(children.get(relation.to) ?? []), relation.from]);\n hasParent.add(relation.from);\n }\n }\n\n const groups: Group[] = [];\n for (const [root] of children) {\n if (hasParent.has(root)) {\n continue;\n }\n const rects = new Map<string, Rect>();\n // Cyclic or diamond hierarchies (LLM/user input) must not recurse forever; each node\n // renders once, on first visit.\n const claimable = (id: string) => unclaimed.has(id) && !rects.has(id);\n const widths = new Map<string, number>();\n // Tidy-tree: a subtree is as wide as its children row (or one cell); parent centers over it.\n const layoutSubtree = (id: string, x: number, depth: number): number => {\n rects.set(id, { x: 0, y: 0, w: cell.w, h: cell.h });\n const kids = (children.get(id) ?? []).filter(claimable);\n const kidWidths = kids.map((kid) => subtreeWidth(kid));\n const rowWidth = kidWidths.reduce((sum, w) => sum + w, 0) + Math.max(0, kids.length - 1) * GAP;\n const width = Math.max(cell.w, rowWidth);\n let childX = x + (width - rowWidth) / 2;\n for (const [index, kid] of kids.entries()) {\n layoutSubtree(kid, childX, depth + 1);\n childX += kidWidths[index] + GAP;\n }\n rects.set(id, { x: x + (width - cell.w) / 2, y: depth * (cell.h + GAP), w: cell.w, h: cell.h });\n return width;\n };\n const subtreeWidth = (id: string, seen: Set<string> = new Set()): number => {\n const cached = widths.get(id);\n if (cached !== undefined) {\n return cached;\n }\n if (seen.has(id)) {\n return cell.w;\n }\n seen.add(id);\n const kids = (children.get(id) ?? []).filter((kid) => unclaimed.has(kid) && !rects.has(kid) && !seen.has(kid));\n const width =\n kids.length === 0\n ? cell.w\n : Math.max(cell.w, kids.reduce((sum, kid) => sum + subtreeWidth(kid, seen), 0) + (kids.length - 1) * GAP);\n widths.set(id, width);\n return width;\n };\n const width = layoutSubtree(root, 0, 0);\n const depth = Math.max(...[...rects.values()].map((rect) => rect.y)) + cell.h;\n if (rects.size < 2) {\n continue;\n }\n for (const id of rects.keys()) {\n unclaimed.delete(id);\n }\n groups.push({ id: `tree:${root}`, rule: 'inheritance', rects, w: width, h: depth });\n }\n return groups;\n },\n};\n\n/**\n * Longest linear chain: the longest path through the still-unclaimed up-oriented relation graph\n * renders left to right (each target directly right of its source).\n */\nexport const linearChainRule: GroupRule = {\n id: 'chain',\n apply: (model, unclaimed, cell) => {\n const edges = upEdges(model).filter((edge) => unclaimed.has(edge.from) && unclaimed.has(edge.to));\n const back = Layout.backEdges([...unclaimed], edges);\n const forward = edges.filter((edge) => !back.has(edge));\n const next = new Map<string, string[]>();\n for (const edge of forward) {\n next.set(edge.from, [...(next.get(edge.from) ?? []), edge.to]);\n }\n\n // Longest path by DFS memo (the forward graph is acyclic after back-edge removal).\n const memo = new Map<string, string[]>();\n const longestFrom = (id: string): string[] => {\n const cached = memo.get(id);\n if (cached) {\n return cached;\n }\n let best: string[] = [];\n for (const target of next.get(id) ?? []) {\n const path = longestFrom(target);\n if (path.length > best.length) {\n best = path;\n }\n }\n const result = [id, ...best];\n memo.set(id, result);\n return result;\n };\n\n let chain: string[] = [];\n for (const id of unclaimed) {\n const path = longestFrom(id);\n if (path.length > chain.length) {\n chain = path;\n }\n }\n if (chain.length < 3) {\n return [];\n }\n\n const rects = new Map<string, Rect>();\n // Chain runs source → target, reading left to right.\n chain.forEach((id, index) => {\n rects.set(id, { x: index * (cell.w + GAP), y: 0, w: cell.w, h: cell.h });\n unclaimed.delete(id);\n });\n return [\n { id: `chain:${chain[0]}`, rule: 'chain', rects, w: chain.length * cell.w + (chain.length - 1) * GAP, h: cell.h },\n ];\n },\n};\n\nexport type CompileOptions = Omit<GridCompileOptions, 'route'> & {\n /** Grouping rules, highest priority first. */\n rules?: GroupRule[];\n};\n\n/** Run the rules over the model; leftovers become singleton groups. */\nexport const buildGroups = (model: UmlModel, cell: Cell, rules: GroupRule[]): Group[] => {\n const unclaimed = new Set(model.classes.map((entry) => entry.id));\n const groups: Group[] = [];\n for (const rule of rules) {\n groups.push(...rule.apply(model, unclaimed, cell));\n }\n for (const id of unclaimed) {\n groups.push({\n id: `node:${id}`,\n rects: new Map([[id, { x: 0, y: 0, w: cell.w, h: cell.h }]]),\n w: cell.w,\n h: cell.h,\n });\n }\n return groups;\n};\n\n/**\n * Pack groups as super-nodes: rank by up-oriented cross-group edges (target group above), then\n * lay ranks out as rows, bottom rank last — mirroring the node-level convention.\n */\nexport const packGroups = (model: UmlModel, groups: Group[]): Map<string, Scene.Point> => {\n const groupOf = new Map<string, Group>();\n for (const group of groups) {\n for (const id of group.rects.keys()) {\n groupOf.set(id, group);\n }\n }\n const crossEdges = upEdges(model)\n .map((edge) => ({ from: groupOf.get(edge.from)!.id, to: groupOf.get(edge.to)!.id }))\n .filter((edge) => edge.from !== edge.to);\n const groupRanks = Layout.rank(\n groups.map((group) => group.id),\n // Rank grows downward from sources; cross edges point up, so invert.\n crossEdges.map((edge) => ({ from: edge.to, to: edge.from })),\n );\n\n const lanes = new Map<number, Group[]>();\n for (const group of groups) {\n const rank = groupRanks.get(group.id) ?? 0;\n lanes.set(rank, [...(lanes.get(rank) ?? []), group]);\n }\n const origins = new Map<string, Scene.Point>();\n let y = 0;\n for (const rank of [...lanes.keys()].sort((left, right) => left - right)) {\n const members = lanes.get(rank)!;\n let x = 0;\n for (const group of members) {\n origins.set(group.id, { x: snap(x), y: snap(y) });\n x += group.w + GROUP_GAP;\n }\n y += Math.max(...members.map((group) => group.h)) + GROUP_GAP;\n }\n return origins;\n};\n\n/** Absolute node rects for a (possibly partial) group placement. */\nexport const resolveRects = (groups: Group[], origins: Map<string, Scene.Point>): Map<string, Rect> => {\n const rects = new Map<string, Rect>();\n for (const group of groups) {\n const at = origins.get(group.id);\n if (!at) {\n continue;\n }\n for (const [id, rect] of group.rects) {\n rects.set(id, { ...rect, x: at.x + rect.x, y: at.y + rect.y });\n }\n }\n return rects;\n};\n\n/** Dashed frames behind multi-node groups. */\nexport const frameCommands = (\n groups: Group[],\n origins: Map<string, Scene.Point>,\n { origin = { x: 0, y: 0 }, scale = 1 }: { origin?: Scene.Point; scale?: number } = {},\n): Scene.Command[] =>\n groups\n .filter((group) => group.rects.size > 1 && origins.has(group.id))\n .map((group) => {\n const at = origins.get(group.id)!;\n return {\n op: 'upsert-object',\n object: {\n id: `group:${group.id}`,\n origin: { x: origin.x + (at.x - FRAME_PAD) * scale, y: origin.y + (at.y - FRAME_PAD) * scale },\n scale,\n elements: [\n {\n kind: 'rect',\n id: 'frame',\n x: 0,\n y: 0,\n w: group.w + FRAME_PAD * 2,\n h: group.h + FRAME_PAD * 2,\n stroke: 'dashed',\n color: 'grey',\n },\n ],\n },\n };\n });\n\n/**\n * Compile with rule-based grouping: rules claim groups, leftovers become singletons, groups pack\n * as super-nodes ranked by their cross-group edges (lanes advance vertically; no borders overlap\n * by construction), and multi-node groups render a dashed frame behind their members.\n */\nexport const compile = (source: string, options: CompileOptions = {}): Scene.Command[] => {\n const { origin = { x: 0, y: 0 }, scale = 1, maxWidth = GRID * 6 } = options;\n const rules = options.rules ?? [inheritanceTreeRule, linearChainRule];\n const model = parse(source);\n const cell = measureCell(model, { maxWidth, cell: options.cell, titleHeight: options.titleHeight });\n const groups = buildGroups(model, cell, rules);\n const origins = packGroups(model, groups);\n const rects = resolveRects(groups, origins);\n return [\n ...frameCommands(groups, origins, { origin, scale }),\n ...emit({ model, cell, rects, ranks: relationRanks(model) }, { origin, scale }),\n ];\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Scored placement search: the longest chain anchors the center; a greedy tree search walks the\n// relation graph outward, trying candidate positions for each still-unplaced group next to its\n// placed neighbour (above/below preferred, connecting nodes axis-aligned) and keeping the\n// highest-scoring one. The final layout is the better of the search and the rank packing, under\n// one score: +1 per straight connector, −1 per crossing. Entirely custom by necessity — ELK and\n// dagre are one-shot global optimizers with no scoring callback or incremental placement API —\n// but either can still lay out a group's interior or contribute a candidate to the same scorer.\n// See `docs/DESIGN.md`.\n//\n\nimport type * as Scene from './scene.ts';\nimport { GRID, type CompileOptions as GridCompileOptions, type Rect, emit, measureCell, zRouter } from './uml-grid.ts';\nimport {\n type Group,\n type GroupRule,\n buildGroups,\n frameCommands,\n inheritanceTreeRule,\n linearChainRule,\n packGroups,\n resolveRects,\n} from './uml-rules.ts';\nimport { type UmlModel, parse, relationRanks } from './uml.ts';\n\nconst GAP = GRID * 3;\n\nconst snap = (value: number) => Math.round(value / GRID) * GRID;\n\ntype Point = Scene.Point;\ntype Segment = [Point, Point];\n\nconst segmentsOf = (points: readonly Point[]): Segment[] =>\n points.slice(0, -1).map((point, index) => [point, points[index + 1]]);\n\n/** Orthogonal segment crossing: proper intersections plus collinear overlaps. */\nconst crosses = ([a1, a2]: Segment, [b1, b2]: Segment): boolean => {\n const aVertical = a1.x === a2.x;\n const bVertical = b1.x === b2.x;\n if (aVertical !== bVertical) {\n const [v1, v2] = aVertical ? [a1, a2] : [b1, b2];\n const [h1, h2] = aVertical ? [b1, b2] : [a1, a2];\n return (\n v1.x > Math.min(h1.x, h2.x) &&\n v1.x < Math.max(h1.x, h2.x) &&\n h1.y > Math.min(v1.y, v2.y) &&\n h1.y < Math.max(v1.y, v2.y)\n );\n }\n if (aVertical) {\n return a1.x === b1.x && Math.min(a1.y, a2.y) < Math.max(b1.y, b2.y) && Math.min(b1.y, b2.y) < Math.max(a1.y, a2.y);\n }\n return a1.y === b1.y && Math.min(a1.x, a2.x) < Math.max(b1.x, b2.x) && Math.min(b1.x, b2.x) < Math.max(a1.x, a2.x);\n};\n\n/** Direction changes along a polyline, ignoring zero-length segments. */\nconst bends = (route: readonly Point[]): number => {\n const points = route.filter(\n (point, index) => index === 0 || point.x !== route[index - 1].x || point.y !== route[index - 1].y,\n );\n let count = 0;\n for (let index = 2; index < points.length; index++) {\n const [a, b, c] = [points[index - 2], points[index - 1], points[index]];\n if (!((a.x === b.x && b.x === c.x) || (a.y === b.y && b.y === c.y))) {\n count++;\n }\n }\n return count;\n};\n\n/**\n * Layout score over the placed subset: +1 per straight or single-bend (L) route, −1 per crossing\n * pair. Routes come from the cheap Z-router — the score ranks candidates, the A* router draws\n * the final picture.\n */\nexport const scoreLayout = (model: UmlModel, rects: Map<string, Rect>): number => {\n const horizontal = model.direction === 'LR' || model.direction === 'RL';\n const routes: Point[][] = [];\n for (const relation of model.relations) {\n const from = rects.get(relation.from);\n const to = rects.get(relation.to);\n if (!from || !to) {\n continue;\n }\n routes.push(zRouter({ relation, from, to, horizontal, offset: 0 }));\n }\n\n let score = 0;\n for (const route of routes) {\n if (bends(route) <= 1) {\n score += 1;\n }\n }\n for (let a = 0; a < routes.length; a++) {\n for (let b = a + 1; b < routes.length; b++) {\n const pairCrosses = segmentsOf(routes[a]).some((left) =>\n segmentsOf(routes[b]).some((right) => crosses(left, right)),\n );\n if (pairCrosses) {\n score -= 1;\n }\n }\n }\n return score;\n};\n\nconst overlaps = (a: Rect, b: Rect): boolean =>\n a.x < b.x + b.w + GAP && b.x < a.x + a.w + GAP && a.y < b.y + b.h + GAP && b.y < a.y + a.h + GAP;\n\n/**\n * Greedy tree search: place the chain (or largest) group first, then repeatedly place the\n * unplaced group connected to the earliest-placed node, trying axis-aligned candidates around\n * the anchor (below and above preferred, then right/left, sliding off collisions) and keeping\n * the best-scoring one.\n */\nexport const searchPlacement = (model: UmlModel, groups: Group[]): Map<string, Scene.Point> => {\n const groupOf = new Map<string, Group>();\n for (const group of groups) {\n for (const id of group.rects.keys()) {\n groupOf.set(id, group);\n }\n }\n\n const seed =\n groups.find((group) => group.rule === 'chain') ??\n [...groups].sort((left, right) => right.rects.size - left.rects.size)[0];\n // An empty or unparseable source yields no groups; compile then emits an empty scene.\n if (!seed) {\n return new Map();\n }\n\n const origins = new Map<string, Point>();\n origins.set(seed.id, { x: 0, y: 0 });\n const placedNodes: string[] = [...seed.rects.keys()];\n\n const absolute = (id: string): Rect | undefined => {\n const group = groupOf.get(id)!;\n const at = origins.get(group.id);\n if (!at) {\n return undefined;\n }\n const local = group.rects.get(id)!;\n return { ...local, x: at.x + local.x, y: at.y + local.y };\n };\n const placedBounds = (): Rect[] =>\n groups.flatMap((group) => {\n const at = origins.get(group.id);\n return at ? [{ x: at.x, y: at.y, w: group.w, h: group.h }] : [];\n });\n\n while (origins.size < groups.length) {\n // Frontier: the earliest-placed node with a relation into an unplaced group.\n let anchorId: string | undefined;\n let connection: { group: Group; node: string } | undefined;\n for (const placed of placedNodes) {\n for (const relation of model.relations) {\n const other = relation.from === placed ? relation.to : relation.to === placed ? relation.from : undefined;\n if (other && !origins.has(groupOf.get(other)!.id)) {\n anchorId = placed;\n connection = { group: groupOf.get(other)!, node: other };\n break;\n }\n }\n if (connection) {\n break;\n }\n }\n // Disconnected remainder: park it right of everything placed so far.\n if (!connection || !anchorId) {\n const group = groups.find((candidate) => !origins.has(candidate.id))!;\n const rightmost = Math.max(...placedBounds().map((rect) => rect.x + rect.w), 0);\n origins.set(group.id, { x: snap(rightmost + GAP), y: 0 });\n placedNodes.push(...group.rects.keys());\n continue;\n }\n\n const anchor = absolute(anchorId)!;\n const local = connection.group.rects.get(connection.node)!;\n const anchorCenterX = anchor.x + anchor.w / 2;\n const anchorCenterY = anchor.y + anchor.h / 2;\n // Candidates align the connecting node's axis with the anchor's, above/below preferred.\n const candidates: Point[] = [\n { x: anchorCenterX - local.x - local.w / 2, y: anchor.y + anchor.h + GAP },\n { x: anchorCenterX - local.x - local.w / 2, y: anchor.y - GAP - connection.group.h },\n { x: anchor.x + anchor.w + GAP, y: anchorCenterY - local.y - local.h / 2 },\n { x: anchor.x - GAP - connection.group.w, y: anchorCenterY - local.y - local.h / 2 },\n ];\n\n let best: { at: Point; score: number } | undefined;\n for (const [candidateIndex, candidate] of candidates.entries()) {\n // Slide along the placement axis (in grid steps) until the group's border clears others.\n const at = { x: snap(candidate.x), y: snap(candidate.y) };\n const bounds = placedBounds();\n let tries = 0;\n // The first two candidates are the below/above placements; index, not coordinate\n // coincidence, decides the slide axis.\n const vertical = candidateIndex < 2;\n while (\n bounds.some((rect) => overlaps(rect, { x: at.x, y: at.y, w: connection.group.w, h: connection.group.h })) &&\n tries < 24\n ) {\n if (vertical) {\n at.x += GRID * 2;\n } else {\n at.y += GRID * 2;\n }\n tries++;\n }\n if (tries >= 24) {\n continue;\n }\n origins.set(connection.group.id, at);\n const score = scoreLayout(model, resolveRects(groups, originsSubset(groups, origins)));\n origins.delete(connection.group.id);\n // Strict >, so earlier (preferred: below, then above) candidates win ties.\n if (!best || score > best.score) {\n best = { at, score };\n }\n }\n\n const at = best?.at ?? { x: snap(Math.max(...placedBounds().map((rect) => rect.x + rect.w)) + GAP), y: 0 };\n origins.set(connection.group.id, at);\n placedNodes.push(...connection.group.rects.keys());\n }\n\n // Normalize the top-left to (0, 0).\n const minX = Math.min(...[...origins.values()].map((point) => point.x));\n const minY = Math.min(...[...origins.values()].map((point) => point.y));\n return new Map([...origins].map(([id, point]) => [id, { x: point.x - minX, y: point.y - minY }]));\n};\n\n/** Placement restricted to placed groups, so partial layouts score without phantom rects. */\nconst originsSubset = (groups: Group[], origins: Map<string, Point>): Map<string, Point> =>\n new Map(groups.filter((group) => origins.has(group.id)).map((group) => [group.id, origins.get(group.id)!]));\n\nexport type CompileOptions = Omit<GridCompileOptions, 'route'> & {\n rules?: GroupRule[];\n};\n\n/**\n * Compile via the scored search, falling back to whichever of {search, rank packing} scores\n * higher — the search is greedy, so the packing occasionally beats it.\n */\nexport const compile = (source: string, options: CompileOptions = {}): Scene.Command[] => {\n const { origin = { x: 0, y: 0 }, scale = 1, maxWidth = GRID * 6 } = options;\n const rules = options.rules ?? [inheritanceTreeRule, linearChainRule];\n const model = parse(source);\n const cell = measureCell(model, { maxWidth, cell: options.cell, titleHeight: options.titleHeight });\n const groups = buildGroups(model, cell, rules);\n\n const searched = searchPlacement(model, groups);\n const packed = packGroups(model, groups);\n const searchedScore = scoreLayout(model, resolveRects(groups, searched));\n const packedScore = scoreLayout(model, resolveRects(groups, packed));\n const origins = searchedScore >= packedScore ? searched : packed;\n\n const rects = resolveRects(groups, origins);\n return [\n ...frameCommands(groups, origins, { origin, scale }),\n ...emit({ model, cell, rects, ranks: relationRanks(model) }, { origin, scale }),\n ];\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/content.ts","../../src/dialect.ts","../../src/aesthetics.ts","../../src/dsl/print.ts","../../src/dsl/convert.ts","../../src/dsl/compile.ts","../../src/dsl/index.ts","../../src/dx-svg.ts","../../src/score.ts","../../src/svg-handler.ts","../../src/ui.ts","../../src/uml-engine.ts","../../src/uml-rules.ts","../../src/uml-search.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Renderer-neutral command application over a canvas content map. Every renderer stores its\n// canvas as `Record<recordId, record>` and stamps DSL identity onto each managed record, so the\n// upsert/remove/move bookkeeping is identical; only the encoding differs. Renderers supply that\n// encoding via `ContentHandler` and inherit the command semantics.\n//\n\nimport { invariant } from '@dxos/invariant';\n\nimport type * as Scene from './scene.ts';\n\n/** Opaque map of record id → renderer record. */\nexport type ContentMap = Record<string, any>;\n\n/** DSL identity stamped onto a managed record. */\nexport type Identity = {\n object: string;\n element: string;\n /** Set on companion records that belong to an element rather than being one (e.g. arrow labels). */\n part?: string;\n};\n\n/** Where an object sits on the canvas: `canvas = origin + local * scale`. */\nexport type Placement = {\n origin: Scene.Point;\n scale: number;\n};\n\n/** An object as accepted by the renderer's compiler; `upsert-elements` supplies only a subset. */\nexport type ObjectInput = Scene.WorldObject | { id: string; elements: readonly Scene.Element[] };\n\n/** A world object as derived from the canvas: placement is always resolved. */\nexport type ReadWorldObject = Scene.WorldObject & Placement;\n\nexport type ReadResult = {\n scene: { objects: ReadWorldObject[] };\n /** Records on the canvas not managed by the DSL (drawn by hand). */\n unmanaged: number;\n};\n\nexport type ApplyResult = {\n /** Object ids created or modified. */\n upserted: string[];\n /** Records removed. */\n removed: number;\n};\n\n/**\n * The renderer-specific half of command application: how records carry identity, how objects\n * compile to records, and any bookkeeping the renderer's store requires.\n */\nexport type ContentHandler = {\n /** DSL identity for a record, or undefined when the record isn't managed by the DSL. */\n identify: (record: any) => Identity | undefined;\n /** Compile an object's elements into records keyed by record id. */\n render: (object: ObjectInput, placement: Placement, content: ContentMap) => ContentMap;\n /** Derive the scene from the content map. */\n read: (content: ContentMap) => ReadResult;\n /** Translate an object move into a per-record mutation. */\n translate: (record: any, delta: Scene.Point) => void;\n /** Create any scaffolding the renderer needs before its first record (e.g. a page). */\n scaffold?: (content: ContentMap) => void;\n /** Merge compiled records into the content map; defaults to a plain assign. */\n merge?: (content: ContentMap, records: ContentMap) => void;\n /** Clean up after deletions (e.g. drop bindings left dangling). */\n prune?: (content: ContentMap) => void;\n};\n\n/** Apply a batch of edit commands to the canvas content (mutates `content`). */\nexport const applyCommands = (\n content: ContentMap,\n commands: readonly Scene.Command[],\n handler: ContentHandler,\n): ApplyResult => {\n handler.scaffold?.(content);\n const upserted = new Set<string>();\n let removed = 0;\n\n const find = (objectId: string) => handler.read(content).scene.objects.find((object) => object.id === objectId);\n\n const merge = (object: ObjectInput, placement: Placement) => {\n const records = handler.render(object, placement, content);\n if (handler.merge) {\n handler.merge(content, records);\n } else {\n Object.assign(content, records);\n }\n };\n\n // Companion records (labels) are deleted alongside their element but aren't themselves\n // elements, so they don't count toward the reported total.\n const remove = (predicate: (identity: Identity) => boolean): number => {\n let count = 0;\n for (const [key, record] of Object.entries(content)) {\n const identity = handler.identify(record);\n if (identity && predicate(identity)) {\n // Read before delete: ECHO proxies dereference lazily, so fields vanish once removed.\n const isPart = identity.part !== undefined;\n delete content[key];\n if (!isPart) {\n count++;\n }\n }\n }\n handler.prune?.(content);\n return count;\n };\n\n for (const command of commands) {\n switch (command.op) {\n case 'upsert-object': {\n const previous = find(command.object.id);\n removed += remove((identity) => identity.object === command.object.id);\n merge(command.object, {\n origin: command.object.origin ?? previous?.origin ?? { x: 0, y: 0 },\n scale: command.object.scale ?? previous?.scale ?? 1,\n });\n upserted.add(command.object.id);\n break;\n }\n\n case 'upsert-elements': {\n const previous = find(command.objectId);\n invariant(previous, `unknown object: ${command.objectId} (use upsert-object to create it)`);\n const ids = new Set(command.elements.map((element) => element.id));\n removed += remove((identity) => identity.object === command.objectId && ids.has(identity.element));\n merge({ id: command.objectId, elements: command.elements }, previous);\n upserted.add(command.objectId);\n break;\n }\n\n case 'remove-elements': {\n const ids = new Set(command.elementIds);\n removed += remove((identity) => identity.object === command.objectId && ids.has(identity.element));\n break;\n }\n\n case 'remove-object': {\n removed += remove((identity) => identity.object === command.objectId);\n break;\n }\n\n case 'move-object': {\n const previous = find(command.objectId);\n invariant(previous, `unknown object: ${command.objectId}`);\n const delta = { x: command.origin.x - previous.origin.x, y: command.origin.y - previous.origin.y };\n for (const record of Object.values(content)) {\n if (handler.identify(record)?.object === command.objectId) {\n handler.translate(record, delta);\n }\n }\n upserted.add(command.objectId);\n break;\n }\n }\n }\n\n return { upserted: [...upserted], removed };\n};\n\n/** Seed a fractional-index counter past any existing `a<n>` indexes. */\nexport const nextIndex = (content: ContentMap, isCounted: (record: any) => boolean = () => true): number => {\n let max = 0;\n let count = 0;\n for (const record of Object.values(content)) {\n if (!record || !isCounted(record)) {\n continue;\n }\n count++;\n const match = /^a(\\d+)$/.exec(record.index ?? '');\n if (match) {\n max = Math.max(max, Number(match[1]));\n }\n }\n return Math.max(max, count);\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Extension point for higher-level diagram languages (mermaid, d2, sequence, uml-class, …).\n// A dialect compiles its input into scene edit commands — owning any layout it needs — so its\n// output lands as ordinary world objects and stays editable by id. Mirrors the architecture\n// shared by Mermaid/D2/Kroki: dialect → intermediate positioned model → renderer.\n//\n\nimport * as Effect from 'effect/Effect';\nimport * as Schema from 'effect/Schema';\n\nimport { invariant } from '@dxos/invariant';\n\nimport * as Scene from './scene.ts';\n\nexport type Dialect<Input = any> = {\n id: string;\n description: string;\n input: Schema.Codec<Input, any>;\n compile: (input: Input) => Effect.Effect<readonly Scene.Command[]>;\n};\n\n/** The core dialect: input is already scene edit commands (identity compile). */\nexport const sceneDialect: Dialect<readonly Scene.Command[]> = {\n id: 'scene',\n description: 'Positioned world objects and elements; the agent does the layout.',\n input: Schema.Array(Scene.Command),\n compile: Effect.succeed,\n};\n\nexport class DialectRegistry {\n readonly #dialects = new Map<string, Dialect>();\n\n constructor(dialects: Dialect[] = [sceneDialect]) {\n dialects.forEach((dialect) => this.register(dialect));\n }\n\n register(dialect: Dialect): void {\n invariant(!this.#dialects.has(dialect.id), `duplicate dialect: ${dialect.id}`);\n this.#dialects.set(dialect.id, dialect);\n }\n\n get(id: string): Dialect | undefined {\n return this.#dialects.get(id);\n }\n\n list(): Dialect[] {\n return [...this.#dialects.values()];\n }\n}\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Aesthetic rules: whether a diagram reads well as drawn, which the layout objective's counts\n// (crossings, bends, length) do not capture — arrows against the flow, labels on top of boxes, edges\n// merged into one trunk, an entry point in the far corner of its group. Judged from `Content.layout`,\n// the text rendering of the page, by the same batched decision call as `Architecture`.\n//\n\nimport type * as DecisionModel from 'effect/ai/DecisionModel';\nimport * as Effect from 'effect/Effect';\n\nimport * as Architecture from './architecture.ts';\nimport type * as Score from './score.ts';\n\nconst HOW_TO_READ =\n 'The input is a diagram as drawn: `layout` renders the page as text, a character drawing followed by a ' +\n 'row-by-row reading of the boxes and of which way each arrow runs. Judge how the drawing reads to a person ' +\n 'looking at it, not whether the architecture it shows is good.';\n\nconst HOW_TO_SEE =\n 'The input is a diagram as drawn: the attached image is the page. Judge how the drawing reads to a person ' +\n 'looking at it, not whether the architecture it shows is good.';\n\nconst rule = (\n id: string,\n key: string,\n description: string,\n question: string,\n criteria: Architecture.Rule['criteria'],\n): Architecture.Rule => ({ id, key, description, instructions: `${HOW_TO_READ} ${question}`, criteria });\n\nexport const RULES: readonly Architecture.Rule[] = [\n rule(\n 'arrows-follow-flow',\n 'arrowsFollowFlow',\n 'Arrows run with the main direction of the diagram, inside groups as well as between them.',\n 'Do the arrows run with the main direction of the diagram (down in a top-to-bottom drawing, right in a ' +\n 'left-to-right one), inside groups as well as between them, with at most a few pointing back against it? ' +\n 'Arrows with a hollow triangle head (inheritance, implementation) point to the abstraction above by ' +\n 'convention and do not count against the flow.',\n {\n true: 'Nearly every arrow runs with the flow; a reader follows dependencies in one direction.',\n false: 'Many arrows, or whole chains inside a group, run up or back against the flow.',\n },\n ),\n rule(\n 'readable-labels',\n 'readableLabels',\n 'Every box and arrow label can be read on its own.',\n 'Can every box label and arrow label be read on its own, without running into another label, a line or a box?',\n {\n true: 'Every label sits clear of other text and lines.',\n false: 'Some label overlaps another label, a box or a line, or is cut off.',\n },\n ),\n rule(\n 'traceable-arrows',\n 'traceableArrows',\n 'Each arrow can be followed from its start to its end.',\n 'Can a reader follow each arrow from its start to its end without ambiguity — no two arrows sharing a line ' +\n 'segment or merged into one trunk, no arrow running through a group it does not connect to, no long detours ' +\n 'around the page, and few crossings?',\n {\n true: 'Each arrow has its own short, direct route.',\n false: 'Arrows share trunks, detour far, or cross so that their ends are hard to pair up.',\n },\n ),\n rule(\n 'entries-face-callers',\n 'entriesFaceCallers',\n 'Boxes that outside arrows reach sit on the side of their group facing the callers.',\n 'Within each group, do the boxes that arrows from outside the group reach sit on the side of the group ' +\n 'facing those callers, so that cross-group arrows are short and do not run through or around the group?',\n {\n true: 'Cross-group arrows land on the near side of each group.',\n false: 'An arrow from outside travels through or around a group to reach a box on its far side.',\n },\n ),\n rule(\n 'compact',\n 'compact',\n 'The drawing is packed tightly: no large empty regions, groups sized to their content.',\n 'Is the drawing compact — no large empty regions between or inside groups, groups no bigger than what they ' +\n 'hold, and boxes that are connected placed next to each other?',\n {\n true: 'The page is tightly packed; connected boxes are neighbours.',\n false: 'There are large empty regions, stretched groups, or connected boxes far apart.',\n },\n ),\n rule(\n 'groups-aligned',\n 'groupsAligned',\n 'Groups line up with each other rather than floating at arbitrary offsets.',\n 'Do the groups line up with one another — sharing a top edge or a left edge where they sit side by side or ' +\n 'stacked — rather than one group floating at an arbitrary height or offset beside another?',\n {\n true: 'Groups share edges and read as one arrangement.',\n false: 'A group sits at an arbitrary offset from its neighbours.',\n },\n ),\n rule(\n 'names-only',\n 'namesOnly',\n 'Each box is labelled with a component name alone, without comments or qualifiers.',\n 'Is every box labelled with just the name of what it is, with no comments, limits or qualifiers mixed into the ' +\n 'name (such as \"no cap\", \"≤10\" or a colon followed by a description)?',\n {\n true: 'Box labels are plain names; any commentary sits on arrows or not at all.',\n false: 'Some box label mixes a name with a comment, a limit or a description.',\n },\n ),\n rule(\n 'aligned-grid',\n 'alignedGrid',\n 'Boxes line up in rows and columns with consistent spacing.',\n 'Are the boxes aligned into clear rows and columns with consistent spacing, so the structure reads as a grid?',\n {\n true: 'Boxes share rows and columns with even gaps.',\n false: 'Boxes are staggered or unevenly spaced, with no clear rows or columns.',\n },\n ),\n];\n\n/** {@link RULES} for a judge shown the page as an image (`Architecture.Subject.images`) instead of `layout`. */\nexport const IMAGE_RULES: readonly Architecture.Rule[] = RULES.map((rule) => ({\n ...rule,\n instructions: `${HOW_TO_SEE}${rule.instructions.slice(HOW_TO_READ.length)}`,\n}));\n\n/**\n * Every aesthetic rule as a score from one `DecisionModel` call. Without `layout` or an image of the\n * page there is nothing to judge, so each rule reports an error rather than a guess.\n */\nexport const judge = (\n rules: readonly Architecture.Rule[] = RULES,\n): Score.Batch<Architecture.Subject, DecisionModel.DecisionModel> => {\n const inner = Architecture.judge(rules, 'aesthetics');\n return {\n entries: inner.entries,\n evaluate: (subject) =>\n subject.content.layout || subject.images?.length\n ? inner.evaluate(subject)\n : Effect.succeed(rules.map(() => ({ score: 0, error: 'No layout to judge.' }))),\n };\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Canonical text for a scene. The form is fixed — two-space indent, one element per line, a blank\n// line between statements, attributes in the order `vocabulary.ts` lists them — because\n// `parse(print(x))` round-tripping is only worth anything if the text side is normalized too.\n//\n\nimport type * as Scene from '../scene.ts';\nimport { BARE_ID, BARE_REF, ELEMENT_ATTRS, OBJECT_ATTRS, RESERVED } from './vocabulary.ts';\n\nconst ESCAPES: Record<string, string> = { '\\\\': '\\\\\\\\', '\"': '\\\\\"', '\\n': '\\\\n', '\\t': '\\\\t', '\\r': '\\\\r' };\n\n/**\n * Shortest form that reads back: integers keep no trailing zeros, negatives keep their sign, and\n * the exponent notation `String` switches to outside ~1e-7..1e21 is spelled as-is, which the\n * grammar accepts. `NaN` and `Infinity` have no readable form at all, so they are refused here\n * rather than silently producing a document that cannot be parsed.\n */\nexport const formatNumber = (value: number): string => {\n if (!Number.isFinite(value)) {\n throw new TypeError(`A scene coordinate must be finite; got ${value}.`);\n }\n return String(value);\n};\n\nexport const formatString = (value: string): string =>\n `\"${value.replace(/[\\\\\"\\n\\t\\r]/g, (character) => ESCAPES[character] ?? character)}\"`;\n\n/** Bare where the grammar allows it, quoted where a word would be read as a keyword or fail to lex. */\nexport const formatId = (id: string): string => (BARE_ID.test(id) && !RESERVED.has(id) ? id : formatString(id));\n\nconst formatPoint = ({ x, y }: Scene.Point): string => `${formatNumber(x)},${formatNumber(y)}`;\n\nconst formatSize = (w: number, h: number): string => `${formatNumber(w)}x${formatNumber(h)}`;\n\n/**\n * Quoted unless every id in it is a bare word: a dialect may build a ref from a node id the\n * grammar cannot lex, such as mermaid's `1st` becoming `1st/box`, and an unquoted one would make\n * the printed scene fail to parse.\n */\nconst formatRef = (ref: string): string => (BARE_REF.test(ref) && !RESERVED.has(ref) ? ref : formatString(ref));\n\n/** `_` is the end the schema leaves unset; a bound end prints as its ref, a free one as a point. */\nconst formatEndpoint = (ref: string | undefined, point: Scene.Point | undefined): string =>\n ref !== undefined ? formatRef(ref) : point !== undefined ? formatPoint(point) : '_';\n\ntype AttrValue = string | number | boolean;\n\n/** Prints `name=value` for the attributes of `kind` that are set, in the table's order. */\nconst formatAttrs = (kind: keyof typeof ELEMENT_ATTRS, values: Partial<Record<string, AttrValue>>): string[] =>\n ELEMENT_ATTRS[kind].flatMap(({ name, type }) => {\n const value = values[name];\n if (value === undefined) {\n return [];\n }\n return [`${name}=${type === 'string' && typeof value === 'string' ? formatString(value) : String(value)}`];\n });\n\nconst style = ({ color, fill, stroke, weight }: Scene.Element): Partial<Record<string, AttrValue>> => ({\n color,\n fill,\n stroke,\n weight,\n});\n\nexport const formatElement = (element: Scene.Element): string => {\n switch (element.kind) {\n case 'rect':\n case 'ellipse':\n case 'diamond':\n case 'triangle':\n return [\n element.kind,\n formatId(element.id),\n formatPoint(element),\n formatSize(element.w, element.h),\n ...(element.text === undefined ? [] : [formatString(element.text)]),\n ...formatAttrs(element.kind, { rotation: element.rotation, corners: element.corners, ...style(element) }),\n ].join(' ');\n\n case 'circle':\n return [\n 'circle',\n formatId(element.id),\n formatPoint({ x: element.cx, y: element.cy }),\n formatNumber(element.r),\n ...(element.text === undefined ? [] : [formatString(element.text)]),\n ...formatAttrs('circle', style(element)),\n ].join(' ');\n\n case 'line':\n return [\n 'line',\n formatId(element.id),\n ...element.points.map(formatPoint),\n ...formatAttrs('line', { closed: element.closed, ...style(element) }),\n ].join(' ');\n\n case 'curve':\n return [\n 'curve',\n formatId(element.id),\n ...element.points.map(formatPoint),\n ...formatAttrs('curve', style(element)),\n ].join(' ');\n\n case 'arc':\n return [\n 'arc',\n formatId(element.id),\n formatPoint({ x: element.cx, y: element.cy }),\n formatNumber(element.r),\n `${formatNumber(element.startAngle)}..${formatNumber(element.endAngle)}`,\n ...formatAttrs('arc', style(element)),\n ].join(' ');\n\n case 'text':\n return [\n 'text',\n formatId(element.id),\n formatPoint(element),\n formatString(element.text),\n ...formatAttrs('text', { w: element.w, ...style(element) }),\n ].join(' ');\n\n case 'arrow':\n return [\n 'arrow',\n formatId(element.id),\n formatEndpoint(element.from, element.start),\n '->',\n formatEndpoint(element.to, element.end),\n ...(element.text === undefined ? [] : [formatString(element.text)]),\n ...formatAttrs('arrow', {\n head: element.head,\n tail: element.tail,\n relation: element.relation,\n ...style(element),\n }),\n ].join(' ');\n\n case 'portal':\n return [\n 'portal',\n formatId(element.id),\n formatPoint(element),\n formatSize(element.w, element.h),\n ...(element.text === undefined ? [] : [formatString(element.text)]),\n ...formatAttrs('portal', { ref: element.ref, ...style(element) }),\n ].join(' ');\n }\n};\n\nconst block = (header: string, elements: readonly Scene.Element[]): string =>\n [`${header} {`, ...elements.map((element) => ` ${formatElement(element)}`), '}'].join('\\n');\n\nexport const formatObject = (object: Scene.WorldObject): string =>\n block(\n [\n 'object',\n formatId(object.id),\n ...(object.origin === undefined ? [] : ['@', formatPoint(object.origin)]),\n ...OBJECT_ATTRS.flatMap(({ name, type }) => {\n const value = { scale: object.scale, index: object.index, ref: object.ref }[name];\n if (value === undefined) {\n return [];\n }\n return [`${name}=${type === 'string' && typeof value === 'string' ? formatString(value) : String(value)}`];\n }),\n ].join(' '),\n object.elements,\n );\n\nexport const formatCommand = (command: Scene.Command): string => {\n switch (command.op) {\n case 'upsert-object':\n return formatObject(command.object);\n case 'upsert-elements':\n return block(`elements ${formatId(command.objectId)}`, command.elements);\n case 'move-object':\n return `move ${formatId(command.objectId)} @ ${formatPoint(command.origin)}`;\n case 'remove-object':\n return `remove object ${formatId(command.objectId)}`;\n case 'remove-elements':\n return `remove elements ${formatId(command.objectId)} ${command.elementIds.map(formatId).join(' ')}`;\n }\n};\n\n/** A whole document: statements separated by a blank line, newline-terminated. */\nexport const printCommands = (commands: readonly Scene.Command[]): string =>\n commands.length === 0 ? '' : `${commands.map(formatCommand).join('\\n\\n')}\\n`;\n\n/** A scene document — every statement an `object`, which is what a drawing serializes to. */\nexport const print = (scene: Scene.Scene): string =>\n printCommands(scene.objects.map((object) => ({ op: 'upsert-object', object }) as const));\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Text in another diagram language, out as ours. Every source language already compiles to\n// `Scene.Command[]`, and the DSL already prints those, so a converter is the two halves joined —\n// which is why adding a dialect costs nothing here.\n//\n// The output is the POST-layout form, and there is no other option: the DSL has no unpositioned\n// node to emit. That is the point of converting — you run mermaid once to get a layout, then keep\n// the result as something you can hand-tune, diff and review. See `docs/DSL.md`.\n//\n\nimport * as Data from 'effect/Data';\nimport * as Effect from 'effect/Effect';\n\nimport * as MermaidEngine from '../mermaid-engine.ts';\nimport * as Mermaid from '../mermaid.ts';\nimport type * as Scene from '../scene.ts';\nimport * as Uml from '../uml.ts';\nimport { printCommands } from './print.ts';\n\n/** A source language that can be turned into DSL text. */\nexport type Source = {\n id: string;\n description: string;\n /** True when a source string looks like this language, for `convert` to pick without being told. */\n detect: (source: string) => boolean;\n compile: (source: string) => Effect.Effect<readonly Scene.Command[]>;\n};\n\n/** Mermaid `classDiagram`, laid out synchronously by the UML engine. */\nexport const umlSource: Source = {\n id: 'uml',\n description: 'Mermaid classDiagram.',\n detect: Uml.isClassDiagram,\n compile: (source) => Effect.sync(() => Uml.compile(source)),\n};\n\n/**\n * Mermaid `flowchart`, laid out by the ELK-backed engine. ELK is promise-based, so the platform\n * boundary sits here rather than leaking a Promise into the rest of the pipeline.\n */\nexport const mermaidSource: Source = {\n id: 'mermaid',\n description: 'Mermaid flowchart, including the `%% ref` and UML edge-token extensions.',\n detect: (source) => /^\\s*(flowchart|graph)\\s+/m.test(source),\n compile: (source) => Effect.promise(() => MermaidEngine.compile(source)),\n};\n\n/** Mermaid flowchart without the ELK pass — the simple layered placement in `mermaid.ts`. */\nexport const mermaidLayeredSource: Source = {\n id: 'mermaid-layered',\n description: \"Mermaid flowchart with the dialect's own layered placement rather than ELK.\",\n detect: () => false,\n compile: (source) => Effect.sync(() => Mermaid.compile(source)),\n};\n\nexport const SOURCES: readonly Source[] = [umlSource, mermaidSource, mermaidLayeredSource];\n\n/** The language a source string is written in, or undefined when nothing claims it. */\nexport const detect = (source: string): Source | undefined => SOURCES.find(({ detect }) => detect(source));\n\nconst known = () => SOURCES.map(({ id }) => id).join(', ');\n\n/** Tagged so the failure channel stays discriminated rather than collapsing into bare `Error`. */\nexport class UnknownSourceError extends Data.TaggedError('DiagramUnknownSource')<{ id: string }> {\n override get message(): string {\n return `Unknown source language \"${this.id}\"; known: ${known()}.`;\n }\n}\n\nexport class UndetectedSourceError extends Data.TaggedError('DiagramUndetectedSource')<{}> {\n override get message(): string {\n return `Could not tell what language this is; pass one of: ${known()}.`;\n }\n}\n\nexport type ConvertOptions = {\n /** Force a language instead of detecting one. */\n source?: string;\n};\n\n/** Compiles `text` through its dialect and prints the result as DSL text. */\nexport const convert = (\n text: string,\n { source }: ConvertOptions = {},\n): Effect.Effect<string, UnknownSourceError | UndetectedSourceError> =>\n Effect.gen(function* () {\n const language = source === undefined ? detect(text) : SOURCES.find(({ id }) => id === source);\n if (!language) {\n return yield* Effect.fail(\n source === undefined ? new UndetectedSourceError() : new UnknownSourceError({ id: source }),\n );\n }\n return printCommands(yield* language.compile(text));\n });\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as SemanticEngine from '../semantic-engine.ts';\nimport { type ParseResult, read, withLayout } from './parse.ts';\n\n/** Options for {@link compile}. */\nexport type CompileOptions = Pick<SemanticEngine.SolveOptions, 'emitCandidate'>;\n\n/**\n * Reads a document and lays out its semantic statements with the full search, which also tries the\n * mermaid engine's placements when nothing was hinted. Asynchronous only because that engine's ELK\n * is; a document of scene statements alone reads exactly as {@link parse} reads it.\n */\nexport const compile: (text: string, options?: CompileOptions) => Effect.Effect<ParseResult> = Effect.fn('Dsl.compile')(\n function* (text: string, options: CompileOptions = {}) {\n const reading = read(text);\n const { diagram } = reading;\n if (!diagram) {\n return withLayout(reading);\n }\n const solution = yield* Effect.promise(() => SemanticEngine.compile(diagram, options));\n return withLayout(reading, solution);\n },\n);\n","//\n// Copyright 2026 DXOS.org\n//\n\nexport {\n type ConvertOptions,\n type Source,\n SOURCES,\n UndetectedSourceError,\n UnknownSourceError,\n convert,\n detect,\n} from './convert.ts';\nexport { type CompileOptions, compile } from './compile.ts';\nexport {\n type ParseResult,\n type Problem,\n type Range,\n type Reading,\n parse,\n parseScene,\n read,\n toScene,\n withLayout,\n} from './parse.ts';\nexport { formatCommand, formatElement, formatId, formatObject, formatString, print, printCommands } from './print.ts';\nexport {\n type AttrSpec,\n type AttrType,\n CLAUSE_KEYWORDS,\n DIAGRAM_ATTRS,\n EDGE_ATTRS,\n ELEMENT_ATTRS,\n ELEMENT_KINDS,\n type ElementKind,\n GROUP_ATTRS,\n NODE_ATTRS,\n OBJECT_ATTRS,\n RELATION_WORDS,\n RESERVED,\n SEMANTIC_KEYWORDS,\n STATEMENT_KEYWORDS,\n} from './vocabulary.ts';\nexport { parser } from './gen/diagram.ts';\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// The `.dx.svg` container: an SVG that renders anywhere and carries the data it was drawn from, as\n// draw.io's editable SVG does. The payload (for the illustrator, a `.dx.json` with the drawing's ECHO\n// objects) is JSON text in a `<metadata id=\"dx-payload\">` element: unlike an attribute or a comment,\n// `<metadata>` survives browsers, GitHub and DOMPurify. Format-only and ECHO-agnostic; the illustrator\n// builds and reads the payload.\n//\n\n/** The container format; versions the slot and encoding, not the payload, which versions itself. */\nexport const FORMAT = 'org.dxos.dx-svg@1';\n\nconst NAMESPACE = 'https://dxos.org/ns/dx-svg';\n\nconst MEDIA_TYPE = 'application/vnd.dxos.dx+json';\n\nconst NOTICE =\n '<!-- Drawn in DXOS: the embedded data is the source; edits to the picture alone are not reflected in it. -->';\n\n/**\n * JSON with `<`, `>` and `&` as unicode escapes, so the text needs neither CDATA nor entity decoding\n * and `JSON.parse` restores it exactly. A top-level `objects` array goes one object per line, so a\n * changed drawing diffs by object.\n */\nconst encode = (payload: unknown): string => {\n const escape = (json: string) => json.replace(/</g, '\\\\u003c').replace(/>/g, '\\\\u003e').replace(/&/g, '\\\\u0026');\n if (\n payload &&\n typeof payload === 'object' &&\n !Array.isArray(payload) &&\n 'objects' in payload &&\n Array.isArray(payload.objects)\n ) {\n const { objects, ...rest } = payload;\n const head = JSON.stringify(rest);\n const body = objects.map((object: unknown) => escape(JSON.stringify(object))).join(',\\n');\n return `${escape(head.slice(0, -1))}${head.length > 2 ? ',' : ''}\"objects\":[\\n${body}\\n]}`;\n }\n return escape(JSON.stringify(payload));\n};\n\n/** Embeds a payload in a standalone SVG: a marker on the root and the payload as its first child. */\nexport const embed = (svg: string, payload: unknown): string => {\n const root = /<svg\\b[^>]*>/.exec(svg);\n if (!root) {\n throw new Error('Not an SVG document: no <svg> element.');\n }\n if (/\\bdx:payload=/.test(root[0])) {\n throw new Error('The SVG already carries a dx-svg payload.');\n }\n const open = root[0].replace(/<svg\\b/, `<svg xmlns:dx=\"${NAMESPACE}\" dx:payload=\"${FORMAT}\"`);\n const metadata = `<metadata id=\"dx-payload\" data-type=\"${MEDIA_TYPE}\" data-version=\"1\" data-encoding=\"json\">\\n${encode(payload)}\\n</metadata>`;\n return `${svg.slice(0, root.index)}${NOTICE}\\n${open}${metadata}${svg.slice(root.index + root[0].length)}`;\n};\n\n/** Whether an SVG carries a payload, without parsing it. */\nexport const isDxSvg = (svg: string): boolean => /<metadata\\b[^>]*\\bid=\"dx-payload\"/.test(svg);\n\n/**\n * The payload of a `.dx.svg`, or undefined for a plain SVG. Works on the text alone, so it runs in node,\n * workers and the browser. An encoding this version does not know is an error, not a missing payload.\n */\nexport const extract = (svg: string): unknown => {\n const match = /<metadata\\b([^>]*)\\bid=\"dx-payload\"([^>]*)>([\\s\\S]*?)<\\/metadata>/.exec(svg);\n if (!match) {\n return undefined;\n }\n const attributes = `${match[1]} ${match[2]}`;\n const encoding = /\\bdata-encoding=\"([^\"]*)\"/.exec(attributes)?.[1] ?? 'json';\n if (encoding !== 'json') {\n throw new Error(`Unsupported dx-svg payload encoding: ${encoding}.`);\n }\n return JSON.parse(match[3]);\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Normalized scoring: every heuristic — an objective's constraints and cost terms, or any other\n// judge of a layout — reports one score in [0, 1] (0 bad, 1 good), so heterogeneous scorers read\n// as one list and combine into one number. `Objective` stays the engines' selector; this is the\n// view of the same measurements a person (or a later judge) compares layouts by.\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport type * as Objective from './objective.ts';\n\n/** What produced a score; open so a host can add its own kinds of judge alongside the built-in ones. */\nexport type Kind = 'constraint' | 'cost' | (string & {});\n\nexport type Result = {\n /** In [0, 1]: 0 is bad, 1 is good. Meaningless when `error` is set. */\n score: number;\n /** Why, in a line or two: the violations, or the raw measure behind a cost. */\n detail?: string;\n /** The scorer could not judge (e.g. its model was unreachable); left out of {@link overall}. */\n error?: string;\n};\n\nexport type Entry = {\n id: string;\n kind: Kind;\n description: string;\n};\n\n/**\n * One judge of a subject — by default the layout. An effect, so a judge that asks something outside the\n * process can run late, be interrupted, and name what it needs in `R`.\n */\nexport type Scorer<S = Objective.Layout, R = never> = Entry & {\n evaluate: (subject: S) => Effect.Effect<Result, never, R>;\n};\n\n/** Several scores from one evaluation, in `entries` order: for a judge that answers many questions per call. */\nexport type Batch<S = Objective.Layout, R = never> = {\n entries: readonly Entry[];\n evaluate: (subject: S) => Effect.Effect<readonly Result[], never, R>;\n};\n\nexport type Source<S = Objective.Layout, R = never> = Scorer<S, R> | Batch<S, R>;\n\nexport type Scored = Result & Entry;\n\n/**\n * Weighted cost at which a cost term scores 0.5: one crossing's worth (see `Objective.crossings`), so\n * \"half marks\" means \"as bad as one crossing\" on every term.\n */\nexport const HALF_COST = 3;\n\n/** Maps a weighted cost in [0, ∞) onto (0, 1]: 1 at no cost, 0.5 at `half`, falling off hyperbolically. */\nexport const fromCost = (weighted: number, half: number = HALF_COST): number => 1 / (1 + Math.max(0, weighted) / half);\n\n/** A hard requirement: 1 when it holds, 0 when anything violates it. */\nexport const constraintScorer = (constraint: Objective.Constraint): Scorer => ({\n id: constraint.id,\n kind: 'constraint',\n description: constraint.description,\n evaluate: (layout) =>\n Effect.sync(() => {\n const violations = constraint.violations(layout);\n return { score: violations.length ? 0 : 1, ...(violations.length ? { detail: violations.join('\\n') } : {}) };\n }),\n});\n\n/** A soft preference: its weighted cost through {@link fromCost}. */\nexport const costScorer = (term: Objective.CostTerm, half: number = HALF_COST): Scorer => ({\n id: term.id,\n kind: 'cost',\n description: term.description,\n evaluate: (layout) =>\n Effect.sync(() => {\n const value = term.measure(layout);\n const weighted = value * term.weight;\n return { score: fromCost(weighted, half), detail: `${round(value)} × ${term.weight} = ${round(weighted)}` };\n }),\n});\n\n/** Every constraint and cost term of an objective, constraints first. */\nexport const fromObjective = (objective: Objective.Objective, half: number = HALF_COST): Scorer[] => [\n ...objective.constraints.map(constraintScorer),\n ...objective.costs.map((term) => costScorer(term, half)),\n];\n\nconst isBatch = <S, R>(source: Source<S, R>): source is Batch<S, R> => 'entries' in source;\n\n/** Runs every source against one subject concurrently; results keep the sources' order, batches flattened. */\nexport const evaluate = <S, R>(sources: readonly Source<S, R>[], subject: S): Effect.Effect<Scored[], never, R> =>\n Effect.all(\n sources.map((source) =>\n isBatch(source)\n ? source\n .evaluate(subject)\n .pipe(Effect.map((results) => source.entries.map((entry, index) => ({ ...entry, ...results[index] }))))\n : source\n .evaluate(subject)\n .pipe(\n Effect.map((result) => [\n { id: source.id, kind: source.kind, description: source.description, ...result },\n ]),\n ),\n ),\n { concurrency: 'unbounded' },\n ).pipe(Effect.map((groups) => groups.flat()));\n\n/**\n * One number for a set of scores: the worst constraint gates the mean of everything else, so a\n * layout that breaks a constraint scores 0 however good it otherwise is — the same precedence\n * `Objective.select` gives violations over cost — while every other kind contributes equally.\n * `undefined` when nothing could be judged, so a set of failed scorers never reads as a perfect score.\n */\nexport const overall = (all: readonly Pick<Scored, 'kind' | 'score' | 'error'>[]): number | undefined => {\n const scores = all.filter(({ error }) => error === undefined);\n if (scores.length === 0) {\n return undefined;\n }\n const gate = Math.min(1, ...scores.filter(({ kind }) => kind === 'constraint').map(({ score }) => score));\n const rest = scores.filter(({ kind }) => kind !== 'constraint');\n const mean = rest.length ? rest.reduce((total, { score }) => total + score, 0) / rest.length : 1;\n return gate * mean;\n};\n\nconst round = (value: number) => (Number.isInteger(value) ? `${value}` : value.toFixed(2));\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// SVG variant content handler: the scene DSL is the persistence format. Each element is stored\n// verbatim as one record carrying its DSL identity and its object's placement, so\n// `applyCommands` provides upsert/remove/move and `read` reconstructs the scene losslessly —\n// there is no renderer-native encoding to compile to. The plugin binds it to ECHO as `SvgBuilder`.\n//\n\nimport { type ContentHandler, type ContentMap, type ReadWorldObject } from './content.ts';\nimport type * as Scene from './scene.ts';\n\n/** Discriminates the base `Drawing.Canvas` as SVG-rendered scene content. */\nexport const SVG_SCHEMA = 'dxos.org/svg/1';\n\ntype SvgRecord = {\n object: string;\n element: string;\n /** Insertion order, so `read` reproduces element paint order. */\n order: number;\n placement: { origin: Scene.Point; scale: number };\n /** The object's `ref`, repeated on each of its records so `read` restores it. */\n ref?: string;\n /** The object's fractional z-order `index`, repeated like `ref`. */\n index?: string;\n data: Scene.Element;\n};\n\nconst isSvgRecord = (record: any): record is SvgRecord =>\n typeof record?.object === 'string' && typeof record?.element === 'string' && record?.data !== undefined;\n\n/** Objects without an index paint first, in insertion order; indexed objects follow in index order. */\nconst byIndex = (left: ReadWorldObject, right: ReadWorldObject): number =>\n left.index === undefined\n ? right.index === undefined\n ? 0\n : -1\n : right.index === undefined\n ? 1\n : left.index < right.index\n ? -1\n : left.index > right.index\n ? 1\n : 0;\n\nexport const SvgHandler: ContentHandler = {\n identify: (record) => (isSvgRecord(record) ? { object: record.object, element: record.element } : undefined),\n\n render: (object, placement, content) => {\n // Past the max, not the count: deletions leave gaps, and a reused order makes paint order\n // ambiguous on read.\n let order =\n Math.max(\n -1,\n ...Object.values(content)\n .filter(isSvgRecord)\n .map((record) => record.order),\n ) + 1;\n // `upsert-elements` supplies only elements; the object's ref and index then come from its\n // existing records.\n const existing = Object.values(content).find((record) => isSvgRecord(record) && record.object === object.id);\n const ref = ('ref' in object && object.ref) || existing?.ref;\n const index = ('index' in object && object.index) || existing?.index;\n const records: ContentMap = {};\n for (const element of object.elements) {\n records[`${object.id}/${element.id}`] = {\n object: object.id,\n element: element.id,\n order: order++,\n placement: { origin: { ...placement.origin }, scale: placement.scale },\n ...(ref ? { ref } : {}),\n ...(index ? { index } : {}),\n // Structured clone: scene elements are plain data, and the record must not alias the input.\n data: JSON.parse(JSON.stringify(element)),\n } satisfies SvgRecord;\n }\n return records;\n },\n\n read: (content) => {\n const records = Object.values(content)\n .filter(isSvgRecord)\n .sort((left, right) => left.order - right.order);\n const objects = new Map<string, ReadWorldObject>();\n let unmanaged = 0;\n for (const record of Object.values(content)) {\n if (!isSvgRecord(record)) {\n unmanaged++;\n }\n }\n for (const record of records) {\n let object = objects.get(record.object);\n if (!object) {\n object = {\n id: record.object,\n origin: { ...record.placement.origin },\n scale: record.placement.scale,\n ...(record.ref ? { ref: record.ref } : {}),\n ...(record.index ? { index: record.index } : {}),\n elements: [],\n };\n objects.set(record.object, object);\n }\n (object.elements as Scene.Element[]).push(record.data);\n }\n return { scene: { objects: [...objects.values()].sort(byIndex) }, unmanaged };\n },\n\n translate: (record, delta) => {\n if (isSvgRecord(record)) {\n record.placement.origin = {\n x: record.placement.origin.x + delta.x,\n y: record.placement.origin.y + delta.y,\n };\n }\n },\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// MOSAIC (Model-Oriented System for Adaptive Interface Composition) UI-schematic dialect:\n// renders low-fidelity UI wireframes from the declarative app model. Phase 1 scope: a single\n// schema compiles to a form drawing — the recursive structure (nested objects, arrays) with each\n// control (input, switch, checkbox, select) as a rectangle and its label as text above — wrapped\n// in the app-ontology containers (deck > plank > panel > form). Two renderers share the model:\n// ASCII (tests, chat) and scene commands (tldraw, via the standard dialect contract). Unrelated\n// to `react-ui-mosaic`. See `dialect.ts` for the extension mechanism this follows (mermaid is\n// the sibling precedent).\n//\n\nimport type * as Schema from 'effect/Schema';\nimport * as SchemaAST from 'effect/SchemaAST';\n\nimport type * as Scene from './scene.ts';\n\n//\n// Drawing model. Plain data (one discriminated tree) — the intermediate model between the app\n// model (schema today; app-graph later) and the renderers.\n//\n\nexport type ControlKind = 'input' | 'switch' | 'checkbox' | 'select';\n\nexport type Control = {\n kind: 'control';\n control: ControlKind;\n label: string;\n /** Dotted schema path; doubles as the element id so drawn controls stay addressable. */\n path: string;\n};\n\n/** Nested object: a labeled group of fields. */\nexport type Group = {\n kind: 'group';\n label: string;\n path: string;\n children: FormChild[];\n};\n\n/** Array: a labeled repetition of one item template. */\nexport type ArrayGroup = {\n kind: 'array';\n label: string;\n path: string;\n /** The element template, rendered once with a trailing \"+\" affordance. */\n item: FormChild;\n};\n\nexport type FormChild = Control | Group | ArrayGroup;\n\n/** A form has no title of its own — the schema title belongs to the enclosing container. */\nexport type Form = { kind: 'form'; children: FormChild[] };\nexport type Panel = { kind: 'panel'; label?: string; child: Form };\nexport type Plank = { kind: 'plank'; label?: string; child: Panel };\nexport type Deck = { kind: 'deck'; planks: Plank[] };\n\nexport type UiNode = Deck | Plank | Panel | Form | FormChild;\n\n//\n// Schema → drawing. Minimal v4 AST walking, self-contained (see @dxos/effect SchemaEx for the\n// full-featured helpers): properties live on `Objects` nodes, `Schema.optional` is a\n// `T | undefined` union, arrays are `Arrays` with a single rest element.\n//\n\nexport type FromSchemaOptions = {\n /** Recursion guard for self-referential schemas. */\n maxDepth?: number;\n};\n\nconst unwrapSuspend = (ast: SchemaAST.AST): SchemaAST.AST =>\n SchemaAST.isSuspend(ast) ? unwrapSuspend(ast.thunk()) : ast;\n\nconst unwrapOptional = (ast: SchemaAST.AST): SchemaAST.AST => {\n let node = ast;\n while (SchemaAST.isUnion(node) && node.types.length === 2 && SchemaAST.isUndefined(node.types[1])) {\n node = node.types[0];\n }\n return node;\n};\n\nconst propertiesOf = (ast: SchemaAST.AST): ReadonlyArray<SchemaAST.PropertySignature> => {\n const node = unwrapSuspend(ast);\n return node._tag === 'Objects' ? node.propertySignatures : [];\n};\n\nconst isLiteralUnion = (node: SchemaAST.AST): boolean =>\n SchemaAST.isUnion(node) && node.types.length > 0 && node.types.every(SchemaAST.isLiteral);\n\nconst arrayElementOf = (node: SchemaAST.AST): SchemaAST.AST | undefined =>\n SchemaAST.isArrays(node) && node.elements.length === 0 && node.rest.length === 1 ? node.rest[0] : undefined;\n\nconst titleOf = (ast: SchemaAST.AST): string | undefined => {\n const title = (ast.annotations?.title ?? SchemaAST.resolve(ast)?.title) as string | undefined;\n return typeof title === 'string' ? title : undefined;\n};\n\nconst label = (name: PropertyKey, type: SchemaAST.AST): string => titleOf(type) ?? String(name);\n\nconst controlOf = (type: SchemaAST.AST, name: PropertyKey, path: string): Control => {\n const control: ControlKind = isLiteralUnion(type) ? 'select' : type._tag === 'Boolean' ? 'checkbox' : 'input';\n return { kind: 'control', control, label: label(name, type), path };\n};\n\nconst childOf = (type: SchemaAST.AST, name: PropertyKey, path: string, depth: number): FormChild => {\n const base = unwrapOptional(unwrapSuspend(type));\n\n const element = arrayElementOf(base);\n if (element && depth > 0) {\n // The array frame already names the collection; an item template carries no label of its own.\n const item = { ...childOf(element, '', `${path}[]`, depth - 1), label: '' };\n return { kind: 'array', label: label(name, base), path, item };\n }\n\n // Nested struct: recurse. Declarations (refs, opaque types) fall through to a plain control —\n // walking into them risks unbounded recursion and they render as pickers anyway.\n if (depth > 0 && !isLiteralUnion(base)) {\n const properties = propertiesOf(base);\n if (properties.length > 0) {\n return {\n kind: 'group',\n label: label(name, base),\n path,\n children: properties.map((property) =>\n childOf(property.type, property.name, `${path}.${String(property.name)}`, depth - 1),\n ),\n };\n }\n }\n\n return controlOf(base, name, path);\n};\n\n/** Convert a schema into a form drawing: the phase-1 slice of the app model. */\nexport const fromSchema = (schema: Schema.Top, options: FromSchemaOptions = {}): Form => {\n const { maxDepth = 4 } = options;\n const children = propertiesOf(schema.ast)\n .filter((property) => property.name !== 'id')\n .map((property) => childOf(property.type, property.name, String(property.name), maxDepth));\n return { kind: 'form', children };\n};\n\n/** The schema's title annotation — container chrome, not form content. */\nexport const schemaTitle = (schema: Schema.Top): string | undefined => titleOf(schema.ast);\n\n/** Wrap a form in the app-ontology containers for a full schematic. */\nexport const deckOf = (form: Form, title?: string): Deck => ({\n kind: 'deck',\n planks: [{ kind: 'plank', label: title, child: { kind: 'panel', child: form } }],\n});\n\n//\n// Scene layout. Vertical flow; containers pad and frame their content. Units are scene units\n// (the caller scales), mirroring the mermaid dialect.\n//\n\nconst CONTROL_W = 200;\nconst CONTROL_H = 28;\nconst TOGGLE_W = 28;\nconst LABEL_H = 18;\nconst GAP = 12;\nconst PAD = 16;\nconst TITLE_H = 22;\nconst PLUS_H = 20;\n\ntype Emit = { commands: Scene.Command[]; elements: Scene.Element[] };\n\nconst controlHeight = (node: Control) => (node.label ? LABEL_H : 0) + CONTROL_H;\n\nconst heightOf = (node: UiNode): number => {\n switch (node.kind) {\n case 'control':\n return controlHeight(node);\n case 'group':\n // An anonymous group (an array's item template) flows its children without chrome.\n if (!node.label) {\n return node.children.reduce((sum, child, index) => sum + heightOf(child) + (index > 0 ? GAP : 0), 0);\n }\n return TITLE_H + node.children.reduce((sum, child) => sum + heightOf(child) + GAP, 0) + PAD;\n case 'array':\n return TITLE_H + heightOf(node.item) + PAD;\n case 'form':\n return node.children.reduce((sum, child, index) => sum + heightOf(child) + (index > 0 ? GAP : 0), 0);\n case 'panel':\n return heightOf(node.child) + PAD * 2 + TITLE_H;\n case 'plank':\n return heightOf(node.child) + PAD * 2 + (node.label ? TITLE_H : 0);\n case 'deck':\n return Math.max(...node.planks.map(heightOf), 0) + PAD * 2;\n }\n};\n\nconst widthOf = (node: UiNode): number => {\n switch (node.kind) {\n case 'control':\n return CONTROL_W;\n case 'group':\n return Math.max(...node.children.map(widthOf), CONTROL_W) + (node.label ? PAD : 0);\n case 'array':\n return Math.max(widthOf(node.item), CONTROL_W) + PAD;\n case 'form':\n return Math.max(...node.children.map(widthOf), CONTROL_W);\n case 'panel':\n return widthOf(node.child) + PAD * 2;\n case 'plank':\n return widthOf(node.child) + PAD * 2;\n case 'deck':\n return node.planks.reduce((sum, plank, index) => sum + widthOf(plank) + (index > 0 ? GAP : 0), 0) + PAD * 2;\n }\n};\n\n/** Qualify a node id with its container, so two planks over the same schema stay addressable. */\nconst qualify = (prefix: string, path: string): string => (prefix ? `${prefix}.${path}` : path);\n\n/** One world object per control (id = container path), so drawn controls stay individually addressable. */\nconst emitControl = (node: Control, x: number, y: number, emit: Emit, prefix: string): void => {\n const top = node.label ? LABEL_H : 0;\n const elements: Scene.Element[] = node.label\n ? [{ kind: 'text', id: 'label', x: 0, y: 0, text: node.label, weight: 's', color: 'grey' }]\n : [];\n switch (node.control) {\n case 'checkbox':\n case 'switch':\n elements.push({ kind: 'rect', id: 'box', x: 0, y: top, w: TOGGLE_W, h: CONTROL_H, stroke: 'solid' });\n break;\n case 'select':\n elements.push(\n { kind: 'rect', id: 'box', x: 0, y: top, w: CONTROL_W, h: CONTROL_H, stroke: 'solid' },\n { kind: 'text', id: 'caret', x: CONTROL_W - 20, y: top + 4, text: '*', weight: 's', color: 'grey' },\n );\n break;\n case 'input':\n elements.push({ kind: 'rect', id: 'box', x: 0, y: top, w: CONTROL_W, h: CONTROL_H, stroke: 'solid' });\n break;\n }\n emit.commands.push({ op: 'upsert-object', object: { id: qualify(prefix, node.path), origin: { x, y }, elements } });\n};\n\nconst frame = (id: string, x: number, y: number, w: number, h: number, title: string | undefined, emit: Emit): void => {\n const elements: Scene.Element[] = [{ kind: 'rect', id: 'frame', x: 0, y: 0, w, h, stroke: 'dashed', color: 'grey' }];\n if (title) {\n elements.push({ kind: 'text', id: 'title', x: PAD / 2, y: 2, text: title, weight: 's' });\n }\n emit.commands.push({ op: 'upsert-object', object: { id, origin: { x, y }, elements } });\n};\n\nconst emitNode = (node: UiNode, x: number, y: number, emit: Emit, prefix = ''): void => {\n switch (node.kind) {\n case 'control':\n emitControl(node, x, y, emit, prefix);\n break;\n\n case 'group': {\n const anonymous = !node.label;\n if (!anonymous) {\n frame(qualify(prefix, node.path), x, y, widthOf(node), heightOf(node), node.label, emit);\n }\n let cursor = y + (anonymous ? 0 : TITLE_H);\n for (const child of node.children) {\n emitNode(child, x + (anonymous ? 0 : PAD), cursor, emit, prefix);\n cursor += heightOf(child) + GAP;\n }\n break;\n }\n\n case 'array': {\n const width = widthOf(node);\n const id = qualify(prefix, node.path);\n frame(id, x, y, width, heightOf(node), node.label, emit);\n // The add button sits on the header line, where the array marker reads in ASCII.\n emit.commands.push({\n op: 'upsert-object',\n object: {\n id: `${id}.add`,\n origin: { x: x + width - TOGGLE_W - 4, y: y + 2 },\n elements: [{ kind: 'rect', id: 'box', x: 0, y: 0, w: TOGGLE_W, h: PLUS_H, text: '+', stroke: 'solid' }],\n },\n });\n emitNode(node.item, x + PAD, y + TITLE_H, emit, prefix);\n break;\n }\n\n case 'form': {\n let cursor = y;\n for (const child of node.children) {\n emitNode(child, x, cursor, emit, prefix);\n cursor += heightOf(child) + GAP;\n }\n break;\n }\n\n case 'panel': {\n const id = qualify(prefix, 'panel');\n frame(id, x, y, widthOf(node), heightOf(node), node.label ?? 'panel', emit);\n emitNode(node.child, x + PAD, y + TITLE_H + PAD, emit, id);\n break;\n }\n\n case 'plank': {\n const id = prefix || 'plank';\n frame(id, x, y, widthOf(node), heightOf(node), node.label, emit);\n emitNode(node.child, x + PAD, y + PAD + (node.label ? TITLE_H : 0), emit, id);\n break;\n }\n\n case 'deck': {\n const id = qualify(prefix, 'deck');\n frame(id, x, y, widthOf(node), heightOf(node), undefined, emit);\n let cursor = x + PAD;\n // Index, not label: an unlabeled plank must still get a distinct id.\n node.planks.forEach((plank, index) => {\n emitNode(plank, cursor, y + PAD, emit, `${id}.plank${index}`);\n cursor += widthOf(plank) + GAP;\n });\n break;\n }\n }\n};\n\nexport type CompileOptions = {\n /** Canvas position of the schematic's top-left, in canvas px. */\n origin?: Scene.Point;\n /** Canvas px per scene unit. */\n scale?: number;\n};\n\n/** Compile a UI drawing into scene commands (frames first, controls above them). */\nexport const compile = (node: UiNode, options: CompileOptions = {}): Scene.Command[] => {\n const { origin = { x: 0, y: 0 }, scale = 1 } = options;\n const emit: Emit = { commands: [], elements: [] };\n emitNode(node, 0, 0, emit);\n return emit.commands.map((command) =>\n command.op === 'upsert-object'\n ? {\n ...command,\n object: {\n ...command.object,\n scale,\n origin: {\n x: origin.x + (command.object.origin?.x ?? 0) * scale,\n y: origin.y + (command.object.origin?.y ?? 0) * scale,\n },\n },\n }\n : command,\n );\n};\n\n//\n// ASCII renderer — the interim/low-cost target over the same model.\n//\n\nconst GLYPHS: Record<ControlKind, string> = {\n input: '[__________]',\n select: '[_________*]',\n checkbox: '[ ]',\n switch: '(o )',\n};\n\nconst indent = (lines: string[], prefix: string): string[] => lines.map((line) => (prefix + line).trimEnd());\n\n/** Wrap lines in a +--- box, optionally titled. */\nconst boxed = (lines: string[], title?: string): string[] => {\n const width = Math.max(...lines.map((line) => line.length), (title?.length ?? 0) + 4, 12);\n const top = title\n ? `+- ${title} ${'-'.repeat(Math.max(width - title.length - 1, 1))}+`\n : `+${'-'.repeat(width + 2)}+`;\n return [top, ...lines.map((line) => `| ${line.padEnd(width)} |`), `+${'-'.repeat(width + 2)}+`];\n};\n\nconst asciiLines = (node: UiNode): string[] => {\n switch (node.kind) {\n case 'control':\n return node.label ? [node.label, GLYPHS[node.control]] : [GLYPHS[node.control]];\n case 'group': {\n const children = node.children.flatMap((child, index) =>\n index > 0 ? ['', ...asciiLines(child)] : asciiLines(child),\n );\n return node.label ? [node.label, ...indent(children, ' ')] : children;\n }\n case 'array':\n return [`${node.label} [+]`, ...indent(asciiLines(node.item), ' ')];\n case 'form':\n return node.children.flatMap((child, index) => (index > 0 ? ['', ...asciiLines(child)] : asciiLines(child)));\n case 'panel':\n return boxed(asciiLines(node.child), node.label);\n case 'plank':\n return boxed(asciiLines(node.child), node.label);\n case 'deck':\n return node.planks.flatMap((plank, index) => (index > 0 ? ['', ...asciiLines(plank)] : asciiLines(plank)));\n }\n};\n\n/** Render a UI drawing as ASCII art. */\nexport const renderAscii = (node: UiNode): string => asciiLines(node).join('\\n');\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Engine-backed placement for the grid UML dialect: dagre or ELK replace the hand-rolled\n// lane/column pass (proper crossing minimization and straightness-seeking coordinate\n// assignment), while parsing, cell measurement, grid snapping, routing, and emission stay\n// shared with `uml-grid.ts`. See `docs/DESIGN.md`.\n//\n\nimport { layout as dagreLayout, graphlib } from '@dagrejs/dagre';\nimport ELK from 'elkjs/lib/elk.bundled.js';\n\nimport type * as Scene from './scene.ts';\nimport {\n type Cell,\n GRID,\n type CompileOptions as GridCompileOptions,\n type Rect,\n emit,\n measureCell,\n} from './uml-grid.ts';\nimport { type Direction, type UmlModel, parse, relationRanks } from './uml.ts';\n\nexport type Engine = 'dagre' | 'elk';\n\nexport type CompileOptions = Omit<GridCompileOptions, 'route'> & {\n /** Placement engine (default 'elk'). */\n engine?: Engine;\n};\n\nconst GAP_MAIN = GRID * 4;\nconst GAP_CROSS = GRID * 4;\n\nconst snap = (value: number) => Math.round(value / GRID) * GRID;\n\ntype PlaceOptions = {\n cell: Cell;\n gapMain: number;\n gapCross: number;\n direction: Direction;\n};\n\nconst DAGRE_DIRECTION: Record<Direction, string> = { TB: 'TB', BT: 'BT', LR: 'LR', RL: 'RL' };\nconst ELK_DIRECTION: Record<Direction, string> = { TB: 'DOWN', BT: 'UP', LR: 'RIGHT', RL: 'LEFT' };\n\n/**\n * Edges oriented for layering: inheritance, realization, and dependency point at abstractions,\n * which rank ABOVE their sources — so those edges are reversed for the engine (which lays out\n * source-above-target), matching `relationRanks`.\n */\nconst orientedEdges = (model: UmlModel): { from: string; to: string }[] =>\n model.relations.map((relation) =>\n relation.kind === 'inheritance' || relation.kind === 'realization' || relation.kind === 'dependency'\n ? { from: relation.to, to: relation.from }\n : { from: relation.from, to: relation.to },\n );\n\n/** Snap engine output to the document grid and normalize the top-left to (0, 0). */\nconst snapRects = (rects: Map<string, Rect>): Map<string, Rect> => {\n const snapped = new Map([...rects].map(([id, rect]) => [id, { ...rect, x: snap(rect.x), y: snap(rect.y) }]));\n const minX = Math.min(...[...snapped.values()].map((rect) => rect.x), 0);\n const minY = Math.min(...[...snapped.values()].map((rect) => rect.y), 0);\n return new Map([...snapped].map(([id, rect]) => [id, { ...rect, x: rect.x - minX, y: rect.y - minY }]));\n};\n\n/** dagre: network-simplex layering + median-sweep crossing minimization. Sync. */\nconst dagrePlace = (model: UmlModel, { cell, gapMain, gapCross, direction }: PlaceOptions): Map<string, Rect> => {\n const graph = new graphlib.Graph();\n graph.setGraph({\n rankdir: DAGRE_DIRECTION[direction],\n ranker: 'network-simplex',\n ranksep: gapMain,\n nodesep: gapCross,\n edgesep: gapCross / 2,\n });\n graph.setDefaultEdgeLabel(() => ({}));\n for (const entry of model.classes) {\n graph.setNode(entry.id, { width: cell.w, height: cell.h });\n }\n for (const edge of orientedEdges(model)) {\n graph.setEdge(edge.from, edge.to);\n }\n dagreLayout(graph);\n\n // dagre reports node centers.\n const rects = new Map<string, Rect>(\n model.classes.map((entry) => {\n const node = graph.node(entry.id);\n return [entry.id, { x: node.x - cell.w / 2, y: node.y - cell.h / 2, w: cell.w, h: cell.h }];\n }),\n );\n return snapRects(rects);\n};\n\n/** ELK layered: layer-sweep crossing minimization + Brandes-Köpf placement. Async. */\nconst elkPlace = async (\n model: UmlModel,\n { cell, gapMain, gapCross, direction }: PlaceOptions,\n): Promise<Map<string, Rect>> => {\n const elk = new ELK();\n const result = await elk.layout({\n id: 'root',\n layoutOptions: {\n 'elk.algorithm': 'layered',\n 'elk.direction': ELK_DIRECTION[direction],\n 'elk.layered.spacing.nodeNodeBetweenLayers': String(gapMain),\n 'elk.spacing.nodeNode': String(gapCross),\n // Favors long straight chains over balanced centering — fewer jagged connectors.\n 'elk.layered.nodePlacement.strategy': 'BRANDES_KOEPF',\n // Keeps declaration order among otherwise-unconstrained siblings, so peers stay gathered.\n 'elk.layered.considerModelOrder.strategy': 'PREFER_NODES',\n },\n children: model.classes.map((entry) => ({ id: entry.id, width: cell.w, height: cell.h })),\n edges: orientedEdges(model).map((edge, index) => ({\n id: `edge-${index}`,\n sources: [edge.from],\n targets: [edge.to],\n })),\n });\n\n const rects = new Map<string, Rect>(\n (result.children ?? []).map((child) => [child.id, { x: child.x ?? 0, y: child.y ?? 0, w: cell.w, h: cell.h }]),\n );\n return snapRects(rects);\n};\n\n/**\n * Compile a mermaid class diagram with engine-backed placement; identical output structure to\n * `UmlGrid.compile` (equal-size grid cells, orthogonal Z-routed connectors), but node positions\n * come from dagre/ELK. Async because ELK is.\n */\nexport const compile = async (source: string, options: CompileOptions = {}): Promise<Scene.Command[]> => {\n const { origin, scale, maxWidth = GRID * 6, engine = 'elk' } = options;\n const model = parse(source);\n const cell = measureCell(model, { maxWidth, cell: options.cell, titleHeight: options.titleHeight });\n const place: PlaceOptions = {\n cell,\n gapMain: snap(options.gapMain ?? GAP_MAIN),\n gapCross: snap(options.gapCross ?? GAP_CROSS),\n direction: model.direction,\n };\n const rects = engine === 'dagre' ? dagrePlace(model, place) : await elkPlace(model, place);\n return emit({ model, cell, rects, ranks: relationRanks(model) }, { origin, scale });\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Rule-based pluggable layout: prioritized rules claim disjoint node GROUPS and lay each out in\n// group-local coordinates; groups then pack as super-nodes (ranked by their cross-group edges)\n// with non-overlapping borders, and the shared router connects nodes across them. Rules capture\n// domain shape the generic engines cannot: an inheritance tree reads as a tree, a call chain as\n// a column. See `docs/DESIGN.md`.\n//\n\nimport * as Layout from './layout.ts';\nimport type * as Scene from './scene.ts';\nimport {\n type Cell,\n GRID,\n type CompileOptions as GridCompileOptions,\n type Rect,\n emit,\n measureCell,\n} from './uml-grid.ts';\nimport { type UmlModel, parse, relationRanks } from './uml.ts';\n\nconst GAP = GRID * 2;\nconst GROUP_GAP = GRID * 3;\nconst FRAME_PAD = GRID;\n\nconst snap = (value: number) => Math.round(value / GRID) * GRID;\n\n/** A laid-out group: member rects in group-local coordinates plus the packed bounds. */\nexport type Group = {\n id: string;\n /** Rule that claimed the group (frame label; singletons carry none). */\n rule?: string;\n rects: Map<string, Rect>;\n w: number;\n h: number;\n};\n\n/**\n * A layout rule: claims disjoint groups from the still-unclaimed nodes and lays each out\n * internally. Rules run in priority order; unclaimed nodes fall through to singleton groups.\n */\nexport type GroupRule = {\n id: string;\n apply: (model: UmlModel, unclaimed: Set<string>, cell: Cell) => Group[];\n};\n\n/** Relations oriented so the target should sit ABOVE the source (arrows read upward). */\nconst upEdges = (model: UmlModel): { from: string; to: string }[] =>\n model.relations.map((relation) =>\n relation.kind === 'inheritance' || relation.kind === 'realization' || relation.kind === 'dependency'\n ? { from: relation.from, to: relation.to }\n : { from: relation.to, to: relation.from },\n );\n\n/**\n * Inheritance trees: each supertype with claimable subtypes forms a group — the hierarchy stacks\n * vertically (root on top, arrows up) and peers share a horizontal axis, packed as a tidy tree\n * (each parent centered over its subtree).\n */\nexport const inheritanceTreeRule: GroupRule = {\n id: 'inheritance',\n apply: (model, unclaimed, cell) => {\n const children = new Map<string, string[]>();\n const hasParent = new Set<string>();\n for (const relation of model.relations) {\n if (\n (relation.kind === 'inheritance' || relation.kind === 'realization') &&\n unclaimed.has(relation.from) &&\n unclaimed.has(relation.to)\n ) {\n // relation: subtype → supertype.\n children.set(relation.to, [...(children.get(relation.to) ?? []), relation.from]);\n hasParent.add(relation.from);\n }\n }\n\n const groups: Group[] = [];\n for (const [root] of children) {\n if (hasParent.has(root)) {\n continue;\n }\n const rects = new Map<string, Rect>();\n // Cyclic or diamond hierarchies (LLM/user input) must not recurse forever; each node\n // renders once, on first visit.\n const claimable = (id: string) => unclaimed.has(id) && !rects.has(id);\n const widths = new Map<string, number>();\n // Tidy-tree: a subtree is as wide as its children row (or one cell); parent centers over it.\n const layoutSubtree = (id: string, x: number, depth: number): number => {\n rects.set(id, { x: 0, y: 0, w: cell.w, h: cell.h });\n const kids = (children.get(id) ?? []).filter(claimable);\n const kidWidths = kids.map((kid) => subtreeWidth(kid));\n const rowWidth = kidWidths.reduce((sum, w) => sum + w, 0) + Math.max(0, kids.length - 1) * GAP;\n const width = Math.max(cell.w, rowWidth);\n let childX = x + (width - rowWidth) / 2;\n for (const [index, kid] of kids.entries()) {\n layoutSubtree(kid, childX, depth + 1);\n childX += kidWidths[index] + GAP;\n }\n rects.set(id, { x: x + (width - cell.w) / 2, y: depth * (cell.h + GAP), w: cell.w, h: cell.h });\n return width;\n };\n const subtreeWidth = (id: string, seen: Set<string> = new Set()): number => {\n const cached = widths.get(id);\n if (cached !== undefined) {\n return cached;\n }\n if (seen.has(id)) {\n return cell.w;\n }\n seen.add(id);\n const kids = (children.get(id) ?? []).filter((kid) => unclaimed.has(kid) && !rects.has(kid) && !seen.has(kid));\n const width =\n kids.length === 0\n ? cell.w\n : Math.max(cell.w, kids.reduce((sum, kid) => sum + subtreeWidth(kid, seen), 0) + (kids.length - 1) * GAP);\n widths.set(id, width);\n return width;\n };\n const width = layoutSubtree(root, 0, 0);\n const depth = Math.max(...[...rects.values()].map((rect) => rect.y)) + cell.h;\n if (rects.size < 2) {\n continue;\n }\n for (const id of rects.keys()) {\n unclaimed.delete(id);\n }\n groups.push({ id: `tree:${root}`, rule: 'inheritance', rects, w: width, h: depth });\n }\n return groups;\n },\n};\n\n/**\n * Longest linear chain: the longest path through the still-unclaimed up-oriented relation graph\n * renders left to right (each target directly right of its source).\n */\nexport const linearChainRule: GroupRule = {\n id: 'chain',\n apply: (model, unclaimed, cell) => {\n const edges = upEdges(model).filter((edge) => unclaimed.has(edge.from) && unclaimed.has(edge.to));\n const back = Layout.backEdges([...unclaimed], edges);\n const forward = edges.filter((edge) => !back.has(edge));\n const next = new Map<string, string[]>();\n for (const edge of forward) {\n next.set(edge.from, [...(next.get(edge.from) ?? []), edge.to]);\n }\n\n // Longest path by DFS memo (the forward graph is acyclic after back-edge removal).\n const memo = new Map<string, string[]>();\n const longestFrom = (id: string): string[] => {\n const cached = memo.get(id);\n if (cached) {\n return cached;\n }\n let best: string[] = [];\n for (const target of next.get(id) ?? []) {\n const path = longestFrom(target);\n if (path.length > best.length) {\n best = path;\n }\n }\n const result = [id, ...best];\n memo.set(id, result);\n return result;\n };\n\n let chain: string[] = [];\n for (const id of unclaimed) {\n const path = longestFrom(id);\n if (path.length > chain.length) {\n chain = path;\n }\n }\n if (chain.length < 3) {\n return [];\n }\n\n const rects = new Map<string, Rect>();\n // Chain runs source → target, reading left to right.\n chain.forEach((id, index) => {\n rects.set(id, { x: index * (cell.w + GAP), y: 0, w: cell.w, h: cell.h });\n unclaimed.delete(id);\n });\n return [\n { id: `chain:${chain[0]}`, rule: 'chain', rects, w: chain.length * cell.w + (chain.length - 1) * GAP, h: cell.h },\n ];\n },\n};\n\nexport type CompileOptions = Omit<GridCompileOptions, 'route'> & {\n /** Grouping rules, highest priority first. */\n rules?: GroupRule[];\n};\n\n/** Run the rules over the model; leftovers become singleton groups. */\nexport const buildGroups = (model: UmlModel, cell: Cell, rules: GroupRule[]): Group[] => {\n const unclaimed = new Set(model.classes.map((entry) => entry.id));\n const groups: Group[] = [];\n for (const rule of rules) {\n groups.push(...rule.apply(model, unclaimed, cell));\n }\n for (const id of unclaimed) {\n groups.push({\n id: `node:${id}`,\n rects: new Map([[id, { x: 0, y: 0, w: cell.w, h: cell.h }]]),\n w: cell.w,\n h: cell.h,\n });\n }\n return groups;\n};\n\n/**\n * Pack groups as super-nodes: rank by up-oriented cross-group edges (target group above), then\n * lay ranks out as rows, bottom rank last — mirroring the node-level convention.\n */\nexport const packGroups = (model: UmlModel, groups: Group[]): Map<string, Scene.Point> => {\n const groupOf = new Map<string, Group>();\n for (const group of groups) {\n for (const id of group.rects.keys()) {\n groupOf.set(id, group);\n }\n }\n const crossEdges = upEdges(model)\n .map((edge) => ({ from: groupOf.get(edge.from)!.id, to: groupOf.get(edge.to)!.id }))\n .filter((edge) => edge.from !== edge.to);\n const groupRanks = Layout.rank(\n groups.map((group) => group.id),\n // Rank grows downward from sources; cross edges point up, so invert.\n crossEdges.map((edge) => ({ from: edge.to, to: edge.from })),\n );\n\n const lanes = new Map<number, Group[]>();\n for (const group of groups) {\n const rank = groupRanks.get(group.id) ?? 0;\n lanes.set(rank, [...(lanes.get(rank) ?? []), group]);\n }\n const origins = new Map<string, Scene.Point>();\n let y = 0;\n for (const rank of [...lanes.keys()].sort((left, right) => left - right)) {\n const members = lanes.get(rank)!;\n let x = 0;\n for (const group of members) {\n origins.set(group.id, { x: snap(x), y: snap(y) });\n x += group.w + GROUP_GAP;\n }\n y += Math.max(...members.map((group) => group.h)) + GROUP_GAP;\n }\n return origins;\n};\n\n/** Absolute node rects for a (possibly partial) group placement. */\nexport const resolveRects = (groups: Group[], origins: Map<string, Scene.Point>): Map<string, Rect> => {\n const rects = new Map<string, Rect>();\n for (const group of groups) {\n const at = origins.get(group.id);\n if (!at) {\n continue;\n }\n for (const [id, rect] of group.rects) {\n rects.set(id, { ...rect, x: at.x + rect.x, y: at.y + rect.y });\n }\n }\n return rects;\n};\n\n/** Dashed frames behind multi-node groups. */\nexport const frameCommands = (\n groups: Group[],\n origins: Map<string, Scene.Point>,\n { origin = { x: 0, y: 0 }, scale = 1 }: { origin?: Scene.Point; scale?: number } = {},\n): Scene.Command[] =>\n groups\n .filter((group) => group.rects.size > 1 && origins.has(group.id))\n .map((group) => {\n const at = origins.get(group.id)!;\n return {\n op: 'upsert-object',\n object: {\n id: `group:${group.id}`,\n origin: { x: origin.x + (at.x - FRAME_PAD) * scale, y: origin.y + (at.y - FRAME_PAD) * scale },\n scale,\n elements: [\n {\n kind: 'rect',\n id: 'frame',\n x: 0,\n y: 0,\n w: group.w + FRAME_PAD * 2,\n h: group.h + FRAME_PAD * 2,\n stroke: 'dashed',\n color: 'grey',\n },\n ],\n },\n };\n });\n\n/**\n * Compile with rule-based grouping: rules claim groups, leftovers become singletons, groups pack\n * as super-nodes ranked by their cross-group edges (lanes advance vertically; no borders overlap\n * by construction), and multi-node groups render a dashed frame behind their members.\n */\nexport const compile = (source: string, options: CompileOptions = {}): Scene.Command[] => {\n const { origin = { x: 0, y: 0 }, scale = 1, maxWidth = GRID * 6 } = options;\n const rules = options.rules ?? [inheritanceTreeRule, linearChainRule];\n const model = parse(source);\n const cell = measureCell(model, { maxWidth, cell: options.cell, titleHeight: options.titleHeight });\n const groups = buildGroups(model, cell, rules);\n const origins = packGroups(model, groups);\n const rects = resolveRects(groups, origins);\n return [\n ...frameCommands(groups, origins, { origin, scale }),\n ...emit({ model, cell, rects, ranks: relationRanks(model) }, { origin, scale }),\n ];\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\n//\n// Scored placement search: the longest chain anchors the center; a greedy tree search walks the\n// relation graph outward, trying candidate positions for each still-unplaced group next to its\n// placed neighbour (above/below preferred, connecting nodes axis-aligned) and keeping the\n// highest-scoring one. The final layout is the better of the search and the rank packing, under\n// one score: +1 per straight connector, −1 per crossing. Entirely custom by necessity — ELK and\n// dagre are one-shot global optimizers with no scoring callback or incremental placement API —\n// but either can still lay out a group's interior or contribute a candidate to the same scorer.\n// See `docs/DESIGN.md`.\n//\n\nimport type * as Scene from './scene.ts';\nimport { GRID, type CompileOptions as GridCompileOptions, type Rect, emit, measureCell, zRouter } from './uml-grid.ts';\nimport {\n type Group,\n type GroupRule,\n buildGroups,\n frameCommands,\n inheritanceTreeRule,\n linearChainRule,\n packGroups,\n resolveRects,\n} from './uml-rules.ts';\nimport { type UmlModel, parse, relationRanks } from './uml.ts';\n\nconst GAP = GRID * 3;\n\nconst snap = (value: number) => Math.round(value / GRID) * GRID;\n\ntype Point = Scene.Point;\ntype Segment = [Point, Point];\n\nconst segmentsOf = (points: readonly Point[]): Segment[] =>\n points.slice(0, -1).map((point, index) => [point, points[index + 1]]);\n\n/** Orthogonal segment crossing: proper intersections plus collinear overlaps. */\nconst crosses = ([a1, a2]: Segment, [b1, b2]: Segment): boolean => {\n const aVertical = a1.x === a2.x;\n const bVertical = b1.x === b2.x;\n if (aVertical !== bVertical) {\n const [v1, v2] = aVertical ? [a1, a2] : [b1, b2];\n const [h1, h2] = aVertical ? [b1, b2] : [a1, a2];\n return (\n v1.x > Math.min(h1.x, h2.x) &&\n v1.x < Math.max(h1.x, h2.x) &&\n h1.y > Math.min(v1.y, v2.y) &&\n h1.y < Math.max(v1.y, v2.y)\n );\n }\n if (aVertical) {\n return a1.x === b1.x && Math.min(a1.y, a2.y) < Math.max(b1.y, b2.y) && Math.min(b1.y, b2.y) < Math.max(a1.y, a2.y);\n }\n return a1.y === b1.y && Math.min(a1.x, a2.x) < Math.max(b1.x, b2.x) && Math.min(b1.x, b2.x) < Math.max(a1.x, a2.x);\n};\n\n/** Direction changes along a polyline, ignoring zero-length segments. */\nconst bends = (route: readonly Point[]): number => {\n const points = route.filter(\n (point, index) => index === 0 || point.x !== route[index - 1].x || point.y !== route[index - 1].y,\n );\n let count = 0;\n for (let index = 2; index < points.length; index++) {\n const [a, b, c] = [points[index - 2], points[index - 1], points[index]];\n if (!((a.x === b.x && b.x === c.x) || (a.y === b.y && b.y === c.y))) {\n count++;\n }\n }\n return count;\n};\n\n/**\n * Layout score over the placed subset: +1 per straight or single-bend (L) route, −1 per crossing\n * pair. Routes come from the cheap Z-router — the score ranks candidates, the A* router draws\n * the final picture.\n */\nexport const scoreLayout = (model: UmlModel, rects: Map<string, Rect>): number => {\n const horizontal = model.direction === 'LR' || model.direction === 'RL';\n const routes: Point[][] = [];\n for (const relation of model.relations) {\n const from = rects.get(relation.from);\n const to = rects.get(relation.to);\n if (!from || !to) {\n continue;\n }\n routes.push(zRouter({ relation, from, to, horizontal, offset: 0 }));\n }\n\n let score = 0;\n for (const route of routes) {\n if (bends(route) <= 1) {\n score += 1;\n }\n }\n for (let a = 0; a < routes.length; a++) {\n for (let b = a + 1; b < routes.length; b++) {\n const pairCrosses = segmentsOf(routes[a]).some((left) =>\n segmentsOf(routes[b]).some((right) => crosses(left, right)),\n );\n if (pairCrosses) {\n score -= 1;\n }\n }\n }\n return score;\n};\n\nconst overlaps = (a: Rect, b: Rect): boolean =>\n a.x < b.x + b.w + GAP && b.x < a.x + a.w + GAP && a.y < b.y + b.h + GAP && b.y < a.y + a.h + GAP;\n\n/**\n * Greedy tree search: place the chain (or largest) group first, then repeatedly place the\n * unplaced group connected to the earliest-placed node, trying axis-aligned candidates around\n * the anchor (below and above preferred, then right/left, sliding off collisions) and keeping\n * the best-scoring one.\n */\nexport const searchPlacement = (model: UmlModel, groups: Group[]): Map<string, Scene.Point> => {\n const groupOf = new Map<string, Group>();\n for (const group of groups) {\n for (const id of group.rects.keys()) {\n groupOf.set(id, group);\n }\n }\n\n const seed =\n groups.find((group) => group.rule === 'chain') ??\n [...groups].sort((left, right) => right.rects.size - left.rects.size)[0];\n // An empty or unparseable source yields no groups; compile then emits an empty scene.\n if (!seed) {\n return new Map();\n }\n\n const origins = new Map<string, Point>();\n origins.set(seed.id, { x: 0, y: 0 });\n const placedNodes: string[] = [...seed.rects.keys()];\n\n const absolute = (id: string): Rect | undefined => {\n const group = groupOf.get(id)!;\n const at = origins.get(group.id);\n if (!at) {\n return undefined;\n }\n const local = group.rects.get(id)!;\n return { ...local, x: at.x + local.x, y: at.y + local.y };\n };\n const placedBounds = (): Rect[] =>\n groups.flatMap((group) => {\n const at = origins.get(group.id);\n return at ? [{ x: at.x, y: at.y, w: group.w, h: group.h }] : [];\n });\n\n while (origins.size < groups.length) {\n // Frontier: the earliest-placed node with a relation into an unplaced group.\n let anchorId: string | undefined;\n let connection: { group: Group; node: string } | undefined;\n for (const placed of placedNodes) {\n for (const relation of model.relations) {\n const other = relation.from === placed ? relation.to : relation.to === placed ? relation.from : undefined;\n if (other && !origins.has(groupOf.get(other)!.id)) {\n anchorId = placed;\n connection = { group: groupOf.get(other)!, node: other };\n break;\n }\n }\n if (connection) {\n break;\n }\n }\n // Disconnected remainder: park it right of everything placed so far.\n if (!connection || !anchorId) {\n const group = groups.find((candidate) => !origins.has(candidate.id))!;\n const rightmost = Math.max(...placedBounds().map((rect) => rect.x + rect.w), 0);\n origins.set(group.id, { x: snap(rightmost + GAP), y: 0 });\n placedNodes.push(...group.rects.keys());\n continue;\n }\n\n const anchor = absolute(anchorId)!;\n const local = connection.group.rects.get(connection.node)!;\n const anchorCenterX = anchor.x + anchor.w / 2;\n const anchorCenterY = anchor.y + anchor.h / 2;\n // Candidates align the connecting node's axis with the anchor's, above/below preferred.\n const candidates: Point[] = [\n { x: anchorCenterX - local.x - local.w / 2, y: anchor.y + anchor.h + GAP },\n { x: anchorCenterX - local.x - local.w / 2, y: anchor.y - GAP - connection.group.h },\n { x: anchor.x + anchor.w + GAP, y: anchorCenterY - local.y - local.h / 2 },\n { x: anchor.x - GAP - connection.group.w, y: anchorCenterY - local.y - local.h / 2 },\n ];\n\n let best: { at: Point; score: number } | undefined;\n for (const [candidateIndex, candidate] of candidates.entries()) {\n // Slide along the placement axis (in grid steps) until the group's border clears others.\n const at = { x: snap(candidate.x), y: snap(candidate.y) };\n const bounds = placedBounds();\n let tries = 0;\n // The first two candidates are the below/above placements; index, not coordinate\n // coincidence, decides the slide axis.\n const vertical = candidateIndex < 2;\n while (\n bounds.some((rect) => overlaps(rect, { x: at.x, y: at.y, w: connection.group.w, h: connection.group.h })) &&\n tries < 24\n ) {\n if (vertical) {\n at.x += GRID * 2;\n } else {\n at.y += GRID * 2;\n }\n tries++;\n }\n if (tries >= 24) {\n continue;\n }\n origins.set(connection.group.id, at);\n const score = scoreLayout(model, resolveRects(groups, originsSubset(groups, origins)));\n origins.delete(connection.group.id);\n // Strict >, so earlier (preferred: below, then above) candidates win ties.\n if (!best || score > best.score) {\n best = { at, score };\n }\n }\n\n const at = best?.at ?? { x: snap(Math.max(...placedBounds().map((rect) => rect.x + rect.w)) + GAP), y: 0 };\n origins.set(connection.group.id, at);\n placedNodes.push(...connection.group.rects.keys());\n }\n\n // Normalize the top-left to (0, 0).\n const minX = Math.min(...[...origins.values()].map((point) => point.x));\n const minY = Math.min(...[...origins.values()].map((point) => point.y));\n return new Map([...origins].map(([id, point]) => [id, { x: point.x - minX, y: point.y - minY }]));\n};\n\n/** Placement restricted to placed groups, so partial layouts score without phantom rects. */\nconst originsSubset = (groups: Group[], origins: Map<string, Point>): Map<string, Point> =>\n new Map(groups.filter((group) => origins.has(group.id)).map((group) => [group.id, origins.get(group.id)!]));\n\nexport type CompileOptions = Omit<GridCompileOptions, 'route'> & {\n rules?: GroupRule[];\n};\n\n/**\n * Compile via the scored search, falling back to whichever of {search, rank packing} scores\n * higher — the search is greedy, so the packing occasionally beats it.\n */\nexport const compile = (source: string, options: CompileOptions = {}): Scene.Command[] => {\n const { origin = { x: 0, y: 0 }, scale = 1, maxWidth = GRID * 6 } = options;\n const rules = options.rules ?? [inheritanceTreeRule, linearChainRule];\n const model = parse(source);\n const cell = measureCell(model, { maxWidth, cell: options.cell, titleHeight: options.titleHeight });\n const groups = buildGroups(model, cell, rules);\n\n const searched = searchPlacement(model, groups);\n const packed = packGroups(model, groups);\n const searchedScore = scoreLayout(model, resolveRects(groups, searched));\n const packedScore = scoreLayout(model, resolveRects(groups, packed));\n const origins = searchedScore >= packedScore ? searched : packed;\n\n const rects = resolveRects(groups, origins);\n return [\n ...frameCommands(groups, origins, { origin, scale }),\n ...emit({ model, cell, rects, ranks: relationRanks(model) }, { origin, scale }),\n ];\n};\n"],"mappings":";;;;;;;;;;;AAyEA,IAAa,iBACX,SACA,UACA,YACgB;CAChB,QAAQ,WAAW,OAAO;CAC1B,MAAM,2BAAW,IAAI,IAAY;CACjC,IAAI,UAAU;CAEd,MAAM,QAAQ,aAAqB,QAAQ,KAAK,OAAO,CAAC,CAAC,MAAM,QAAQ,MAAM,WAAW,OAAO,OAAO,QAAQ;CAE9G,MAAM,SAAS,QAAqB,cAAyB;EAC3D,MAAM,UAAU,QAAQ,OAAO,QAAQ,WAAW,OAAO;EACzD,IAAI,QAAQ,OACV,QAAQ,MAAM,SAAS,OAAO;OAE9B,OAAO,OAAO,SAAS,OAAO;CAElC;CAIA,MAAM,UAAU,cAAuD;EACrE,IAAI,QAAQ;EACZ,KAAK,MAAM,CAAC,KAAK,WAAW,OAAO,QAAQ,OAAO,GAAG;GACnD,MAAM,WAAW,QAAQ,SAAS,MAAM;GACxC,IAAI,YAAY,UAAU,QAAQ,GAAG;IAEnC,MAAM,SAAS,SAAS,SAAS,KAAA;IACjC,OAAO,QAAQ;IACf,IAAI,CAAC,QACH;GAEJ;EACF;EACA,QAAQ,QAAQ,OAAO;EACvB,OAAO;CACT;CAEA,KAAK,MAAM,WAAW,UACpB,QAAQ,QAAQ,IAAhB;EACE,KAAK,iBAAiB;GACpB,MAAM,WAAW,KAAK,QAAQ,OAAO,EAAE;GACvC,WAAW,QAAQ,aAAa,SAAS,WAAW,QAAQ,OAAO,EAAE;GACrE,MAAM,QAAQ,QAAQ;IACpB,QAAQ,QAAQ,OAAO,UAAU,UAAU,UAAU;KAAE,GAAG;KAAG,GAAG;IAAE;IAClE,OAAO,QAAQ,OAAO,SAAS,UAAU,SAAS;GACpD,CAAC;GACD,SAAS,IAAI,QAAQ,OAAO,EAAE;GAC9B;EACF;EAEA,KAAK,mBAAmB;GACtB,MAAM,WAAW,KAAK,QAAQ,QAAQ;GACtC,UAAU,UAAU,mBAAmB,QAAQ,SAAS,oCAAiC;IAAA,YAAA;IAAA,GAAA;IAAA,GAAA;IAAA,GAAA,KAAA;IAAA,GAAA,CAAA,YAAA,wEAAA;GAAA,CAAC;GAC1F,MAAM,MAAM,IAAI,IAAI,QAAQ,SAAS,KAAK,YAAY,QAAQ,EAAE,CAAC;GACjE,WAAW,QAAQ,aAAa,SAAS,WAAW,QAAQ,YAAY,IAAI,IAAI,SAAS,OAAO,CAAC;GACjG,MAAM;IAAE,IAAI,QAAQ;IAAU,UAAU,QAAQ;GAAS,GAAG,QAAQ;GACpE,SAAS,IAAI,QAAQ,QAAQ;GAC7B;EACF;EAEA,KAAK,mBAAmB;GACtB,MAAM,MAAM,IAAI,IAAI,QAAQ,UAAU;GACtC,WAAW,QAAQ,aAAa,SAAS,WAAW,QAAQ,YAAY,IAAI,IAAI,SAAS,OAAO,CAAC;GACjG;EACF;EAEA,KAAK;GACH,WAAW,QAAQ,aAAa,SAAS,WAAW,QAAQ,QAAQ;GACpE;EAGF,KAAK,eAAe;GAClB,MAAM,WAAW,KAAK,QAAQ,QAAQ;GACtC,UAAU,UAAU,mBAAmB,QAAQ,YAAS;IAAA,YAAA;IAAA,GAAA;IAAA,GAAA;IAAA,GAAA,KAAA;IAAA,GAAA,CAAA,YAAA,uCAAA;GAAA,CAAC;GACzD,MAAM,QAAQ;IAAE,GAAG,QAAQ,OAAO,IAAI,SAAS,OAAO;IAAG,GAAG,QAAQ,OAAO,IAAI,SAAS,OAAO;GAAE;GACjG,KAAK,MAAM,UAAU,OAAO,OAAO,OAAO,GACxC,IAAI,QAAQ,SAAS,MAAM,CAAC,EAAE,WAAW,QAAQ,UAC/C,QAAQ,UAAU,QAAQ,KAAK;GAGnC,SAAS,IAAI,QAAQ,QAAQ;GAC7B;EACF;CACF;CAGF,OAAO;EAAE,UAAU,CAAC,GAAG,QAAQ;EAAG;CAAQ;AAC5C;;AAGA,IAAa,aAAa,SAAqB,kBAA4C,SAAiB;CAC1G,IAAI,MAAM;CACV,IAAI,QAAQ;CACZ,KAAK,MAAM,UAAU,OAAO,OAAO,OAAO,GAAG;EAC3C,IAAI,CAAC,UAAU,CAAC,UAAU,MAAM,GAC9B;EAEF;EACA,MAAM,QAAQ,WAAW,KAAK,OAAO,SAAS,EAAE;EAChD,IAAI,OACF,MAAM,KAAK,IAAI,KAAK,OAAO,MAAM,EAAE,CAAC;CAExC;CACA,OAAO,KAAK,IAAI,KAAK,KAAK;AAC5B;;;;;ACzJA,IAAa,eAAkD;CAC7D,IAAI;CACJ,aAAa;CACb,OAAO,OAAO,MAAM,OAAa;CACjC,SAAS,OAAO;AAClB;AAEA,IAAa,kBAAb,MAA6B;CAC3B,4BAAqB,IAAI,IAAqB;CAE9C,YAAY,WAAsB,CAAC,YAAY,GAAG;EAChD,SAAS,SAAS,YAAY,KAAK,SAAS,OAAO,CAAC;CACtD;CAEA,SAAS,SAAwB;EAC/B,UAAU,CAAC,KAAK,UAAU,IAAI,QAAQ,EAAE,GAAG,sBAAsB,QAAQ,MAAG;GAAA,YAAA;GAAA,GAAA;GAAA,GAAA;GAAA,GAAA;GAAA,GAAA,CAAA,mCAAA,oCAAA;EAAA,CAAC;EAC7E,KAAK,UAAU,IAAI,QAAQ,IAAI,OAAO;CACxC;CAEA,IAAI,IAAiC;EACnC,OAAO,KAAK,UAAU,IAAI,EAAE;CAC9B;CAEA,OAAkB;EAChB,OAAO,CAAC,GAAG,KAAK,UAAU,OAAO,CAAC;CACpC;AACF;;;;;;;;ACnCA,IAAM,cACJ;AAIF,IAAM,aACJ;AAGF,IAAM,QACJ,IACA,KACA,aACA,UACA,cACuB;CAAE;CAAI;CAAK;CAAa,cAAc,GAAG,YAAY,GAAG;CAAY;AAAS;AAEtG,IAAa,QAAsC;CACjD,KACE,sBACA,oBACA,6FACA,kWAIA;EACE,MAAM;EACN,OAAO;CACT,CACF;CACA,KACE,mBACA,kBACA,qDACA,gHACA;EACE,MAAM;EACN,OAAO;CACT,CACF;CACA,KACE,oBACA,mBACA,yDACA,4PAGA;EACE,MAAM;EACN,OAAO;CACT,CACF;CACA,KACE,wBACA,sBACA,sFACA,gNAEA;EACE,MAAM;EACN,OAAO;CACT,CACF;CACA,KACE,WACA,WACA,yFACA,2KAEA;EACE,MAAM;EACN,OAAO;CACT,CACF;CACA,KACE,kBACA,iBACA,6EACA,uMAEA;EACE,MAAM;EACN,OAAO;CACT,CACF;CACA,KACE,cACA,aACA,qFACA,0LAEA;EACE,MAAM;EACN,OAAO;CACT,CACF;CACA,KACE,gBACA,eACA,8DACA,gHACA;EACE,MAAM;EACN,OAAO;CACT,CACF;AACF;;AAGA,IAAa,cAA4C,MAAM,KAAK,UAAU;CAC5E,GAAG;CACH,cAAc,GAAG,aAAa,KAAK,aAAa,MAAM,GAAkB;AAC1E,EAAE;;;;;AAMF,IAAa,SACX,QAAsC,UAC6B;CACnE,MAAM,QAAQ,QAAmB,OAAO,YAAY;CACpD,OAAO;EACL,SAAS,MAAM;EACf,WAAW,YACT,QAAQ,QAAQ,UAAU,QAAQ,QAAQ,SACtC,MAAM,SAAS,OAAO,IACtB,OAAO,QAAQ,MAAM,WAAW;GAAE,OAAO;GAAG,OAAO;EAAsB,EAAE,CAAC;CACpF;AACF;;;ACtIA,IAAM,UAAkC;CAAE,MAAM;CAAQ,MAAK;CAAO,MAAM;CAAO,KAAM;CAAO,MAAM;AAAM;;;;;;;AAQ1G,IAAa,gBAAgB,UAA0B;CACrD,IAAI,CAAC,OAAO,SAAS,KAAK,GACxB,MAAM,IAAI,UAAU,0CAA0C,MAAM,EAAE;CAExE,OAAO,OAAO,KAAK;AACrB;AAEA,IAAa,gBAAgB,UAC3B,IAAI,MAAM,QAAQ,iBAAiB,cAAc,QAAQ,cAAc,SAAS,EAAE;;AAGpF,IAAa,YAAY,OAAwB,QAAQ,KAAK,EAAE,KAAK,CAAC,SAAS,IAAI,EAAE,IAAI,KAAK,aAAa,EAAE;AAE7G,IAAM,eAAe,EAAE,GAAG,QAA6B,GAAG,aAAa,CAAC,EAAE,GAAG,aAAa,CAAC;AAE3F,IAAM,cAAc,GAAW,MAAsB,GAAG,aAAa,CAAC,EAAE,GAAG,aAAa,CAAC;;;;;;AAOzF,IAAM,aAAa,QAAyB,SAAS,KAAK,GAAG,KAAK,CAAC,SAAS,IAAI,GAAG,IAAI,MAAM,aAAa,GAAG;;AAG7G,IAAM,kBAAkB,KAAyB,UAC/C,QAAQ,KAAA,IAAY,UAAU,GAAG,IAAI,UAAU,KAAA,IAAY,YAAY,KAAK,IAAI;;AAKlF,IAAM,eAAe,MAAkC,WACrD,cAAc,KAAK,CAAC,SAAS,EAAE,MAAM,WAAW;CAC9C,MAAM,QAAQ,OAAO;CACrB,IAAI,UAAU,KAAA,GACZ,OAAO,CAAC;CAEV,OAAO,CAAC,GAAG,KAAK,GAAG,SAAS,YAAY,OAAO,UAAU,WAAW,aAAa,KAAK,IAAI,OAAO,KAAK,GAAG;AAC3G,CAAC;AAEH,IAAM,SAAS,EAAE,OAAO,MAAM,QAAQ,cAAiE;CACrG;CACA;CACA;CACA;AACF;AAEA,IAAa,iBAAiB,YAAmC;CAC/D,QAAQ,QAAQ,MAAhB;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,YACH,OAAO;GACL,QAAQ;GACR,SAAS,QAAQ,EAAE;GACnB,YAAY,OAAO;GACnB,WAAW,QAAQ,GAAG,QAAQ,CAAC;GAC/B,GAAI,QAAQ,SAAS,KAAA,IAAY,CAAC,IAAI,CAAC,aAAa,QAAQ,IAAI,CAAC;GACjE,GAAG,YAAY,QAAQ,MAAM;IAAE,UAAU,QAAQ;IAAU,SAAS,QAAQ;IAAS,GAAG,MAAM,OAAO;GAAE,CAAC;EAC1G,CAAC,CAAC,KAAK,GAAG;EAEZ,KAAK,UACH,OAAO;GACL;GACA,SAAS,QAAQ,EAAE;GACnB,YAAY;IAAE,GAAG,QAAQ;IAAI,GAAG,QAAQ;GAAG,CAAC;GAC5C,aAAa,QAAQ,CAAC;GACtB,GAAI,QAAQ,SAAS,KAAA,IAAY,CAAC,IAAI,CAAC,aAAa,QAAQ,IAAI,CAAC;GACjE,GAAG,YAAY,UAAU,MAAM,OAAO,CAAC;EACzC,CAAC,CAAC,KAAK,GAAG;EAEZ,KAAK,QACH,OAAO;GACL;GACA,SAAS,QAAQ,EAAE;GACnB,GAAG,QAAQ,OAAO,IAAI,WAAW;GACjC,GAAG,YAAY,QAAQ;IAAE,QAAQ,QAAQ;IAAQ,GAAG,MAAM,OAAO;GAAE,CAAC;EACtE,CAAC,CAAC,KAAK,GAAG;EAEZ,KAAK,SACH,OAAO;GACL;GACA,SAAS,QAAQ,EAAE;GACnB,GAAG,QAAQ,OAAO,IAAI,WAAW;GACjC,GAAG,YAAY,SAAS,MAAM,OAAO,CAAC;EACxC,CAAC,CAAC,KAAK,GAAG;EAEZ,KAAK,OACH,OAAO;GACL;GACA,SAAS,QAAQ,EAAE;GACnB,YAAY;IAAE,GAAG,QAAQ;IAAI,GAAG,QAAQ;GAAG,CAAC;GAC5C,aAAa,QAAQ,CAAC;GACtB,GAAG,aAAa,QAAQ,UAAU,EAAE,IAAI,aAAa,QAAQ,QAAQ;GACrE,GAAG,YAAY,OAAO,MAAM,OAAO,CAAC;EACtC,CAAC,CAAC,KAAK,GAAG;EAEZ,KAAK,QACH,OAAO;GACL;GACA,SAAS,QAAQ,EAAE;GACnB,YAAY,OAAO;GACnB,aAAa,QAAQ,IAAI;GACzB,GAAG,YAAY,QAAQ;IAAE,GAAG,QAAQ;IAAG,GAAG,MAAM,OAAO;GAAE,CAAC;EAC5D,CAAC,CAAC,KAAK,GAAG;EAEZ,KAAK,SACH,OAAO;GACL;GACA,SAAS,QAAQ,EAAE;GACnB,eAAe,QAAQ,MAAM,QAAQ,KAAK;GAC1C;GACA,eAAe,QAAQ,IAAI,QAAQ,GAAG;GACtC,GAAI,QAAQ,SAAS,KAAA,IAAY,CAAC,IAAI,CAAC,aAAa,QAAQ,IAAI,CAAC;GACjE,GAAG,YAAY,SAAS;IACtB,MAAM,QAAQ;IACd,MAAM,QAAQ;IACd,UAAU,QAAQ;IAClB,GAAG,MAAM,OAAO;GAClB,CAAC;EACH,CAAC,CAAC,KAAK,GAAG;EAEZ,KAAK,UACH,OAAO;GACL;GACA,SAAS,QAAQ,EAAE;GACnB,YAAY,OAAO;GACnB,WAAW,QAAQ,GAAG,QAAQ,CAAC;GAC/B,GAAI,QAAQ,SAAS,KAAA,IAAY,CAAC,IAAI,CAAC,aAAa,QAAQ,IAAI,CAAC;GACjE,GAAG,YAAY,UAAU;IAAE,KAAK,QAAQ;IAAK,GAAG,MAAM,OAAO;GAAE,CAAC;EAClE,CAAC,CAAC,KAAK,GAAG;CACd;AACF;AAEA,IAAM,SAAS,QAAgB,aAC7B;CAAC,GAAG,OAAO;CAAK,GAAG,SAAS,KAAK,YAAY,KAAK,cAAc,OAAO,GAAG;CAAG;AAAG,CAAC,CAAC,KAAK,IAAI;AAE7F,IAAa,gBAAgB,WAC3B,MACE;CACE;CACA,SAAS,OAAO,EAAE;CAClB,GAAI,OAAO,WAAW,KAAA,IAAY,CAAC,IAAI,CAAC,KAAK,YAAY,OAAO,MAAM,CAAC;CACvE,GAAG,aAAa,SAAS,EAAE,MAAM,WAAW;EAC1C,MAAM,QAAQ;GAAE,OAAO,OAAO;GAAO,OAAO,OAAO;GAAO,KAAK,OAAO;EAAI,EAAE;EAC5E,IAAI,UAAU,KAAA,GACZ,OAAO,CAAC;EAEV,OAAO,CAAC,GAAG,KAAK,GAAG,SAAS,YAAY,OAAO,UAAU,WAAW,aAAa,KAAK,IAAI,OAAO,KAAK,GAAG;CAC3G,CAAC;AACH,CAAC,CAAC,KAAK,GAAG,GACV,OAAO,QACT;AAEF,IAAa,iBAAiB,YAAmC;CAC/D,QAAQ,QAAQ,IAAhB;EACE,KAAK,iBACH,OAAO,aAAa,QAAQ,MAAM;EACpC,KAAK,mBACH,OAAO,MAAM,YAAY,SAAS,QAAQ,QAAQ,KAAK,QAAQ,QAAQ;EACzE,KAAK,eACH,OAAO,QAAQ,SAAS,QAAQ,QAAQ,EAAE,KAAK,YAAY,QAAQ,MAAM;EAC3E,KAAK,iBACH,OAAO,iBAAiB,SAAS,QAAQ,QAAQ;EACnD,KAAK,mBACH,OAAO,mBAAmB,SAAS,QAAQ,QAAQ,EAAE,GAAG,QAAQ,WAAW,IAAI,QAAQ,CAAC,CAAC,KAAK,GAAG;CACrG;AACF;;AAGA,IAAa,iBAAiB,aAC5B,SAAS,WAAW,IAAI,KAAK,GAAG,SAAS,IAAI,aAAa,CAAC,CAAC,KAAK,MAAM,EAAE;;AAG3E,IAAa,SAAS,UACpB,cAAc,MAAM,QAAQ,KAAK,YAAY;CAAE,IAAI;CAAiB;AAAO,EAAW,CAAC;AC1IzF,IAAa,UAA6B;CAAC;EAzBzC,IAAI;EACJ,aAAa;EACb,QAAQ;EACR,UAAU,WAAW,OAAO,WAAW,UAAY,MAAM,CAAC;CAsBjB;CAAW;EAdpD,IAAI;EACJ,aAAa;EACb,SAAS,WAAW,4BAA4B,KAAK,MAAM;EAC3D,UAAU,WAAW,OAAO,cAAc,UAAsB,MAAM,CAAC;CAWnB;CAAe;EANnE,IAAI;EACJ,aAAa;EACb,cAAc;EACd,UAAU,WAAW,OAAO,WAAW,UAAgB,MAAM,CAAC;CAGK;AAAoB;;AAGzF,IAAa,UAAU,WAAuC,QAAQ,MAAM,EAAE,aAAa,OAAO,MAAM,CAAC;AAEzG,IAAM,cAAc,QAAQ,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,KAAK,IAAI;;AAGzD,IAAa,qBAAb,cAAwC,KAAK,YAAY,sBAAsB,CAAC,CAAiB;CAC/F,IAAa,UAAkB;EAC7B,OAAO,4BAA4B,KAAK,GAAG,YAAY,MAAM,EAAE;CACjE;AACF;AAEA,IAAa,wBAAb,cAA2C,KAAK,YAAY,yBAAyB,CAAC,CAAK;CACzF,IAAa,UAAkB;EAC7B,OAAO,sDAAsD,MAAM,EAAE;CACvE;AACF;;AAQA,IAAa,WACX,MACA,EAAE,WAA2B,CAAC,MAE9B,OAAO,IAAI,aAAa;CACtB,MAAM,WAAW,WAAW,KAAA,IAAY,OAAO,IAAI,IAAI,QAAQ,MAAM,EAAE,SAAS,OAAO,MAAM;CAC7F,IAAI,CAAC,UACH,OAAO,OAAO,OAAO,KACnB,WAAW,KAAA,IAAY,IAAI,sBAAsB,IAAI,IAAI,mBAAmB,EAAE,IAAI,OAAO,CAAC,CAC5F;CAEF,OAAO,cAAc,OAAO,SAAS,QAAQ,IAAI,CAAC;AACpD,CAAC;;;;;;;;AChFH,IAAa,YAAkF,OAAO,GAAG,aAAa,CAAC,CACrH,WAAW,MAAc,UAA0B,CAAC,GAAG;CACrD,MAAM,UAAU,KAAK,IAAI;CACzB,MAAM,EAAE,YAAY;CACpB,IAAI,CAAC,SACH,OAAO,WAAW,OAAO;CAE3B,MAAM,WAAW,OAAO,OAAO,cAAc,UAAuB,SAAS,OAAO,CAAC;CACrF,OAAO,WAAW,SAAS,QAAQ;AACrC,CACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AEdA,IAAa,SAAS;AAEtB,IAAM,YAAY;AAElB,IAAM,aAAa;AAEnB,IAAM,SACJ;;;;;;AAOF,IAAM,UAAU,YAA6B;CAC3C,MAAM,UAAU,SAAiB,KAAK,QAAQ,MAAM,SAAS,CAAC,CAAC,QAAQ,MAAM,SAAS,CAAC,CAAC,QAAQ,MAAM,SAAS;CAC/G,IACE,WACA,OAAO,YAAY,YACnB,CAAC,MAAM,QAAQ,OAAO,KACtB,aAAa,WACb,MAAM,QAAQ,QAAQ,OAAO,GAC7B;EACA,MAAM,EAAE,SAAS,GAAG,SAAS;EAC7B,MAAM,OAAO,KAAK,UAAU,IAAI;EAChC,MAAM,OAAO,QAAQ,KAAK,WAAoB,OAAO,KAAK,UAAU,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK;EACxF,OAAO,GAAG,OAAO,KAAK,MAAM,GAAG,EAAE,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,GAAG,eAAe,KAAK;CACvF;CACA,OAAO,OAAO,KAAK,UAAU,OAAO,CAAC;AACvC;;AAGA,IAAa,SAAS,KAAa,YAA6B;CAC9D,MAAM,OAAO,eAAe,KAAK,GAAG;CACpC,IAAI,CAAC,MACH,MAAM,IAAI,MAAM,wCAAwC;CAE1D,IAAI,gBAAgB,KAAK,KAAK,EAAE,GAC9B,MAAM,IAAI,MAAM,2CAA2C;CAE7D,MAAM,OAAO,KAAK,EAAE,CAAC,QAAQ,UAAU,kBAAkB,UAAU,gBAAgB,OAAO,EAAE;CAC5F,MAAM,WAAW,wCAAwC,WAAW,4CAA4C,OAAO,OAAO,EAAE;CAChI,OAAO,GAAG,IAAI,MAAM,GAAG,KAAK,KAAK,IAAI,OAAO,IAAI,OAAO,WAAW,IAAI,MAAM,KAAK,QAAQ,KAAK,EAAE,CAAC,MAAM;AACzG;;AAGA,IAAa,WAAW,QAAyB,oCAAoC,KAAK,GAAG;;;;;AAM7F,IAAa,WAAW,QAAyB;CAC/C,MAAM,QAAQ,oEAAoE,KAAK,GAAG;CAC1F,IAAI,CAAC,OACH;CAEF,MAAM,aAAa,GAAG,MAAM,GAAG,GAAG,MAAM;CACxC,MAAM,WAAW,4BAA4B,KAAK,UAAU,CAAC,GAAG,MAAM;CACtE,IAAI,aAAa,QACf,MAAM,IAAI,MAAM,wCAAwC,SAAS,EAAE;CAErE,OAAO,KAAK,MAAM,MAAM,EAAE;AAC5B;;;;;;;;;;;;;AClBA,IAAa,YAAY,UAAkB,OAAA,MAAqC,KAAK,IAAI,KAAK,IAAI,GAAG,QAAQ,IAAI;;AAGjH,IAAa,oBAAoB,gBAA8C;CAC7E,IAAI,WAAW;CACf,MAAM;CACN,aAAa,WAAW;CACxB,WAAW,WACT,OAAO,WAAW;EAChB,MAAM,aAAa,WAAW,WAAW,MAAM;EAC/C,OAAO;GAAE,OAAO,WAAW,SAAS,IAAI;GAAG,GAAI,WAAW,SAAS,EAAE,QAAQ,WAAW,KAAK,IAAI,EAAE,IAAI,CAAC;EAAG;CAC7G,CAAC;AACL;;AAGA,IAAa,cAAc,MAA0B,OAAA,OAAsC;CACzF,IAAI,KAAK;CACT,MAAM;CACN,aAAa,KAAK;CAClB,WAAW,WACT,OAAO,WAAW;EAChB,MAAM,QAAQ,KAAK,QAAQ,MAAM;EACjC,MAAM,WAAW,QAAQ,KAAK;EAC9B,OAAO;GAAE,OAAO,SAAS,UAAU,IAAI;GAAG,QAAQ,GAAG,MAAM,KAAK,EAAE,KAAK,KAAK,OAAO,KAAK,MAAM,QAAQ;EAAI;CAC5G,CAAC;AACL;;AAGA,IAAa,iBAAiB,WAAgC,OAAA,MAAuC,CACnG,GAAG,UAAU,YAAY,IAAI,gBAAgB,GAC7C,GAAG,UAAU,MAAM,KAAK,SAAS,WAAW,MAAM,IAAI,CAAC,CACzD;AAEA,IAAM,WAAiB,WAAgD,aAAa;;AAGpF,IAAa,YAAkB,SAAkC,YAC/D,OAAO,IACL,QAAQ,KAAK,WACX,QAAQ,MAAM,IACV,OACG,SAAS,OAAO,CAAA,CAChB,KAAK,OAAO,KAAK,YAAY,OAAO,QAAQ,KAAK,OAAO,WAAW;CAAE,GAAG;CAAO,GAAG,QAAQ;AAAO,EAAE,CAAC,CAAC,IACxG,OACG,SAAS,OAAO,CAAA,CAChB,KACC,OAAO,KAAK,WAAW,CACrB;CAAE,IAAI,OAAO;CAAI,MAAM,OAAO;CAAM,aAAa,OAAO;CAAa,GAAG;AAAO,CACjF,CAAC,CACH,CACR,GACA,EAAE,aAAa,YAAY,CAC7B,CAAC,CAAC,KAAK,OAAO,KAAK,WAAW,OAAO,KAAK,CAAC,CAAC;;;;;;;AAQ9C,IAAa,WAAW,QAAiF;CACvG,MAAM,SAAS,IAAI,QAAQ,EAAE,YAAY,UAAU,KAAA,CAAS;CAC5D,IAAI,OAAO,WAAW,GACpB;CAEF,MAAM,OAAO,KAAK,IAAI,GAAG,GAAG,OAAO,QAAQ,EAAE,WAAW,SAAS,YAAY,CAAC,CAAC,KAAK,EAAE,YAAY,KAAK,CAAC;CACxG,MAAM,OAAO,OAAO,QAAQ,EAAE,WAAW,SAAS,YAAY;CAE9D,OAAO,QADM,KAAK,SAAS,KAAK,QAAQ,OAAO,EAAE,YAAY,QAAQ,OAAO,CAAC,IAAI,KAAK,SAAS;AAEjG;AAEA,IAAM,SAAS,UAAmB,OAAO,UAAU,KAAK,IAAI,GAAG,UAAU,MAAM,QAAQ,CAAC;;;;AClHxF,IAAa,aAAa;AAe1B,IAAM,eAAe,WACnB,OAAO,QAAQ,WAAW,YAAY,OAAO,QAAQ,YAAY,YAAY,QAAQ,SAAS,KAAA;;AAGhG,IAAM,WAAW,MAAuB,UACtC,KAAK,UAAU,KAAA,IACX,MAAM,UAAU,KAAA,IACd,IACA,KACF,MAAM,UAAU,KAAA,IACd,IACA,KAAK,QAAQ,MAAM,QACjB,KACA,KAAK,QAAQ,MAAM,QACjB,IACA;AAEZ,IAAa,aAA6B;CACxC,WAAW,WAAY,YAAY,MAAM,IAAI;EAAE,QAAQ,OAAO;EAAQ,SAAS,OAAO;CAAQ,IAAI,KAAA;CAElG,SAAS,QAAQ,WAAW,YAAY;EAGtC,IAAI,QACF,KAAK,IACH,IACA,GAAG,OAAO,OAAO,OAAO,CAAA,CACrB,OAAO,WAAW,CAAA,CAClB,KAAK,WAAW,OAAO,KAAK,CACjC,IAAI;EAGN,MAAM,WAAW,OAAO,OAAO,OAAO,CAAC,CAAC,MAAM,WAAW,YAAY,MAAM,KAAK,OAAO,WAAW,OAAO,EAAE;EAC3G,MAAM,MAAO,SAAS,UAAU,OAAO,OAAQ,UAAU;EACzD,MAAM,QAAS,WAAW,UAAU,OAAO,SAAU,UAAU;EAC/D,MAAM,UAAsB,CAAC;EAC7B,KAAK,MAAM,WAAW,OAAO,UAC3B,QAAQ,GAAG,OAAO,GAAG,GAAG,QAAQ,QAAQ;GACtC,QAAQ,OAAO;GACf,SAAS,QAAQ;GACjB,OAAO;GACP,WAAW;IAAE,QAAQ,EAAE,GAAG,UAAU,OAAO;IAAG,OAAO,UAAU;GAAM;GACrE,GAAI,MAAM,EAAE,IAAI,IAAI,CAAC;GACrB,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;GAEzB,MAAM,KAAK,MAAM,KAAK,UAAU,OAAO,CAAC;EAC1C;EAEF,OAAO;CACT;CAEA,OAAO,YAAY;EACjB,MAAM,UAAU,OAAO,OAAO,OAAO,CAAA,CAClC,OAAO,WAAW,CAAA,CAClB,MAAM,MAAM,UAAU,KAAK,QAAQ,MAAM,KAAK;EACjD,MAAM,0BAAU,IAAI,IAA6B;EACjD,IAAI,YAAY;EAChB,KAAK,MAAM,UAAU,OAAO,OAAO,OAAO,GACxC,IAAI,CAAC,YAAY,MAAM,GACrB;EAGJ,KAAK,MAAM,UAAU,SAAS;GAC5B,IAAI,SAAS,QAAQ,IAAI,OAAO,MAAM;GACtC,IAAI,CAAC,QAAQ;IACX,SAAS;KACP,IAAI,OAAO;KACX,QAAQ,EAAE,GAAG,OAAO,UAAU,OAAO;KACrC,OAAO,OAAO,UAAU;KACxB,GAAI,OAAO,MAAM,EAAE,KAAK,OAAO,IAAI,IAAI,CAAC;KACxC,GAAI,OAAO,QAAQ,EAAE,OAAO,OAAO,MAAM,IAAI,CAAC;KAC9C,UAAU,CAAC;IACb;IACA,QAAQ,IAAI,OAAO,QAAQ,MAAM;GACnC;GACA,OAAQ,SAA6B,KAAK,OAAO,IAAI;EACvD;EACA,OAAO;GAAE,OAAO,EAAE,SAAS,CAAC,GAAG,QAAQ,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE;GAAG;EAAU;CAC9E;CAEA,YAAY,QAAQ,UAAU;EAC5B,IAAI,YAAY,MAAM,GACpB,OAAO,UAAU,SAAS;GACxB,GAAG,OAAO,UAAU,OAAO,IAAI,MAAM;GACrC,GAAG,OAAO,UAAU,OAAO,IAAI,MAAM;EACvC;CAEJ;AACF;;;;;;;;;;AC7CA,IAAM,iBAAiB,QACrB,UAAU,UAAU,GAAG,IAAI,cAAc,IAAI,MAAM,CAAC,IAAI;AAE1D,IAAM,kBAAkB,QAAsC;CAC5D,IAAI,OAAO;CACX,OAAO,UAAU,QAAQ,IAAI,KAAK,KAAK,MAAM,WAAW,KAAK,UAAU,YAAY,KAAK,MAAM,EAAE,GAC9F,OAAO,KAAK,MAAM;CAEpB,OAAO;AACT;AAEA,IAAM,gBAAgB,QAAmE;CACvF,MAAM,OAAO,cAAc,GAAG;CAC9B,OAAO,KAAK,SAAS,YAAY,KAAK,qBAAqB,CAAC;AAC9D;AAEA,IAAM,kBAAkB,SACtB,UAAU,QAAQ,IAAI,KAAK,KAAK,MAAM,SAAS,KAAK,KAAK,MAAM,MAAM,UAAU,SAAS;AAE1F,IAAM,kBAAkB,SACtB,UAAU,SAAS,IAAI,KAAK,KAAK,SAAS,WAAW,KAAK,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,KAAK,KAAA;AAEpG,IAAM,WAAW,QAA2C;CAC1D,MAAM,QAAS,IAAI,aAAa,SAAS,UAAU,QAAQ,GAAG,CAAC,EAAE;CACjE,OAAO,OAAO,UAAU,WAAW,QAAQ,KAAA;AAC7C;AAEA,IAAM,SAAS,MAAmB,SAAgC,QAAQ,IAAI,KAAK,OAAO,IAAI;AAE9F,IAAM,aAAa,MAAqB,MAAmB,SAA0B;CAEnF,OAAO;EAAE,MAAM;EAAW,SADG,eAAe,IAAI,IAAI,WAAW,KAAK,SAAS,YAAY,aAAa;EACnE,OAAO,MAAM,MAAM,IAAI;EAAG;CAAK;AACpE;AAEA,IAAM,WAAW,MAAqB,MAAmB,MAAc,UAA6B;CAClG,MAAM,OAAO,eAAe,cAAc,IAAI,CAAC;CAE/C,MAAM,UAAU,eAAe,IAAI;CACnC,IAAI,WAAW,QAAQ,GAAG;EAExB,MAAM,OAAO;GAAE,GAAG,QAAQ,SAAS,IAAI,GAAG,KAAK,KAAK,QAAQ,CAAC;GAAG,OAAO;EAAG;EAC1E,OAAO;GAAE,MAAM;GAAS,OAAO,MAAM,MAAM,IAAI;GAAG;GAAM;EAAK;CAC/D;CAIA,IAAI,QAAQ,KAAK,CAAC,eAAe,IAAI,GAAG;EACtC,MAAM,aAAa,aAAa,IAAI;EACpC,IAAI,WAAW,SAAS,GACtB,OAAO;GACL,MAAM;GACN,OAAO,MAAM,MAAM,IAAI;GACvB;GACA,UAAU,WAAW,KAAK,aACxB,QAAQ,SAAS,MAAM,SAAS,MAAM,GAAG,KAAK,GAAG,OAAO,SAAS,IAAI,KAAK,QAAQ,CAAC,CACrF;EACF;CAEJ;CAEA,OAAO,UAAU,MAAM,MAAM,IAAI;AACnC;;AAGA,IAAa,cAAc,QAAoB,UAA6B,CAAC,MAAY;CACvF,MAAM,EAAE,WAAW,MAAM;CAIzB,OAAO;EAAE,MAAM;EAAQ,UAHN,aAAa,OAAO,GAAG,CAAA,CACrC,QAAQ,aAAa,SAAS,SAAS,IAAI,CAAA,CAC3C,KAAK,aAAa,QAAQ,SAAS,MAAM,SAAS,MAAM,OAAO,SAAS,IAAI,GAAG,QAAQ,CACnE;CAAS;AAClC;;AAGA,IAAa,eAAe,WAA2C,QAAQ,OAAO,GAAG;;AAGzF,IAAa,UAAU,MAAY,WAA0B;CAC3D,MAAM;CACN,QAAQ,CAAC;EAAE,MAAM;EAAS,OAAO;EAAO,OAAO;GAAE,MAAM;GAAS,OAAO;EAAK;CAAE,CAAC;AACjF;AAOA,IAAM,YAAY;AAClB,IAAM,YAAY;AAClB,IAAM,WAAW;AACjB,IAAM,UAAU;AAChB,IAAM,QAAM;AACZ,IAAM,MAAM;AACZ,IAAM,UAAU;AAChB,IAAM,SAAS;AAIf,IAAM,iBAAiB,UAAmB,KAAK,QAAQ,UAAU,KAAK;AAEtE,IAAM,YAAY,SAAyB;CACzC,QAAQ,KAAK,MAAb;EACE,KAAK,WACH,OAAO,cAAc,IAAI;EAC3B,KAAK;GAEH,IAAI,CAAC,KAAK,OACR,OAAO,KAAK,SAAS,QAAQ,KAAK,OAAO,UAAU,MAAM,SAAS,KAAK,KAAK,QAAQ,IAAI,QAAM,IAAI,CAAC;GAErG,OAAO,UAAU,KAAK,SAAS,QAAQ,KAAK,UAAU,MAAM,SAAS,KAAK,IAAI,OAAK,CAAC,IAAI;EAC1F,KAAK,SACH,OAAO,UAAU,SAAS,KAAK,IAAI,IAAI;EACzC,KAAK,QACH,OAAO,KAAK,SAAS,QAAQ,KAAK,OAAO,UAAU,MAAM,SAAS,KAAK,KAAK,QAAQ,IAAI,QAAM,IAAI,CAAC;EACrG,KAAK,SACH,OAAO,SAAS,KAAK,KAAK,IAAI,KAAU;EAC1C,KAAK,SACH,OAAO,SAAS,KAAK,KAAK,IAAI,MAAW,KAAK,QAAQ,UAAU;EAClE,KAAK,QACH,OAAO,KAAK,IAAI,GAAG,KAAK,OAAO,IAAI,QAAQ,GAAG,CAAC,IAAI;CACvD;AACF;AAEA,IAAM,WAAW,SAAyB;CACxC,QAAQ,KAAK,MAAb;EACE,KAAK,WACH,OAAO;EACT,KAAK,SACH,OAAO,KAAK,IAAI,GAAG,KAAK,SAAS,IAAI,OAAO,GAAG,SAAS,KAAK,KAAK,QAAQ,MAAM;EAClF,KAAK,SACH,OAAO,KAAK,IAAI,QAAQ,KAAK,IAAI,GAAG,SAAS,IAAI;EACnD,KAAK,QACH,OAAO,KAAK,IAAI,GAAG,KAAK,SAAS,IAAI,OAAO,GAAG,SAAS;EAC1D,KAAK,SACH,OAAO,QAAQ,KAAK,KAAK,IAAI;EAC/B,KAAK,SACH,OAAO,QAAQ,KAAK,KAAK,IAAI;EAC/B,KAAK,QACH,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO,UAAU,MAAM,QAAQ,KAAK,KAAK,QAAQ,IAAI,QAAM,IAAI,CAAC,IAAI;CACxG;AACF;;AAGA,IAAM,WAAW,QAAgB,SAA0B,SAAS,GAAG,OAAO,GAAG,SAAS;;AAG1F,IAAM,eAAe,MAAe,GAAW,GAAW,MAAY,WAAyB;CAC7F,MAAM,MAAM,KAAK,QAAQ,UAAU;CACnC,MAAM,WAA4B,KAAK,QACnC,CAAC;EAAE,MAAM;EAAQ,IAAI;EAAS,GAAG;EAAG,GAAG;EAAG,MAAM,KAAK;EAAO,QAAQ;EAAK,OAAO;CAAO,CAAC,IACxF,CAAC;CACL,QAAQ,KAAK,SAAb;EACE,KAAK;EACL,KAAK;GACH,SAAS,KAAK;IAAE,MAAM;IAAQ,IAAI;IAAO,GAAG;IAAG,GAAG;IAAK,GAAG;IAAU,GAAG;IAAW,QAAQ;GAAQ,CAAC;GACnG;EACF,KAAK;GACH,SAAS,KACP;IAAE,MAAM;IAAQ,IAAI;IAAO,GAAG;IAAG,GAAG;IAAK,GAAG;IAAW,GAAG;IAAW,QAAQ;GAAQ,GACrF;IAAE,MAAM;IAAQ,IAAI;IAAS,GAAG;IAAgB,GAAG,MAAM;IAAG,MAAM;IAAK,QAAQ;IAAK,OAAO;GAAO,CACpG;GACA;EACF,KAAK,SACH,SAAS,KAAK;GAAE,MAAM;GAAQ,IAAI;GAAO,GAAG;GAAG,GAAG;GAAK,GAAG;GAAW,GAAG;GAAW,QAAQ;EAAQ,CAAC;CAExG;CACA,KAAK,SAAS,KAAK;EAAE,IAAI;EAAiB,QAAQ;GAAE,IAAI,QAAQ,QAAQ,KAAK,IAAI;GAAG,QAAQ;IAAE;IAAG;GAAE;GAAG;EAAS;CAAE,CAAC;AACpH;AAEA,IAAM,SAAS,IAAY,GAAW,GAAW,GAAW,GAAW,OAA2B,SAAqB;CACrH,MAAM,WAA4B,CAAC;EAAE,MAAM;EAAQ,IAAI;EAAS,GAAG;EAAG,GAAG;EAAG;EAAG;EAAG,QAAQ;EAAU,OAAO;CAAO,CAAC;CACnH,IAAI,OACF,SAAS,KAAK;EAAE,MAAM;EAAQ,IAAI;EAAS,GAAG,MAAM;EAAG,GAAG;EAAG,MAAM;EAAO,QAAQ;CAAI,CAAC;CAEzF,KAAK,SAAS,KAAK;EAAE,IAAI;EAAiB,QAAQ;GAAE;GAAI,QAAQ;IAAE;IAAG;GAAE;GAAG;EAAS;CAAE,CAAC;AACxF;AAEA,IAAM,YAAY,MAAc,GAAW,GAAW,MAAY,SAAS,OAAa;CACtF,QAAQ,KAAK,MAAb;EACE,KAAK;GACH,YAAY,MAAM,GAAG,GAAG,MAAM,MAAM;GACpC;EAEF,KAAK,SAAS;GACZ,MAAM,YAAY,CAAC,KAAK;GACxB,IAAI,CAAC,WACH,MAAM,QAAQ,QAAQ,KAAK,IAAI,GAAG,GAAG,GAAG,QAAQ,IAAI,GAAG,SAAS,IAAI,GAAG,KAAK,OAAO,IAAI;GAEzF,IAAI,SAAS,KAAK,YAAY,IAAI;GAClC,KAAK,MAAM,SAAS,KAAK,UAAU;IACjC,SAAS,OAAO,KAAK,YAAY,IAAI,MAAM,QAAQ,MAAM,MAAM;IAC/D,UAAU,SAAS,KAAK,IAAI;GAC9B;GACA;EACF;EAEA,KAAK,SAAS;GACZ,MAAM,QAAQ,QAAQ,IAAI;GAC1B,MAAM,KAAK,QAAQ,QAAQ,KAAK,IAAI;GACpC,MAAM,IAAI,GAAG,GAAG,OAAO,SAAS,IAAI,GAAG,KAAK,OAAO,IAAI;GAEvD,KAAK,SAAS,KAAK;IACjB,IAAI;IACJ,QAAQ;KACN,IAAI,GAAG,GAAG;KACV,QAAQ;MAAE,GAAG,IAAI,QAAQ,WAAW;MAAG,GAAG,IAAI;KAAE;KAChD,UAAU,CAAC;MAAE,MAAM;MAAQ,IAAI;MAAO,GAAG;MAAG,GAAG;MAAG,GAAG;MAAU,GAAG;MAAQ,MAAM;MAAK,QAAQ;KAAQ,CAAC;IACxG;GACF,CAAC;GACD,SAAS,KAAK,MAAM,IAAI,KAAK,IAAI,SAAS,MAAM,MAAM;GACtD;EACF;EAEA,KAAK,QAAQ;GACX,IAAI,SAAS;GACb,KAAK,MAAM,SAAS,KAAK,UAAU;IACjC,SAAS,OAAO,GAAG,QAAQ,MAAM,MAAM;IACvC,UAAU,SAAS,KAAK,IAAI;GAC9B;GACA;EACF;EAEA,KAAK,SAAS;GACZ,MAAM,KAAK,QAAQ,QAAQ,OAAO;GAClC,MAAM,IAAI,GAAG,GAAG,QAAQ,IAAI,GAAG,SAAS,IAAI,GAAG,KAAK,SAAS,SAAS,IAAI;GAC1E,SAAS,KAAK,OAAO,IAAI,KAAK,IAAI,UAAU,KAAK,MAAM,EAAE;GACzD;EACF;EAEA,KAAK,SAAS;GACZ,MAAM,KAAK,UAAU;GACrB,MAAM,IAAI,GAAG,GAAG,QAAQ,IAAI,GAAG,SAAS,IAAI,GAAG,KAAK,OAAO,IAAI;GAC/D,SAAS,KAAK,OAAO,IAAI,KAAK,IAAI,OAAO,KAAK,QAAQ,UAAU,IAAI,MAAM,EAAE;GAC5E;EACF;EAEA,KAAK,QAAQ;GACX,MAAM,KAAK,QAAQ,QAAQ,MAAM;GACjC,MAAM,IAAI,GAAG,GAAG,QAAQ,IAAI,GAAG,SAAS,IAAI,GAAG,KAAA,GAAW,IAAI;GAC9D,IAAI,SAAS,IAAI;GAEjB,KAAK,OAAO,SAAS,OAAO,UAAU;IACpC,SAAS,OAAO,QAAQ,IAAI,KAAK,MAAM,GAAG,GAAG,QAAQ,OAAO;IAC5D,UAAU,QAAQ,KAAK,IAAI;GAC7B,CAAC;GACD;EACF;CACF;AACF;;AAUA,IAAa,aAAW,MAAc,UAA0B,CAAC,MAAuB;CACtF,MAAM,EAAE,SAAS;EAAE,GAAG;EAAG,GAAG;CAAE,GAAG,QAAQ,MAAM;CAC/C,MAAM,OAAa;EAAE,UAAU,CAAC;EAAG,UAAU,CAAC;CAAE;CAChD,SAAS,MAAM,GAAG,GAAG,IAAI;CACzB,OAAO,KAAK,SAAS,KAAK,YACxB,QAAQ,OAAO,kBACX;EACE,GAAG;EACH,QAAQ;GACN,GAAG,QAAQ;GACX;GACA,QAAQ;IACN,GAAG,OAAO,KAAK,QAAQ,OAAO,QAAQ,KAAK,KAAK;IAChD,GAAG,OAAO,KAAK,QAAQ,OAAO,QAAQ,KAAK,KAAK;GAClD;EACF;CACF,IACA,OACN;AACF;AAMA,IAAM,SAAsC;CAC1C,OAAO;CACP,QAAQ;CACR,UAAU;CACV,QAAQ;AACV;AAEA,IAAM,UAAU,OAAiB,WAA6B,MAAM,KAAK,UAAU,SAAS,KAAA,CAAM,QAAQ,CAAC;;AAG3G,IAAM,SAAS,OAAiB,UAA6B;CAC3D,MAAM,QAAQ,KAAK,IAAI,GAAG,MAAM,KAAK,SAAS,KAAK,MAAM,IAAI,OAAO,UAAU,KAAK,GAAG,EAAE;CAIxF,OAAO;EAHK,QACR,MAAM,MAAM,GAAG,IAAI,OAAO,KAAK,IAAI,QAAQ,MAAM,SAAS,GAAG,CAAC,CAAC,EAAE,KACjE,IAAI,IAAI,OAAO,QAAQ,CAAC,EAAE;EACjB,GAAG,MAAM,KAAK,SAAS,KAAK,KAAK,OAAO,KAAK,EAAE,GAAG;EAAG,IAAI,IAAI,OAAO,QAAQ,CAAC,EAAE;CAAE;AAChG;AAEA,IAAM,cAAc,SAA2B;CAC7C,QAAQ,KAAK,MAAb;EACE,KAAK,WACH,OAAO,KAAK,QAAQ,CAAC,KAAK,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,OAAO,KAAK,QAAQ;EAChF,KAAK,SAAS;GACZ,MAAM,WAAW,KAAK,SAAS,SAAS,OAAO,UAC7C,QAAQ,IAAI,CAAC,IAAI,GAAG,WAAW,KAAK,CAAC,IAAI,WAAW,KAAK,CAC3D;GACA,OAAO,KAAK,QAAQ,CAAC,KAAK,OAAO,GAAG,OAAO,UAAU,IAAI,CAAC,IAAI;EAChE;EACA,KAAK,SACH,OAAO,CAAC,GAAG,KAAK,MAAM,OAAO,GAAG,OAAO,WAAW,KAAK,IAAI,GAAG,IAAI,CAAC;EACrE,KAAK,QACH,OAAO,KAAK,SAAS,SAAS,OAAO,UAAW,QAAQ,IAAI,CAAC,IAAI,GAAG,WAAW,KAAK,CAAC,IAAI,WAAW,KAAK,CAAE;EAC7G,KAAK,SACH,OAAO,MAAM,WAAW,KAAK,KAAK,GAAG,KAAK,KAAK;EACjD,KAAK,SACH,OAAO,MAAM,WAAW,KAAK,KAAK,GAAG,KAAK,KAAK;EACjD,KAAK,QACH,OAAO,KAAK,OAAO,SAAS,OAAO,UAAW,QAAQ,IAAI,CAAC,IAAI,GAAG,WAAW,KAAK,CAAC,IAAI,WAAW,KAAK,CAAE;CAC7G;AACF;;AAGA,IAAa,eAAe,SAAyB,WAAW,IAAI,CAAC,CAAC,KAAK,IAAI;;;;AC7W/E,IAAM,WAAA;AACN,IAAM,YAAA;AAEN,IAAM,UAAQ,UAAkB,KAAK,MAAM,QAAA,EAAY,IAAA;AASvD,IAAM,kBAA6C;CAAE,IAAI;CAAM,IAAI;CAAM,IAAI;CAAM,IAAI;AAAK;AAC5F,IAAM,gBAA2C;CAAE,IAAI;CAAQ,IAAI;CAAM,IAAI;CAAS,IAAI;AAAO;;;;;;AAOjG,IAAM,iBAAiB,UACrB,MAAM,UAAU,KAAK,aACnB,SAAS,SAAS,iBAAiB,SAAS,SAAS,iBAAiB,SAAS,SAAS,eACpF;CAAE,MAAM,SAAS;CAAI,IAAI,SAAS;AAAK,IACvC;CAAE,MAAM,SAAS;CAAM,IAAI,SAAS;AAAG,CAC7C;;AAGF,IAAM,aAAa,UAAgD;CACjE,MAAM,UAAU,IAAI,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,IAAI;EAAE,GAAG;EAAM,GAAG,OAAK,KAAK,CAAC;EAAG,GAAG,OAAK,KAAK,CAAC;CAAE,CAAC,CAAC,CAAC;CAC3G,MAAM,OAAO,KAAK,IAAI,GAAG,CAAC,GAAG,QAAQ,OAAO,CAAC,CAAC,CAAC,KAAK,SAAS,KAAK,CAAC,GAAG,CAAC;CACvE,MAAM,OAAO,KAAK,IAAI,GAAG,CAAC,GAAG,QAAQ,OAAO,CAAC,CAAC,CAAC,KAAK,SAAS,KAAK,CAAC,GAAG,CAAC;CACvE,OAAO,IAAI,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,IAAI;EAAE,GAAG;EAAM,GAAG,KAAK,IAAI;EAAM,GAAG,KAAK,IAAI;CAAK,CAAC,CAAC,CAAC;AACxG;;AAGA,IAAM,cAAc,OAAiB,EAAE,MAAM,SAAS,UAAU,gBAAiD;CAC/G,MAAM,QAAQ,IAAI,SAAS,MAAM;CACjC,MAAM,SAAS;EACb,SAAS,gBAAgB;EACzB,QAAQ;EACR,SAAS;EACT,SAAS;EACT,SAAS,WAAW;CACtB,CAAC;CACD,MAAM,2BAA2B,CAAC,EAAE;CACpC,KAAK,MAAM,SAAS,MAAM,SACxB,MAAM,QAAQ,MAAM,IAAI;EAAE,OAAO,KAAK;EAAG,QAAQ,KAAK;CAAE,CAAC;CAE3D,KAAK,MAAM,QAAQ,cAAc,KAAK,GACpC,MAAM,QAAQ,KAAK,MAAM,KAAK,EAAE;CAElC,OAAY,KAAK;CASjB,OAAO,UAAU,IANC,IAChB,MAAM,QAAQ,KAAK,UAAU;EAC3B,MAAM,OAAO,MAAM,KAAK,MAAM,EAAE;EAChC,OAAO,CAAC,MAAM,IAAI;GAAE,GAAG,KAAK,IAAI,KAAK,IAAI;GAAG,GAAG,KAAK,IAAI,KAAK,IAAI;GAAG,GAAG,KAAK;GAAG,GAAG,KAAK;EAAE,CAAC;CAC5F,CAAC,CAEc,CAAK;AACxB;;AAGA,IAAM,WAAW,OACf,OACA,EAAE,MAAM,SAAS,UAAU,gBACI;CAE/B,MAAM,SAAS,MAAM,IADL,IACK,CAAA,CAAI,OAAO;EAC9B,IAAI;EACJ,eAAe;GACb,iBAAiB;GACjB,iBAAiB,cAAc;GAC/B,6CAA6C,OAAO,OAAO;GAC3D,wBAAwB,OAAO,QAAQ;GAEvC,sCAAsC;GAEtC,2CAA2C;EAC7C;EACA,UAAU,MAAM,QAAQ,KAAK,WAAW;GAAE,IAAI,MAAM;GAAI,OAAO,KAAK;GAAG,QAAQ,KAAK;EAAE,EAAE;EACxF,OAAO,cAAc,KAAK,CAAC,CAAC,KAAK,MAAM,WAAW;GAChD,IAAI,QAAQ;GACZ,SAAS,CAAC,KAAK,IAAI;GACnB,SAAS,CAAC,KAAK,EAAE;EACnB,EAAE;CACJ,CAAC;CAKD,OAAO,UAAU,IAHC,KACf,OAAO,YAAY,CAAC,EAAA,CAAG,KAAK,UAAU,CAAC,MAAM,IAAI;EAAE,GAAG,MAAM,KAAK;EAAG,GAAG,MAAM,KAAK;EAAG,GAAG,KAAK;EAAG,GAAG,KAAK;CAAE,CAAC,CAAC,CAE9F,CAAK;AACxB;;;;;;AAOA,IAAa,YAAU,OAAO,QAAgB,UAA0B,CAAC,MAAgC;CACvG,MAAM,EAAE,QAAQ,OAAO,WAAA,KAAqB,SAAS,UAAU;CAC/D,MAAM,QAAQ,QAAM,MAAM;CAC1B,MAAM,OAAO,YAAY,OAAO;EAAE;EAAU,MAAM,QAAQ;EAAM,aAAa,QAAQ;CAAY,CAAC;CAClG,MAAM,QAAsB;EAC1B;EACA,SAAS,OAAK,QAAQ,WAAW,QAAQ;EACzC,UAAU,OAAK,QAAQ,YAAY,SAAS;EAC5C,WAAW,MAAM;CACnB;CACA,MAAM,QAAQ,WAAW,UAAU,WAAW,OAAO,KAAK,IAAI,MAAM,SAAS,OAAO,KAAK;CACzF,OAAO,KAAK;EAAE;EAAO;EAAM;EAAO,OAAO,cAAc,KAAK;CAAE,GAAG;EAAE;EAAQ;CAAM,CAAC;AACpF;;;;;;;;;;;;ACzHA,IAAM,QAAA;AACN,IAAM,YAAA;AACN,IAAM,YAAA;AAEN,IAAM,UAAQ,UAAkB,KAAK,MAAM,QAAA,EAAY,IAAA;;AAsBvD,IAAM,WAAW,UACf,MAAM,UAAU,KAAK,aACnB,SAAS,SAAS,iBAAiB,SAAS,SAAS,iBAAiB,SAAS,SAAS,eACpF;CAAE,MAAM,SAAS;CAAM,IAAI,SAAS;AAAG,IACvC;CAAE,MAAM,SAAS;CAAI,IAAI,SAAS;AAAK,CAC7C;;;;;;AAOF,IAAa,sBAAiC;CAC5C,IAAI;CACJ,QAAQ,OAAO,WAAW,SAAS;EACjC,MAAM,2BAAW,IAAI,IAAsB;EAC3C,MAAM,4BAAY,IAAI,IAAY;EAClC,KAAK,MAAM,YAAY,MAAM,WAC3B,KACG,SAAS,SAAS,iBAAiB,SAAS,SAAS,kBACtD,UAAU,IAAI,SAAS,IAAI,KAC3B,UAAU,IAAI,SAAS,EAAE,GACzB;GAEA,SAAS,IAAI,SAAS,IAAI,CAAC,GAAI,SAAS,IAAI,SAAS,EAAE,KAAK,CAAC,GAAI,SAAS,IAAI,CAAC;GAC/E,UAAU,IAAI,SAAS,IAAI;EAC7B;EAGF,MAAM,SAAkB,CAAC;EACzB,KAAK,MAAM,CAAC,SAAS,UAAU;GAC7B,IAAI,UAAU,IAAI,IAAI,GACpB;GAEF,MAAM,wBAAQ,IAAI,IAAkB;GAGpC,MAAM,aAAa,OAAe,UAAU,IAAI,EAAE,KAAK,CAAC,MAAM,IAAI,EAAE;GACpE,MAAM,yBAAS,IAAI,IAAoB;GAEvC,MAAM,iBAAiB,IAAY,GAAW,UAA0B;IACtE,MAAM,IAAI,IAAI;KAAE,GAAG;KAAG,GAAG;KAAG,GAAG,KAAK;KAAG,GAAG,KAAK;IAAE,CAAC;IAClD,MAAM,QAAQ,SAAS,IAAI,EAAE,KAAK,CAAC,EAAA,CAAG,OAAO,SAAS;IACtD,MAAM,YAAY,KAAK,KAAK,QAAQ,aAAa,GAAG,CAAC;IACrD,MAAM,WAAW,UAAU,QAAQ,KAAK,MAAM,MAAM,GAAG,CAAC,IAAI,KAAK,IAAI,GAAG,KAAK,SAAS,CAAC,IAAI;IAC3F,MAAM,QAAQ,KAAK,IAAI,KAAK,GAAG,QAAQ;IACvC,IAAI,SAAS,KAAK,QAAQ,YAAY;IACtC,KAAK,MAAM,CAAC,OAAO,QAAQ,KAAK,QAAQ,GAAG;KACzC,cAAc,KAAK,QAAQ,QAAQ,CAAC;KACpC,UAAU,UAAU,SAAS;IAC/B;IACA,MAAM,IAAI,IAAI;KAAE,GAAG,KAAK,QAAQ,KAAK,KAAK;KAAG,GAAG,SAAS,KAAK,IAAI;KAAM,GAAG,KAAK;KAAG,GAAG,KAAK;IAAE,CAAC;IAC9F,OAAO;GACT;GACA,MAAM,gBAAgB,IAAY,uBAAoB,IAAI,IAAI,MAAc;IAC1E,MAAM,SAAS,OAAO,IAAI,EAAE;IAC5B,IAAI,WAAW,KAAA,GACb,OAAO;IAET,IAAI,KAAK,IAAI,EAAE,GACb,OAAO,KAAK;IAEd,KAAK,IAAI,EAAE;IACX,MAAM,QAAQ,SAAS,IAAI,EAAE,KAAK,CAAC,EAAA,CAAG,QAAQ,QAAQ,UAAU,IAAI,GAAG,KAAK,CAAC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,IAAI,GAAG,CAAC;IAC7G,MAAM,QACJ,KAAK,WAAW,IACZ,KAAK,IACL,KAAK,IAAI,KAAK,GAAG,KAAK,QAAQ,KAAK,QAAQ,MAAM,aAAa,KAAK,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS,KAAK,KAAG;IAC5G,OAAO,IAAI,IAAI,KAAK;IACpB,OAAO;GACT;GACA,MAAM,QAAQ,cAAc,MAAM,GAAG,CAAC;GACtC,MAAM,QAAQ,KAAK,IAAI,GAAG,CAAC,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,SAAS,KAAK,CAAC,CAAC,IAAI,KAAK;GAC5E,IAAI,MAAM,OAAO,GACf;GAEF,KAAK,MAAM,MAAM,MAAM,KAAK,GAC1B,UAAU,OAAO,EAAE;GAErB,OAAO,KAAK;IAAE,IAAI,QAAQ;IAAQ,MAAM;IAAe;IAAO,GAAG;IAAO,GAAG;GAAM,CAAC;EACpF;EACA,OAAO;CACT;AACF;;;;;AAMA,IAAa,kBAA6B;CACxC,IAAI;CACJ,QAAQ,OAAO,WAAW,SAAS;EACjC,MAAM,QAAQ,QAAQ,KAAK,CAAC,CAAC,QAAQ,SAAS,UAAU,IAAI,KAAK,IAAI,KAAK,UAAU,IAAI,KAAK,EAAE,CAAC;EAChG,MAAM,OAAO,UAAiB,CAAC,GAAG,SAAS,GAAG,KAAK;EACnD,MAAM,UAAU,MAAM,QAAQ,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC;EACtD,MAAM,uBAAO,IAAI,IAAsB;EACvC,KAAK,MAAM,QAAQ,SACjB,KAAK,IAAI,KAAK,MAAM,CAAC,GAAI,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC,GAAI,KAAK,EAAE,CAAC;EAI/D,MAAM,uBAAO,IAAI,IAAsB;EACvC,MAAM,eAAe,OAAyB;GAC5C,MAAM,SAAS,KAAK,IAAI,EAAE;GAC1B,IAAI,QACF,OAAO;GAET,IAAI,OAAiB,CAAC;GACtB,KAAK,MAAM,UAAU,KAAK,IAAI,EAAE,KAAK,CAAC,GAAG;IACvC,MAAM,OAAO,YAAY,MAAM;IAC/B,IAAI,KAAK,SAAS,KAAK,QACrB,OAAO;GAEX;GACA,MAAM,SAAS,CAAC,IAAI,GAAG,IAAI;GAC3B,KAAK,IAAI,IAAI,MAAM;GACnB,OAAO;EACT;EAEA,IAAI,QAAkB,CAAC;EACvB,KAAK,MAAM,MAAM,WAAW;GAC1B,MAAM,OAAO,YAAY,EAAE;GAC3B,IAAI,KAAK,SAAS,MAAM,QACtB,QAAQ;EAEZ;EACA,IAAI,MAAM,SAAS,GACjB,OAAO,CAAC;EAGV,MAAM,wBAAQ,IAAI,IAAkB;EAEpC,MAAM,SAAS,IAAI,UAAU;GAC3B,MAAM,IAAI,IAAI;IAAE,GAAG,SAAS,KAAK,IAAI;IAAM,GAAG;IAAG,GAAG,KAAK;IAAG,GAAG,KAAK;GAAE,CAAC;GACvE,UAAU,OAAO,EAAE;EACrB,CAAC;EACD,OAAO,CACL;GAAE,IAAI,SAAS,MAAM;GAAM,MAAM;GAAS;GAAO,GAAG,MAAM,SAAS,KAAK,KAAK,MAAM,SAAS,KAAK;GAAK,GAAG,KAAK;EAAE,CAClH;CACF;AACF;;AAQA,IAAa,eAAe,OAAiB,MAAY,UAAgC;CACvF,MAAM,YAAY,IAAI,IAAI,MAAM,QAAQ,KAAK,UAAU,MAAM,EAAE,CAAC;CAChE,MAAM,SAAkB,CAAC;CACzB,KAAK,MAAM,QAAQ,OACjB,OAAO,KAAK,GAAG,KAAK,MAAM,OAAO,WAAW,IAAI,CAAC;CAEnD,KAAK,MAAM,MAAM,WACf,OAAO,KAAK;EACV,IAAI,QAAQ;EACZ,uBAAO,IAAI,IAAI,CAAC,CAAC,IAAI;GAAE,GAAG;GAAG,GAAG;GAAG,GAAG,KAAK;GAAG,GAAG,KAAK;EAAE,CAAC,CAAC,CAAC;EAC3D,GAAG,KAAK;EACR,GAAG,KAAK;CACV,CAAC;CAEH,OAAO;AACT;;;;;AAMA,IAAa,cAAc,OAAiB,WAA8C;CACxF,MAAM,0BAAU,IAAI,IAAmB;CACvC,KAAK,MAAM,SAAS,QAClB,KAAK,MAAM,MAAM,MAAM,MAAM,KAAK,GAChC,QAAQ,IAAI,IAAI,KAAK;CAGzB,MAAM,aAAa,QAAQ,KAAK,CAAA,CAC7B,KAAK,UAAU;EAAE,MAAM,QAAQ,IAAI,KAAK,IAAI,CAAC,CAAE;EAAI,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC,CAAE;CAAG,EAAE,CAAA,CAClF,QAAQ,SAAS,KAAK,SAAS,KAAK,EAAE;CACzC,MAAM,aAAa,KACjB,OAAO,KAAK,UAAU,MAAM,EAAE,GAE9B,WAAW,KAAK,UAAU;EAAE,MAAM,KAAK;EAAI,IAAI,KAAK;CAAK,EAAE,CAC7D;CAEA,MAAM,wBAAQ,IAAI,IAAqB;CACvC,KAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,OAAO,WAAW,IAAI,MAAM,EAAE,KAAK;EACzC,MAAM,IAAI,MAAM,CAAC,GAAI,MAAM,IAAI,IAAI,KAAK,CAAC,GAAI,KAAK,CAAC;CACrD;CACA,MAAM,0BAAU,IAAI,IAAyB;CAC7C,IAAI,IAAI;CACR,KAAK,MAAM,QAAQ,CAAC,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,MAAM,MAAM,UAAU,OAAO,KAAK,GAAG;EACxE,MAAM,UAAU,MAAM,IAAI,IAAI;EAC9B,IAAI,IAAI;EACR,KAAK,MAAM,SAAS,SAAS;GAC3B,QAAQ,IAAI,MAAM,IAAI;IAAE,GAAG,OAAK,CAAC;IAAG,GAAG,OAAK,CAAC;GAAE,CAAC;GAChD,KAAK,MAAM,IAAI;EACjB;EACA,KAAK,KAAK,IAAI,GAAG,QAAQ,KAAK,UAAU,MAAM,CAAC,CAAC,IAAI;CACtD;CACA,OAAO;AACT;;AAGA,IAAa,gBAAgB,QAAiB,YAAyD;CACrG,MAAM,wBAAQ,IAAI,IAAkB;CACpC,KAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,KAAK,QAAQ,IAAI,MAAM,EAAE;EAC/B,IAAI,CAAC,IACH;EAEF,KAAK,MAAM,CAAC,IAAI,SAAS,MAAM,OAC7B,MAAM,IAAI,IAAI;GAAE,GAAG;GAAM,GAAG,GAAG,IAAI,KAAK;GAAG,GAAG,GAAG,IAAI,KAAK;EAAE,CAAC;CAEjE;CACA,OAAO;AACT;;AAGA,IAAa,iBACX,QACA,SACA,EAAE,SAAS;CAAE,GAAG;CAAG,GAAG;AAAE,GAAG,QAAQ,MAAgD,CAAC,MAEpF,OACG,QAAQ,UAAU,MAAM,MAAM,OAAO,KAAK,QAAQ,IAAI,MAAM,EAAE,CAAC,CAAA,CAC/D,KAAK,UAAU;CACd,MAAM,KAAK,QAAQ,IAAI,MAAM,EAAE;CAC/B,OAAO;EACL,IAAI;EACJ,QAAQ;GACN,IAAI,SAAS,MAAM;GACnB,QAAQ;IAAE,GAAG,OAAO,KAAK,GAAG,IAAI,aAAa;IAAO,GAAG,OAAO,KAAK,GAAG,IAAI,aAAa;GAAM;GAC7F;GACA,UAAU,CACR;IACE,MAAM;IACN,IAAI;IACJ,GAAG;IACH,GAAG;IACH,GAAG,MAAM,IAAI,YAAY;IACzB,GAAG,MAAM,IAAI,YAAY;IACzB,QAAQ;IACR,OAAO;GACT,CACF;EACF;CACF;AACF,CAAC;;;;;;AAOL,IAAa,aAAW,QAAgB,UAA0B,CAAC,MAAuB;CACxF,MAAM,EAAE,SAAS;EAAE,GAAG;EAAG,GAAG;CAAE,GAAG,QAAQ,GAAG,WAAA,QAAwB;CACpE,MAAM,QAAQ,QAAQ,SAAS,CAAC,qBAAqB,eAAe;CACpE,MAAM,QAAQ,QAAM,MAAM;CAC1B,MAAM,OAAO,YAAY,OAAO;EAAE;EAAU,MAAM,QAAQ;EAAM,aAAa,QAAQ;CAAY,CAAC;CAClG,MAAM,SAAS,YAAY,OAAO,MAAM,KAAK;CAC7C,MAAM,UAAU,WAAW,OAAO,MAAM;CACxC,MAAM,QAAQ,aAAa,QAAQ,OAAO;CAC1C,OAAO,CACL,GAAG,cAAc,QAAQ,SAAS;EAAE;EAAQ;CAAM,CAAC,GACnD,GAAG,KAAK;EAAE;EAAO;EAAM;EAAO,OAAO,cAAc,KAAK;CAAE,GAAG;EAAE;EAAQ;CAAM,CAAC,CAChF;AACF;;;;;;;;ACjSA,IAAM,MAAA;AAEN,IAAM,QAAQ,UAAkB,KAAK,MAAM,QAAA,EAAY,IAAA;AAKvD,IAAM,cAAc,WAClB,OAAO,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK,OAAO,UAAU,CAAC,OAAO,OAAO,QAAQ,EAAE,CAAC;;AAGtE,IAAM,WAAW,CAAC,IAAI,KAAc,CAAC,IAAI,QAA0B;CACjE,MAAM,YAAY,GAAG,MAAM,GAAG;CAE9B,IAAI,eADc,GAAG,MAAM,GAAG,IACD;EAC3B,MAAM,CAAC,IAAI,MAAM,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;EAC/C,MAAM,CAAC,IAAI,MAAM,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;EAC/C,OACE,GAAG,IAAI,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC,KAC1B,GAAG,IAAI,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC,KAC1B,GAAG,IAAI,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC,KAC1B,GAAG,IAAI,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC;CAE9B;CACA,IAAI,WACF,OAAO,GAAG,MAAM,GAAG,KAAK,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC,IAAI,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC,KAAK,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC,IAAI,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC;CAEnH,OAAO,GAAG,MAAM,GAAG,KAAK,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC,IAAI,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC,KAAK,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC,IAAI,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC;AACnH;;AAGA,IAAM,SAAS,UAAoC;CACjD,MAAM,SAAS,MAAM,QAClB,OAAO,UAAU,UAAU,KAAK,MAAM,MAAM,MAAM,QAAQ,EAAE,CAAC,KAAK,MAAM,MAAM,MAAM,QAAQ,EAAE,CAAC,CAClG;CACA,IAAI,QAAQ;CACZ,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS;EAClD,MAAM,CAAC,GAAG,GAAG,KAAK;GAAC,OAAO,QAAQ;GAAI,OAAO,QAAQ;GAAI,OAAO;EAAM;EACtE,IAAI,EAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAC9D;CAEJ;CACA,OAAO;AACT;;;;;;AAOA,IAAa,eAAe,OAAiB,UAAqC;CAChF,MAAM,aAAa,MAAM,cAAc,QAAQ,MAAM,cAAc;CACnE,MAAM,SAAoB,CAAC;CAC3B,KAAK,MAAM,YAAY,MAAM,WAAW;EACtC,MAAM,OAAO,MAAM,IAAI,SAAS,IAAI;EACpC,MAAM,KAAK,MAAM,IAAI,SAAS,EAAE;EAChC,IAAI,CAAC,QAAQ,CAAC,IACZ;EAEF,OAAO,KAAK,QAAQ;GAAE;GAAU;GAAM;GAAI;GAAY,QAAQ;EAAE,CAAC,CAAC;CACpE;CAEA,IAAI,QAAQ;CACZ,KAAK,MAAM,SAAS,QAClB,IAAI,MAAM,KAAK,KAAK,GAClB,SAAS;CAGb,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KACjC,KAAK,IAAI,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAIrC,IAHoB,WAAW,OAAO,EAAE,CAAC,CAAC,MAAM,SAC9C,WAAW,OAAO,EAAE,CAAC,CAAC,MAAM,UAAU,QAAQ,MAAM,KAAK,CAAC,CAExD,GACF,SAAS;CAIf,OAAO;AACT;AAEA,IAAM,YAAY,GAAS,MACzB,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;;;;;;;AAQ/F,IAAa,mBAAmB,OAAiB,WAA8C;CAC7F,MAAM,0BAAU,IAAI,IAAmB;CACvC,KAAK,MAAM,SAAS,QAClB,KAAK,MAAM,MAAM,MAAM,MAAM,KAAK,GAChC,QAAQ,IAAI,IAAI,KAAK;CAIzB,MAAM,OACJ,OAAO,MAAM,UAAU,MAAM,SAAS,OAAO,KAC7C,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,MAAM,UAAU,MAAM,MAAM,OAAO,KAAK,MAAM,IAAI,CAAC,CAAC;CAExE,IAAI,CAAC,MACH,uBAAO,IAAI,IAAI;CAGjB,MAAM,0BAAU,IAAI,IAAmB;CACvC,QAAQ,IAAI,KAAK,IAAI;EAAE,GAAG;EAAG,GAAG;CAAE,CAAC;CACnC,MAAM,cAAwB,CAAC,GAAG,KAAK,MAAM,KAAK,CAAC;CAEnD,MAAM,YAAY,OAAiC;EACjD,MAAM,QAAQ,QAAQ,IAAI,EAAE;EAC5B,MAAM,KAAK,QAAQ,IAAI,MAAM,EAAE;EAC/B,IAAI,CAAC,IACH;EAEF,MAAM,QAAQ,MAAM,MAAM,IAAI,EAAE;EAChC,OAAO;GAAE,GAAG;GAAO,GAAG,GAAG,IAAI,MAAM;GAAG,GAAG,GAAG,IAAI,MAAM;EAAE;CAC1D;CACA,MAAM,qBACJ,OAAO,SAAS,UAAU;EACxB,MAAM,KAAK,QAAQ,IAAI,MAAM,EAAE;EAC/B,OAAO,KAAK,CAAC;GAAE,GAAG,GAAG;GAAG,GAAG,GAAG;GAAG,GAAG,MAAM;GAAG,GAAG,MAAM;EAAE,CAAC,IAAI,CAAC;CAChE,CAAC;CAEH,OAAO,QAAQ,OAAO,OAAO,QAAQ;EAEnC,IAAI;EACJ,IAAI;EACJ,KAAK,MAAM,UAAU,aAAa;GAChC,KAAK,MAAM,YAAY,MAAM,WAAW;IACtC,MAAM,QAAQ,SAAS,SAAS,SAAS,SAAS,KAAK,SAAS,OAAO,SAAS,SAAS,OAAO,KAAA;IAChG,IAAI,SAAS,CAAC,QAAQ,IAAI,QAAQ,IAAI,KAAK,CAAC,CAAE,EAAE,GAAG;KACjD,WAAW;KACX,aAAa;MAAE,OAAO,QAAQ,IAAI,KAAK;MAAI,MAAM;KAAM;KACvD;IACF;GACF;GACA,IAAI,YACF;EAEJ;EAEA,IAAI,CAAC,cAAc,CAAC,UAAU;GAC5B,MAAM,QAAQ,OAAO,MAAM,cAAc,CAAC,QAAQ,IAAI,UAAU,EAAE,CAAC;GACnE,MAAM,YAAY,KAAK,IAAI,GAAG,aAAa,CAAC,CAAC,KAAK,SAAS,KAAK,IAAI,KAAK,CAAC,GAAG,CAAC;GAC9E,QAAQ,IAAI,MAAM,IAAI;IAAE,GAAG,KAAK,YAAY,GAAG;IAAG,GAAG;GAAE,CAAC;GACxD,YAAY,KAAK,GAAG,MAAM,MAAM,KAAK,CAAC;GACtC;EACF;EAEA,MAAM,SAAS,SAAS,QAAQ;EAChC,MAAM,QAAQ,WAAW,MAAM,MAAM,IAAI,WAAW,IAAI;EACxD,MAAM,gBAAgB,OAAO,IAAI,OAAO,IAAI;EAC5C,MAAM,gBAAgB,OAAO,IAAI,OAAO,IAAI;EAE5C,MAAM,aAAsB;GAC1B;IAAE,GAAG,gBAAgB,MAAM,IAAI,MAAM,IAAI;IAAG,GAAG,OAAO,IAAI,OAAO,IAAI;GAAI;GACzE;IAAE,GAAG,gBAAgB,MAAM,IAAI,MAAM,IAAI;IAAG,GAAG,OAAO,IAAI,MAAM,WAAW,MAAM;GAAE;GACnF;IAAE,GAAG,OAAO,IAAI,OAAO,IAAI;IAAK,GAAG,gBAAgB,MAAM,IAAI,MAAM,IAAI;GAAE;GACzE;IAAE,GAAG,OAAO,IAAI,MAAM,WAAW,MAAM;IAAG,GAAG,gBAAgB,MAAM,IAAI,MAAM,IAAI;GAAE;EACrF;EAEA,IAAI;EACJ,KAAK,MAAM,CAAC,gBAAgB,cAAc,WAAW,QAAQ,GAAG;GAE9D,MAAM,KAAK;IAAE,GAAG,KAAK,UAAU,CAAC;IAAG,GAAG,KAAK,UAAU,CAAC;GAAE;GACxD,MAAM,SAAS,aAAa;GAC5B,IAAI,QAAQ;GAGZ,MAAM,WAAW,iBAAiB;GAClC,OACE,OAAO,MAAM,SAAS,SAAS,MAAM;IAAE,GAAG,GAAG;IAAG,GAAG,GAAG;IAAG,GAAG,WAAW,MAAM;IAAG,GAAG,WAAW,MAAM;GAAE,CAAC,CAAC,KACxG,QAAQ,IACR;IACA,IAAI,UACF,GAAG,KAAA;SAEH,GAAG,KAAA;IAEL;GACF;GACA,IAAI,SAAS,IACX;GAEF,QAAQ,IAAI,WAAW,MAAM,IAAI,EAAE;GACnC,MAAM,QAAQ,YAAY,OAAO,aAAa,QAAQ,cAAc,QAAQ,OAAO,CAAC,CAAC;GACrF,QAAQ,OAAO,WAAW,MAAM,EAAE;GAElC,IAAI,CAAC,QAAQ,QAAQ,KAAK,OACxB,OAAO;IAAE;IAAI;GAAM;EAEvB;EAEA,MAAM,KAAK,MAAM,MAAM;GAAE,GAAG,KAAK,KAAK,IAAI,GAAG,aAAa,CAAC,CAAC,KAAK,SAAS,KAAK,IAAI,KAAK,CAAC,CAAC,IAAI,GAAG;GAAG,GAAG;EAAE;EACzG,QAAQ,IAAI,WAAW,MAAM,IAAI,EAAE;EACnC,YAAY,KAAK,GAAG,WAAW,MAAM,MAAM,KAAK,CAAC;CACnD;CAGA,MAAM,OAAO,KAAK,IAAI,GAAG,CAAC,GAAG,QAAQ,OAAO,CAAC,CAAC,CAAC,KAAK,UAAU,MAAM,CAAC,CAAC;CACtE,MAAM,OAAO,KAAK,IAAI,GAAG,CAAC,GAAG,QAAQ,OAAO,CAAC,CAAC,CAAC,KAAK,UAAU,MAAM,CAAC,CAAC;CACtE,OAAO,IAAI,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,WAAW,CAAC,IAAI;EAAE,GAAG,MAAM,IAAI;EAAM,GAAG,MAAM,IAAI;CAAK,CAAC,CAAC,CAAC;AAClG;;AAGA,IAAM,iBAAiB,QAAiB,YACtC,IAAI,IAAI,OAAO,QAAQ,UAAU,QAAQ,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,UAAU,CAAC,MAAM,IAAI,QAAQ,IAAI,MAAM,EAAE,CAAE,CAAC,CAAC;;;;;AAU5G,IAAa,WAAW,QAAgB,UAA0B,CAAC,MAAuB;CACxF,MAAM,EAAE,SAAS;EAAE,GAAG;EAAG,GAAG;CAAE,GAAG,QAAQ,GAAG,WAAA,QAAwB;CACpE,MAAM,QAAQ,QAAQ,SAAS,CAAC,qBAAqB,eAAe;CACpE,MAAM,QAAQ,QAAM,MAAM;CAC1B,MAAM,OAAO,YAAY,OAAO;EAAE;EAAU,MAAM,QAAQ;EAAM,aAAa,QAAQ;CAAY,CAAC;CAClG,MAAM,SAAS,YAAY,OAAO,MAAM,KAAK;CAE7C,MAAM,WAAW,gBAAgB,OAAO,MAAM;CAC9C,MAAM,SAAS,WAAW,OAAO,MAAM;CAGvC,MAAM,UAFgB,YAAY,OAAO,aAAa,QAAQ,QAAQ,CAEtD,KADI,YAAY,OAAO,aAAa,QAAQ,MAAM,CACjC,IAAc,WAAW;CAE1D,MAAM,QAAQ,aAAa,QAAQ,OAAO;CAC1C,OAAO,CACL,GAAG,cAAc,QAAQ,SAAS;EAAE;EAAQ;CAAM,CAAC,GACnD,GAAG,KAAK;EAAE;EAAO;EAAM;EAAO,OAAO,cAAc,KAAK;CAAE,GAAG;EAAE;EAAQ;CAAM,CAAC,CAChF;AACF"}