ice-entity-designer-dsl 0.0.7 → 0.0.9
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.
- package/README.md +40 -3
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/types/compiler/umlToScene.d.ts +35 -0
- package/dist/types/index.d.ts +5 -3
- package/dist/types/runtime/renderDsl.d.ts +14 -2
- package/dist/types/types.d.ts +55 -2
- package/dist/types/validate.d.ts +8 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -10,6 +10,10 @@ One document kind, three shapes:
|
|
|
10
10
|
- **BPMN document** (`kind: "bpmn"` with `nodes` / `edges`): business processes with
|
|
11
11
|
participants (pools), lanes, events, gateways and message flows. Containers are
|
|
12
12
|
nodes too, so the document stays a flat list; geometries are optional.
|
|
13
|
+
- **UML class diagram** (`kind: "uml"` with `nodes` / `edges`): classes, interfaces and
|
|
14
|
+
enums with free-text members (`- id: string`, `+ pay(): void`), plus the six relation
|
|
15
|
+
kinds (inheritance / realization / association / aggregation / composition /
|
|
16
|
+
dependency). Coordinates are optional — inheritance drives a top-down layering.
|
|
13
17
|
|
|
14
18
|
The package contains:
|
|
15
19
|
|
|
@@ -18,7 +22,7 @@ The package contains:
|
|
|
18
22
|
- compilers from DSL to Entity/Relation or FlowNode/FlowEdge props (shared layered layout)
|
|
19
23
|
- browser runtime that renders DSL through `ice-entity-designer`
|
|
20
24
|
- browser examples with a JSON editor (`examples/entity-editor-dsl.html`,
|
|
21
|
-
`examples/flowchart-dsl.html`, `examples/bpmn-dsl.html`)
|
|
25
|
+
`examples/flowchart-dsl.html`, `examples/bpmn-dsl.html`, `examples/uml-dsl.html`)
|
|
22
26
|
|
|
23
27
|
## Install
|
|
24
28
|
|
|
@@ -122,8 +126,39 @@ const result = ICEDSL.renderDsl('canvas', bpmn);
|
|
|
122
126
|
// result.kind === 'bpmn'; result.designer is a BpmnDesigner
|
|
123
127
|
result.designer.validateBpmn(); // 语义检查:每个池一个开始事件、顺序流不跨池…
|
|
124
128
|
const xml = IED.toBpmnXml(result.designer); // BPMN 2.0 + BPMNDI(互操作格式,不是执行模型)
|
|
129
|
+
const svg = result.designer.toSvg(); // 矢量 SVG(与画布同一口径,放大不糊)
|
|
125
130
|
```
|
|
126
131
|
|
|
132
|
+
### UML usage
|
|
133
|
+
|
|
134
|
+
```js
|
|
135
|
+
const uml = {
|
|
136
|
+
schemaVersion: 1,
|
|
137
|
+
kind: 'uml',
|
|
138
|
+
nodes: [
|
|
139
|
+
{ id: 'entity', kind: 'class', title: 'Entity', abstract: true, methods: ['+ save(): void'] },
|
|
140
|
+
{ id: 'user', kind: 'class', title: 'User', attributes: ['- email: string'] },
|
|
141
|
+
{ id: 'payable', kind: 'interface', title: 'Payable', methods: ['+ pay(): void'] },
|
|
142
|
+
],
|
|
143
|
+
edges: [
|
|
144
|
+
{ source: 'user', target: 'entity', type: 'inheritance' }, // source = 子类,target = 父类
|
|
145
|
+
{ source: 'user', target: 'payable', type: 'realization' },
|
|
146
|
+
],
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const result = ICEDSL.renderDsl('canvas', uml);
|
|
150
|
+
// result.kind === 'uml'; result.designer is a UmlDesigner
|
|
151
|
+
result.designer.validateUml(); // 重名类 / 继承成环 / 悬空关系
|
|
152
|
+
result.designer.toSvg(); // 矢量导出
|
|
153
|
+
IED.toPlantUml(result.designer); // 文本互操作(PlantUML / Mermaid 语法子集)
|
|
154
|
+
IED.fromPlantUml(text, result.designer); // 反向导入
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Node kinds: `class` (default) / `interface` / `enum`. Relation `type`: `inheritance` /
|
|
158
|
+
`realization` / `association` / `aggregation` / `composition` / `dependency` — the
|
|
159
|
+
direction convention is inherited from PlantUML (`A <|-- B` = B inherits A, so the
|
|
160
|
+
edge is `{ source: 'B', target: 'A' }`).
|
|
161
|
+
|
|
127
162
|
Node kinds: `pool` / `lane` (containers), `task` (default), `event`, `gateway`,
|
|
128
163
|
`subprocess`, `dataObject`, `annotation`; events carry `eventKind` (start /
|
|
129
164
|
intermediate / end) + `trigger`, gateways carry `gatewayType` (exclusive / parallel
|
|
@@ -134,18 +169,20 @@ intermediate / end) + `trigger`, gateways carry `gatewayType` (exclusive / paral
|
|
|
134
169
|
|
|
135
170
|
## API
|
|
136
171
|
|
|
137
|
-
- `validateDsl(dsl)` —— ER / flowchart / BPMN documents (dispatches on `kind`); `validateFlowDsl(dsl)` / `validateBpmnDsl(dsl)` for one kind only
|
|
172
|
+
- `validateDsl(dsl)` —— ER / flowchart / BPMN / UML documents (dispatches on `kind`); `validateFlowDsl(dsl)` / `validateBpmnDsl(dsl)` / `validateUmlDsl(dsl)` for one kind only
|
|
138
173
|
- `compileDsl(dsl)` —— ER document → `Entity` / `Relation` props
|
|
139
174
|
- `compileFlowDsl(dsl)` —— flowchart document → `FlowNode` / `FlowEdge` props (with layered auto-layout)
|
|
140
175
|
- `compileBpmnDsl(dsl)` —— BPMN document → `FlowNode` / `FlowEdge` props (container auto-geometry + container-scoped auto-layout)
|
|
176
|
+
- `compileUmlDsl(dsl)` —— UML document → `UmlClass` / `UmlRelation` props (inheritance-driven layering)
|
|
141
177
|
- `layeredLayout(items, edges, options)` —— the shared layered layout (`direction: "vertical" | "horizontal"`)
|
|
142
178
|
- `renderDsl(canvasOrId, dsl)` —— renders any kind, returns `{ kind, ice, designer }`
|
|
179
|
+
- Export: `result.designer.toSvg(options)` (flowchart / BPMN) or `IED.exportSvg(result.ice, options)`; `options` = `{ area: 'content' | 'viewport', padding, scale, background, includeTools }`. The SVG is regenerated from the component tree + path commands, so it matches the canvas (geometry, styles, opacity, shadows, link labels) and can be rasterised to PNG/PDF by any external tool.
|
|
143
180
|
- `DSL_SCHEMA_VERSION`
|
|
144
181
|
|
|
145
182
|
## Example
|
|
146
183
|
|
|
147
184
|
Open `examples/entity-editor-dsl.html` (ER), `examples/flowchart-dsl.html`
|
|
148
|
-
(flowchart)
|
|
185
|
+
(flowchart), `examples/bpmn-dsl.html` (BPMN) or `examples/uml-dsl.html` (UML) after building.
|
|
149
186
|
|
|
150
187
|
## Agent discovery
|
|
151
188
|
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("ice-entity-designer");function isFlowDsl(e){return!!e&&"object"==typeof e&&"flowchart"===e.kind}function isBpmnDsl(e){return!!e&&"object"==typeof e&&"bpmn"===e.kind}const t=["terminator","process","decision","io"],i=["T","R","B","L","C"],o=["pool","lane","task","event","gateway","subprocess","dataObject","annotation"],n=["start","intermediate","end"],r=["none","message","timer","error","terminate"],s=["exclusive","parallel","inclusive","event"],a=["none","user","service","script","send","receive","manual"],l=["sequence","message","association"];function validateDsl(e){return isBpmnDsl(e)?validateBpmnDsl(e):isFlowDsl(e)?validateFlowDsl(e):function validateErDsl(e){const t=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&t.push("Unsupported schemaVersion: "+e.schemaVersion);if(Array.isArray(e.entities)){const i=new Set;e.entities.forEach((e,o)=>{const n=`entities[${o}]`;e&&"object"==typeof e?("string"==typeof e.id&&e.id.trim()?i.has(e.id)?t.push(`${n}.id is duplicated: ${e.id}`):i.add(e.id):t.push(n+".id must be a non-empty string"),Array.isArray(e.fields)?e.fields.forEach((e,i)=>{e&&"object"==typeof e&&"string"==typeof e.name&&e.name.trim()||t.push(`${n}.fields[${i}].name must be a non-empty string`)}):t.push(n+".fields must be an array")):t.push(n+" must be an object")})}else t.push("entities must be an array");void 0===e.relations||Array.isArray(e.relations)?(e.relations||[]).forEach((e,i)=>{const o=`relations[${i}]`;e&&"object"==typeof e?("string"==typeof e.source&&e.source.trim()||t.push(o+".source must be a non-empty string"),"string"==typeof e.target&&e.target.trim()||t.push(o+".target must be a non-empty string")):t.push(o+" must be an object")}):t.push("relations must be an array");return{valid:0===t.length,errors:t}}(e)}function validateBpmnDsl(e){const t=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&t.push("Unsupported schemaVersion: "+e.schemaVersion);const i=new Set,p=new Map;return Array.isArray(e.nodes)?(e.nodes.forEach((e,l)=>{const d=`nodes[${l}]`;if(!e||"object"!=typeof e)return void t.push(d+" must be an object");"string"==typeof e.id&&e.id.trim()?i.has(e.id)?t.push(`${d}.id is duplicated: ${e.id}`):(i.add(e.id),p.set(e.id,e.kind||"task")):t.push(d+".id must be a non-empty string"),void 0!==e.kind&&-1===o.indexOf(e.kind)&&t.push(`${d}.kind must be one of ${o.join("/")}`),["left","top","width","height"].forEach(i=>{const o=e[i];void 0!==o&&"number"!=typeof o&&t.push(`${d}.${i} must be a number when present`)});[["eventKind",n],["trigger",r],["gatewayType",s],["taskType",a]].forEach(([i,o])=>{const n=e[i];void 0!==n&&-1===o.indexOf(n)&&t.push(`${d}.${i} must be one of ${o.join("/")}`)})}),e.nodes.forEach((e,o)=>{if(!e||"object"!=typeof e||void 0===e.parent)return;const n=`nodes[${o}]`;if("string"!=typeof e.parent||!e.parent.trim())return void t.push(n+".parent must be a non-empty string when present");if(!i.has(e.parent))return void t.push(n+".parent must reference an existing node id");if(e.parent===e.id)return void t.push(n+".parent must not reference itself");const r=p.get(e.parent);"pool"===e.kind?t.push(n+".parent is not allowed on a pool (池是最外层容器)"):"lane"===e.kind&&"pool"!==r?t.push(n+".parent must reference a pool"):"pool"!==r&&"lane"!==r&&t.push(n+".parent must reference a pool or a lane")})):t.push("nodes must be an array"),void 0===e.edges||Array.isArray(e.edges)?(e.edges||[]).forEach((e,o)=>{const n=`edges[${o}]`;if(!e||"object"!=typeof e)return void t.push(n+" must be an object");"string"==typeof e.source&&e.source.trim()&&i.has(e.source)||t.push(n+".source must reference an existing node id"),"string"==typeof e.target&&e.target.trim()&&i.has(e.target)||t.push(n+".target must reference an existing node id");const r=void 0!==e.type?e.type:e.flowType;void 0!==r&&-1===l.indexOf(r)&&t.push(`${n}.type must be one of ${l.join("/")}`),void 0!==e.label&&"string"!=typeof e.label&&t.push(n+".label must be a string when present"),void 0!==e.condition&&"string"!=typeof e.condition&&t.push(n+".condition must be a string when present"),void 0!==e.linkShape&&"visio"!==e.linkShape&&"bezier"!==e.linkShape&&t.push(n+'.linkShape must be "visio" or "bezier" when present')}):t.push("edges must be an array when present"),{valid:0===t.length,errors:t}}function validateFlowDsl(e){const o=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&o.push("Unsupported schemaVersion: "+e.schemaVersion);const n=new Set;return Array.isArray(e.nodes)?e.nodes.forEach((e,i)=>{const r=`nodes[${i}]`;e&&"object"==typeof e?("string"==typeof e.id&&e.id.trim()?n.has(e.id)?o.push(`${r}.id is duplicated: ${e.id}`):n.add(e.id):o.push(r+".id must be a non-empty string"),void 0!==e.kind&&-1===t.indexOf(e.kind)&&o.push(`${r}.kind must be one of ${t.join("/")}`),["left","top","width","height"].forEach(t=>{const i=e[t];void 0!==i&&"number"!=typeof i&&o.push(`${r}.${t} must be a number when present`)})):o.push(r+" must be an object")}):o.push("nodes must be an array"),void 0===e.edges||Array.isArray(e.edges)?(e.edges||[]).forEach((e,t)=>{const r=`edges[${t}]`;e&&"object"==typeof e?("string"==typeof e.source&&e.source.trim()&&n.has(e.source)||o.push(r+".source must reference an existing node id"),"string"==typeof e.target&&e.target.trim()&&n.has(e.target)||o.push(r+".target must reference an existing node id"),void 0!==e.label&&"string"!=typeof e.label&&o.push(r+".label must be a string when present"),void 0!==e.sourcePort&&-1===i.indexOf(e.sourcePort)&&o.push(`${r}.sourcePort must be one of ${i.join("/")}`),void 0!==e.targetPort&&-1===i.indexOf(e.targetPort)&&o.push(`${r}.targetPort must be one of ${i.join("/")}`),void 0!==e.linkShape&&"visio"!==e.linkShape&&"bezier"!==e.linkShape&&o.push(r+'.linkShape must be "visio" or "bezier" when present')):o.push(r+" must be an object")}):o.push("edges must be an array when present"),{valid:0===o.length,errors:o}}function entityName(e){return e.entityName||e.name||e.id}function relationType(e){return e.relationType||e.type||"one-to-many"}function compileDsl(e){if(isFlowDsl(e))throw new Error("compileDsl() 只处理 ER 文档;流程图文档请使用 compileFlowDsl()");if(!e||!Array.isArray(e.entities))throw new Error("ER 文档必须包含 entities 数组");return{entities:e.entities.map(e=>({id:e.id,entityName:entityName(e),fields:e.fields||[],left:e.left,top:e.top,width:e.width,height:e.height,style:e.style,headerStyle:e.headerStyle,fieldStyle:e.fieldStyle,dividerStyle:e.dividerStyle,draggable:e.draggable,interactive:e.interactive})),relations:(e.relations||[]).map((e,t)=>({id:e.id||"relation-"+t,relationType:relationType(e),sourceId:e.source,targetId:e.target,sourceField:e.sourceField||"id",targetField:e.targetField||"id",nullable:e.nullable,onDelete:e.onDelete,onUpdate:e.onUpdate,joinTableName:e.joinTableName,fromKey:e.fromKey,toKey:e.toKey,sourceCardinality:e.sourceCardinality,targetCardinality:e.targetCardinality,label:e.label,style:e.style,arrow:e.arrow,linkShape:e.linkShape,routeType:e.routeType,routeOffset:e.routeOffset,curveType:e.curveType,lineDash:e.lineDash})),layout:e.layout,options:e.options}}function layeredLayout(e,t,i={}){const o=Number(i.gapX)||90,n=Number(i.gapY)||90,r=void 0===i.originX?80:i.originX,s=void 0===i.originY?80:i.originY,a=new Map;if(!e.length)return a;const l=new Map;e.forEach(e=>l.set(e.id,e));const p=new Map,d=new Map;e.forEach(e=>{p.set(e.id,0),d.set(e.id,[])}),t.forEach(e=>{l.has(e.sourceId)&&l.has(e.targetId)&&(p.set(e.targetId,(p.get(e.targetId)||0)+1),d.get(e.sourceId).push(e.targetId))});const h=new Map,c=[];e.forEach(e=>{0===(p.get(e.id)||0)&&(h.set(e.id,0),c.push(e.id))}),c.length||(h.set(e[0].id,0),c.push(e[0].id));let u=e.length*e.length+e.length;for(;c.length&&u-- >0;){const e=c.shift(),t=h.get(e)||0;(d.get(e)||[]).forEach(e=>{const i=t+1;(void 0===h.get(e)?-1:h.get(e))<i&&(h.set(e,i),c.push(e))})}e.forEach(e=>{h.has(e.id)||h.set(e.id,0)});const f=new Map;e.forEach(e=>{const t=h.get(e.id)||0;f.has(t)||f.set(t,[]),f.get(t).push(e)});const m=[...f.keys()].sort((e,t)=>e-t);if("horizontal"===i.direction){const e=m.map(e=>Math.max(...f.get(e).map(e=>e.width)));let t=0;m.forEach((i,r)=>{const s=f.get(i);let l=-(s.reduce((e,t)=>e+t.height,0)+Math.max(s.length-1,0)*n)/2;s.forEach(i=>{a.set(i.id,{left:Math.round(t+(e[r]-i.width)/2),top:Math.round(l)}),l+=i.height+n}),t+=e[r]+o})}else{const e=m.map(e=>Math.max(...f.get(e).map(e=>e.height)));let t=0;m.forEach((i,r)=>{const s=f.get(i);let l=-(s.reduce((e,t)=>e+t.width,0)+Math.max(s.length-1,0)*o)/2;s.forEach(i=>{a.set(i.id,{left:Math.round(l),top:Math.round(t+(e[r]-i.height)/2)}),l+=i.width+o}),t+=e[r]+n})}const g=Math.min(...e.map(e=>a.get(e.id).left)),y=Math.min(...e.map(e=>a.get(e.id).top));return a.forEach(e=>{e.left+=r-g,e.top+=s-y}),a}const p={terminator:{width:e.FLOW_NODE_KINDS.terminator.width,height:e.FLOW_NODE_KINDS.terminator.height,fill:e.FLOW_NODE_KINDS.terminator.fill,stroke:e.FLOW_NODE_KINDS.terminator.stroke},process:{width:e.FLOW_NODE_KINDS.process.width,height:e.FLOW_NODE_KINDS.process.height,fill:e.FLOW_NODE_KINDS.process.fill,stroke:e.FLOW_NODE_KINDS.process.stroke},decision:{width:e.FLOW_NODE_KINDS.decision.width,height:e.FLOW_NODE_KINDS.decision.height,fill:e.FLOW_NODE_KINDS.decision.fill,stroke:e.FLOW_NODE_KINDS.decision.stroke},io:{width:e.FLOW_NODE_KINDS.io.width,height:e.FLOW_NODE_KINDS.io.height,fill:e.FLOW_NODE_KINDS.io.fill,stroke:e.FLOW_NODE_KINDS.io.stroke}};function compileFlowDsl(e){const t=e.options||{},i=(e.nodes||[]).map(e=>{const t=function nodeKind(e){return e.kind&&p[e.kind]?e.kind:"process"}(e),i=p[t];return{id:e.id,typeId:"FlowNode",kind:t,title:(o=e,o.title||o.name||o.id),left:"number"==typeof e.left?e.left:Number.NaN,top:"number"==typeof e.top?e.top:Number.NaN,width:"number"==typeof e.width?e.width:i.width,height:"number"==typeof e.height?e.height:i.height,fillColor:e.fillColor||i.fill,strokeColor:e.strokeColor||i.stroke};var o}),o=(e.edges||[]).map((e,t)=>({id:e.id||"edge-"+t,sourceId:e.source,targetId:e.target,sourcePort:e.sourcePort||"B",targetPort:e.targetPort||"T",label:e.label||"",linkShape:e.linkShape||"visio"})),n=t.layout||"layered";return"none"!==n&&i.some(e=>Number.isNaN(e.left)||Number.isNaN(e.top))&&(i.forEach(e=>{Number.isNaN(e.left)&&(e.left=0),Number.isNaN(e.top)&&(e.top=0)}),function autoLayout(e,t,i,o){const n=layeredLayout(e,t,{gapX:i,gapY:o});e.forEach(e=>{const t=n.get(e.id);t&&(e.left=t.left,e.top=t.top)})}(i,o,Number(t.gapX)||90,Number(t.gapY)||90)),i.forEach(e=>{Number.isNaN(e.left)&&(e.left=0),Number.isNaN(e.top)&&(e.top=0)}),{kind:"flowchart",nodes:i,edges:o,layout:n,options:t}}const d={pool:"bpmnPool",lane:"bpmnLane",task:"bpmnTask",event:"bpmnEvent",gateway:"bpmnGateway",subprocess:"bpmnSubprocess",dataObject:"bpmnDataObject",annotation:"bpmnAnnotation"},h=Number(e.FLOW_NODE_KINDS.bpmnPool.bandSize)||32,c=Number(e.FLOW_NODE_KINDS.bpmnLane.bandSize)||32,u=Number(e.FLOW_NODE_KINDS.bpmnLane.height)||130,f=Number(e.FLOW_NODE_KINDS.bpmnPool.width)||900;function toWorkingNode(t){const i=t.kind||"task",o=function presetOf(t){return e.FLOW_NODE_KINDS[t]||e.FLOW_NODE_KINDS.bpmnTask}(d[i]||"bpmnTask"),n={id:t.id,typeId:"FlowNode",kind:d[i]||"bpmnTask",title:t.title||t.name||t.id,left:"number"==typeof t.left?t.left:0,top:"number"==typeof t.top?t.top:0,width:"number"==typeof t.width?t.width:o.width,height:"number"==typeof t.height?t.height:o.height,fillColor:t.fillColor,strokeColor:t.strokeColor,dslKind:i,parent:t.parent,explicitLeft:"number"==typeof t.left,explicitTop:"number"==typeof t.top,explicitWidth:"number"==typeof t.width,explicitHeight:"number"==typeof t.height};return"event"===i&&(n.eventKind=t.eventKind||o.eventKind||"start",n.trigger=t.trigger||o.trigger||"none"),"gateway"===i&&(n.gatewayType=t.gatewayType||o.gatewayType||"exclusive"),"task"!==i&&"subprocess"!==i||(n.taskType=t.taskType||o.taskType||"none"),n}function buildGroups(e,t){const i=new Map;t.forEach(e=>i.set(e.id,e));const o=1===t.length?t[0]:null,n=[];return e.forEach(e=>{(e=>{let t=n.filter(t=>t.owner===e)[0];return t||(t={owner:e,nodes:[],box:null,didLayout:!1},n.push(t)),t})((e.parent?i.get(e.parent):void 0)||o).nodes.push(e)}),n}function layoutGroups(e,t,i,o){e.forEach(e=>{if(e.nodes.some(e=>!e.explicitLeft||!e.explicitTop)){const n=layeredLayout(e.nodes,t,{gapX:i,gapY:o,originX:0,originY:0,direction:"horizontal"});e.nodes.forEach(e=>{const t=n.get(e.id);t&&(e.left=t.left,e.top=t.top)}),e.didLayout=!0}e.box=function unionBox(e){if(!e.length)return null;let t=1/0,i=1/0,o=-1/0,n=-1/0;return e.forEach(e=>{t=Math.min(t,e.left),i=Math.min(i,e.top),o=Math.max(o,e.left+e.width),n=Math.max(n,e.top+e.height)}),{minX:t,minY:i,maxX:o,maxY:n}}(e.nodes)})}function compileBpmnDsl(e){const t=e.options||{},i=(e.nodes||[]).map(toWorkingNode),o=i.filter(e=>"pool"===e.dslKind),n=i.filter(e=>"lane"===e.dslKind),r=i.filter(e=>!function isContainer(e){return"pool"===e.dslKind||"lane"===e.dslKind}(e)),s=(e.edges||[]).map((e,t)=>({id:e.id||"edge-"+t,sourceId:e.source,targetId:e.target,flowType:e.type||e.flowType||"sequence",label:e.label||"",condition:e.condition||"",isDefault:!!e.isDefault,linkShape:e.linkShape||"visio"})),a=t.layout||"auto",l=function resolveLaneOwners(e,t){const i=new Map;return e.forEach(e=>{let o=e.parent;o||1!==t.length||(o=t[0].id),o&&i.set(e.id,o)}),i}(n,o),lanesOf=e=>n.filter(t=>l.get(t.id)===e);let p=[];"none"!==a&&(p=buildGroups(r,o.concat(n)),layoutGroups(p,s,Number(t.gapX)||90,Number(t.gapY)||60)),n.forEach(e=>{const t=p.filter(t=>t.owner===e)[0],i=t?t.box:null;e.explicitHeight||(e.height=Math.round(Math.max(56+(i?i.maxY-i.minY:0),u))),e.explicitWidth||(e.width=Math.round(Math.max((i?i.maxX-i.minX:0)+c+56,f)))}),o.forEach(e=>{const t=lanesOf(e.id);if(t.length){const i=t.reduce((e,t)=>Math.max(e,t.width),f);return e.explicitWidth||(e.width=i),e.explicitWidth&&t.forEach(t=>{t.explicitWidth||(t.width=e.width)}),void(e.explicitHeight||(e.height=h+t.reduce((e,t)=>e+t.height,0)))}const i=p.filter(t=>t.owner===e)[0],o=i?i.box:null;e.explicitWidth||(e.width=Math.round(Math.max(56+(o?o.maxX-o.minX:0),f))),e.explicitHeight||(e.height=Math.round(Math.max((o?o.maxY-o.minY:0)+h+56,160)))});let d=60;o.forEach(e=>{e.explicitLeft||(e.left=60),e.explicitTop||(e.top=d),d=Math.max(d,e.top+e.height+60)}),o.forEach(e=>{const t=lanesOf(e.id);if(!t.length)return;const i=e.top+h,o=Math.max(e.height-h,1),n=t.reduce((e,t)=>e+(t.explicitHeight?t.height:0),0),r=t.filter(e=>!e.explicitHeight),s=r.length?Math.max(o-n,0)/r.length:0;let a=i;t.forEach(t=>{t.explicitLeft||(t.left=e.left),t.explicitTop||(t.top=a),!t.explicitHeight&&e.explicitHeight&&(t.height=Math.round(s||u)),a=t.top+t.height})});let m=60;n.forEach(e=>{l.get(e.id)||(e.explicitLeft||(e.left=60),e.explicitTop||(e.top=m,m=e.top+e.height+60))}),p.forEach(e=>{const t=e.box;if(!t||!e.didLayout)return;const i=e.owner;let o=80,n=80;i&&(o=i.left+28,n=i.top+28,"pool"===i.dslKind?n+=h:o+=c),e.nodes.forEach(e=>{e.left=Math.round(o+(e.left-t.minX)),e.top=Math.round(n+(e.top-t.minY))})});return{kind:"bpmn",nodes:o.concat(n).concat(r).map(e=>{const t={id:e.id,typeId:"FlowNode",kind:e.kind,title:e.title,left:e.left,top:e.top,width:e.width,height:e.height};return void 0!==e.eventKind&&(t.eventKind=e.eventKind),void 0!==e.trigger&&(t.trigger=e.trigger),void 0!==e.gatewayType&&(t.gatewayType=e.gatewayType),void 0!==e.taskType&&(t.taskType=e.taskType),void 0!==e.fillColor&&(t.fillColor=e.fillColor),void 0!==e.strokeColor&&(t.strokeColor=e.strokeColor),t}),edges:s,layout:a,options:t}}function renderBpmnDsl(t,i){const o=compileBpmnDsl(i),n=o.options||{},r=(new e.ICE).init(t),s=new e.BpmnDesigner(r);return o.nodes.forEach(e=>{const t={id:e.id,title:e.title,left:e.left,top:e.top,width:e.width,height:e.height};["eventKind","trigger","gatewayType","taskType","fillColor","strokeColor"].forEach(i=>{void 0!==e[i]&&(t[i]=e[i])}),s.createNode(e.kind,t)}),o.edges.forEach(e=>{s.createEdge(e)}),s.select(null),n.viewport?r.setViewport(n.viewport.scale,n.viewport.tx,n.viewport.ty):!1!==n.fitViewport&&s.fitViewport(n.fitViewportPadding),s.resetHistory(),{kind:"bpmn",ice:r,designer:s}}function renderFlowDsl(t,i){const o=compileFlowDsl(i),n=o.options||{},r=(new e.ICE).init(t),s=new e.FlowDesigner(r);return o.nodes.forEach(e=>{s.createNode(e.kind,e)}),o.edges.forEach(e=>{s.createEdge(e)}),s.select(null),n.viewport?r.setViewport(n.viewport.scale,n.viewport.tx,n.viewport.ty):!1!==n.fitViewport&&s.fitViewport(n.fitViewportPadding),s.resetHistory(),{kind:"flowchart",ice:r,designer:s}}exports.DSL_SCHEMA_VERSION=1,exports.compileBpmnDsl=compileBpmnDsl,exports.compileDsl=compileDsl,exports.compileFlowDsl=compileFlowDsl,exports.isBpmnDsl=isBpmnDsl,exports.isFlowDsl=isFlowDsl,exports.layeredLayout=layeredLayout,exports.renderBpmnDsl=renderBpmnDsl,exports.renderDsl=function renderDsl(t,i){const o=validateDsl(i);if(!o.valid)throw new Error(o.errors.join("\n"));return isBpmnDsl(i)?renderBpmnDsl(t,i):isFlowDsl(i)?renderFlowDsl(t,i):function renderErDsl(t,i){const o=compileDsl(i),n=o.options||{},r=(new e.ICE).init(t),s=new e.EntityDesigner(r);o.entities.forEach(e=>{s.createEntity(e)}),function positionLinks(e,t,i){const o=new Map;return e.entities.forEach(e=>{o.set(e.state.id,e.getMinBoundingBox(!0))}),t.relations.map(e=>{const t=o.get(e.sourceId),n=o.get(e.targetId);let r="R",s="L";if(t&&n){const e=n.center[0]-t.center[0],i=n.center[1]-t.center[1];Math.abs(e)>Math.abs(i)?(r=e>=0?"R":"L",s=e>=0?"L":"R"):(r=i>=0?"B":"T",s=i>=0?"T":"B")}return{...e,routeType:e.routeType||i||"orthogonal",linkShape:e.linkShape||"visio",links:{start:{id:e.sourceId,position:r},end:{id:e.targetId,position:s}}}})}(s,o,n.routeType).forEach(e=>{s.createRelation(e)}),("layered"===o.layout||"horizontal"===o.layout)&&new e.ICELayeredLayout({gapX:n.gapX||120,gapY:n.gapY||50}).layoutContainer(r);n.viewport?r.setViewport(n.viewport.scale,n.viewport.tx,n.viewport.ty):n.fitViewport&&function fitViewport(e,t,i){const o=t.entities||[];let n=1/0,r=1/0,s=-1/0,a=-1/0;o.forEach(e=>{const t=e.getMinBoundingBox(!0).getMinAndMaxPoint();n=Math.min(n,t.minX),r=Math.min(r,t.minY),s=Math.max(s,t.maxX),a=Math.max(a,t.maxY)});const l=s-n,p=a-r,d=e.canvasWidth||0,h=e.canvasHeight||0;if(!d||!h||l<=0||p<=0)return;const c=Number.isFinite(i)&&i>=0?i:40,u=Math.max(1,d-2*c),f=Math.max(1,h-2*c),m=Math.min(u/l,f/p,1),g=(d-l*m)/2-n*m,y=(h-p*m)/2-r*m;e.setViewport(m,g,y)}(r,s,n.fitViewportPadding);return{kind:"entity",ice:r,designer:s}}(t,i)},exports.renderFlowDsl=renderFlowDsl,exports.validateBpmnDsl=validateBpmnDsl,exports.validateDsl=validateDsl,exports.validateFlowDsl=validateFlowDsl;
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("ice-entity-designer");function isFlowDsl(e){return!!e&&"object"==typeof e&&"flowchart"===e.kind}function isBpmnDsl(e){return!!e&&"object"==typeof e&&"bpmn"===e.kind}function isUmlDsl(e){return!!e&&"object"==typeof e&&"uml"===e.kind}const t=["terminator","process","decision","io"],i=["T","R","B","L","C"],o=["pool","lane","task","event","gateway","subprocess","dataObject","annotation"],r=["start","intermediate","end"],n=["none","message","timer","error","terminate"],s=["exclusive","parallel","inclusive","event"],a=["none","user","service","script","send","receive","manual"],l=["sequence","message","association"],d=["class","interface","enum"],p=["inheritance","realization","association","aggregation","composition","dependency"];function validateDsl(e){return isUmlDsl(e)?validateUmlDsl(e):isBpmnDsl(e)?validateBpmnDsl(e):isFlowDsl(e)?validateFlowDsl(e):function validateErDsl(e){const t=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&t.push("Unsupported schemaVersion: "+e.schemaVersion);if(Array.isArray(e.entities)){const i=new Set;e.entities.forEach((e,o)=>{const r=`entities[${o}]`;e&&"object"==typeof e?("string"==typeof e.id&&e.id.trim()?i.has(e.id)?t.push(`${r}.id is duplicated: ${e.id}`):i.add(e.id):t.push(r+".id must be a non-empty string"),Array.isArray(e.fields)?e.fields.forEach((e,i)=>{e&&"object"==typeof e&&"string"==typeof e.name&&e.name.trim()||t.push(`${r}.fields[${i}].name must be a non-empty string`)}):t.push(r+".fields must be an array")):t.push(r+" must be an object")})}else t.push("entities must be an array");void 0===e.relations||Array.isArray(e.relations)?(e.relations||[]).forEach((e,i)=>{const o=`relations[${i}]`;e&&"object"==typeof e?("string"==typeof e.source&&e.source.trim()||t.push(o+".source must be a non-empty string"),"string"==typeof e.target&&e.target.trim()||t.push(o+".target must be a non-empty string")):t.push(o+" must be an object")}):t.push("relations must be an array");return{valid:0===t.length,errors:t}}(e)}function validateBpmnDsl(e){const t=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&t.push("Unsupported schemaVersion: "+e.schemaVersion);const i=new Set,d=new Map;return Array.isArray(e.nodes)?(e.nodes.forEach((e,l)=>{const p=`nodes[${l}]`;if(!e||"object"!=typeof e)return void t.push(p+" must be an object");"string"==typeof e.id&&e.id.trim()?i.has(e.id)?t.push(`${p}.id is duplicated: ${e.id}`):(i.add(e.id),d.set(e.id,e.kind||"task")):t.push(p+".id must be a non-empty string"),void 0!==e.kind&&-1===o.indexOf(e.kind)&&t.push(`${p}.kind must be one of ${o.join("/")}`),["left","top","width","height"].forEach(i=>{const o=e[i];void 0!==o&&"number"!=typeof o&&t.push(`${p}.${i} must be a number when present`)});[["eventKind",r],["trigger",n],["gatewayType",s],["taskType",a]].forEach(([i,o])=>{const r=e[i];void 0!==r&&-1===o.indexOf(r)&&t.push(`${p}.${i} must be one of ${o.join("/")}`)})}),e.nodes.forEach((e,o)=>{if(!e||"object"!=typeof e||void 0===e.parent)return;const r=`nodes[${o}]`;if("string"!=typeof e.parent||!e.parent.trim())return void t.push(r+".parent must be a non-empty string when present");if(!i.has(e.parent))return void t.push(r+".parent must reference an existing node id");if(e.parent===e.id)return void t.push(r+".parent must not reference itself");const n=d.get(e.parent);"pool"===e.kind?t.push(r+".parent is not allowed on a pool (池是最外层容器)"):"lane"===e.kind&&"pool"!==n?t.push(r+".parent must reference a pool"):"pool"!==n&&"lane"!==n&&t.push(r+".parent must reference a pool or a lane")})):t.push("nodes must be an array"),void 0===e.edges||Array.isArray(e.edges)?(e.edges||[]).forEach((e,o)=>{const r=`edges[${o}]`;if(!e||"object"!=typeof e)return void t.push(r+" must be an object");"string"==typeof e.source&&e.source.trim()&&i.has(e.source)||t.push(r+".source must reference an existing node id"),"string"==typeof e.target&&e.target.trim()&&i.has(e.target)||t.push(r+".target must reference an existing node id");const n=void 0!==e.type?e.type:e.flowType;void 0!==n&&-1===l.indexOf(n)&&t.push(`${r}.type must be one of ${l.join("/")}`),void 0!==e.label&&"string"!=typeof e.label&&t.push(r+".label must be a string when present"),void 0!==e.condition&&"string"!=typeof e.condition&&t.push(r+".condition must be a string when present"),void 0!==e.linkShape&&"visio"!==e.linkShape&&"bezier"!==e.linkShape&&t.push(r+'.linkShape must be "visio" or "bezier" when present')}):t.push("edges must be an array when present"),{valid:0===t.length,errors:t}}function validateFlowDsl(e){const o=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&o.push("Unsupported schemaVersion: "+e.schemaVersion);const r=new Set;return Array.isArray(e.nodes)?e.nodes.forEach((e,i)=>{const n=`nodes[${i}]`;e&&"object"==typeof e?("string"==typeof e.id&&e.id.trim()?r.has(e.id)?o.push(`${n}.id is duplicated: ${e.id}`):r.add(e.id):o.push(n+".id must be a non-empty string"),void 0!==e.kind&&-1===t.indexOf(e.kind)&&o.push(`${n}.kind must be one of ${t.join("/")}`),["left","top","width","height"].forEach(t=>{const i=e[t];void 0!==i&&"number"!=typeof i&&o.push(`${n}.${t} must be a number when present`)})):o.push(n+" must be an object")}):o.push("nodes must be an array"),void 0===e.edges||Array.isArray(e.edges)?(e.edges||[]).forEach((e,t)=>{const n=`edges[${t}]`;e&&"object"==typeof e?("string"==typeof e.source&&e.source.trim()&&r.has(e.source)||o.push(n+".source must reference an existing node id"),"string"==typeof e.target&&e.target.trim()&&r.has(e.target)||o.push(n+".target must reference an existing node id"),void 0!==e.label&&"string"!=typeof e.label&&o.push(n+".label must be a string when present"),void 0!==e.sourcePort&&-1===i.indexOf(e.sourcePort)&&o.push(`${n}.sourcePort must be one of ${i.join("/")}`),void 0!==e.targetPort&&-1===i.indexOf(e.targetPort)&&o.push(`${n}.targetPort must be one of ${i.join("/")}`),void 0!==e.linkShape&&"visio"!==e.linkShape&&"bezier"!==e.linkShape&&o.push(n+'.linkShape must be "visio" or "bezier" when present')):o.push(n+" must be an object")}):o.push("edges must be an array when present"),{valid:0===o.length,errors:o}}function validateUmlDsl(e){const t=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&t.push("Unsupported schemaVersion: "+e.schemaVersion);const i=new Set;return Array.isArray(e.nodes)?e.nodes.forEach((e,o)=>{const r=`nodes[${o}]`;e&&"object"==typeof e?("string"==typeof e.id&&e.id.trim()?i.has(e.id)?t.push(`${r}.id is duplicated: ${e.id}`):i.add(e.id):t.push(r+".id must be a non-empty string"),void 0!==e.kind&&-1===d.indexOf(e.kind)&&t.push(`${r}.kind must be one of ${d.join("/")}`),["attributes","methods"].forEach(i=>{const o=e[i];void 0!==o&&(Array.isArray(o)&&!o.some(e=>"string"!=typeof e)||t.push(`${r}.${i} must be an array of strings when present`))}),["left","top","width","height"].forEach(i=>{const o=e[i];void 0!==o&&"number"!=typeof o&&t.push(`${r}.${i} must be a number when present`)})):t.push(r+" must be an object")}):t.push("nodes must be an array"),void 0===e.edges||Array.isArray(e.edges)?(e.edges||[]).forEach((e,o)=>{const r=`edges[${o}]`;if(!e||"object"!=typeof e)return void t.push(r+" must be an object");"string"==typeof e.source&&e.source.trim()&&i.has(e.source)||t.push(r+".source must reference an existing node id"),"string"==typeof e.target&&e.target.trim()&&i.has(e.target)||t.push(r+".target must reference an existing node id");const n=void 0!==e.type?e.type:e.relation;void 0!==n&&-1===p.indexOf(n)&&t.push(`${r}.type must be one of ${p.join("/")}`),void 0!==e.label&&"string"!=typeof e.label&&t.push(r+".label must be a string when present")}):t.push("edges must be an array when present"),{valid:0===t.length,errors:t}}function entityName(e){return e.entityName||e.name||e.id}function relationType(e){return e.relationType||e.type||"one-to-many"}function compileDsl(e){if(isFlowDsl(e))throw new Error("compileDsl() 只处理 ER 文档;流程图文档请使用 compileFlowDsl()");if(!e||!Array.isArray(e.entities))throw new Error("ER 文档必须包含 entities 数组");return{entities:e.entities.map(e=>({id:e.id,entityName:entityName(e),fields:e.fields||[],left:e.left,top:e.top,width:e.width,height:e.height,style:e.style,headerStyle:e.headerStyle,fieldStyle:e.fieldStyle,dividerStyle:e.dividerStyle,draggable:e.draggable,interactive:e.interactive})),relations:(e.relations||[]).map((e,t)=>({id:e.id||"relation-"+t,relationType:relationType(e),sourceId:e.source,targetId:e.target,sourceField:e.sourceField||"id",targetField:e.targetField||"id",nullable:e.nullable,onDelete:e.onDelete,onUpdate:e.onUpdate,joinTableName:e.joinTableName,fromKey:e.fromKey,toKey:e.toKey,sourceCardinality:e.sourceCardinality,targetCardinality:e.targetCardinality,label:e.label,style:e.style,arrow:e.arrow,linkShape:e.linkShape,routeType:e.routeType,routeOffset:e.routeOffset,curveType:e.curveType,lineDash:e.lineDash})),layout:e.layout,options:e.options}}function layeredLayout(e,t,i={}){const o=Number(i.gapX)||90,r=Number(i.gapY)||90,n=void 0===i.originX?80:i.originX,s=void 0===i.originY?80:i.originY,a=new Map;if(!e.length)return a;const l=new Map;e.forEach(e=>l.set(e.id,e));const d=new Map,p=new Map;e.forEach(e=>{d.set(e.id,0),p.set(e.id,[])}),t.forEach(e=>{l.has(e.sourceId)&&l.has(e.targetId)&&(d.set(e.targetId,(d.get(e.targetId)||0)+1),p.get(e.sourceId).push(e.targetId))});const h=new Map,c=[];e.forEach(e=>{0===(d.get(e.id)||0)&&(h.set(e.id,0),c.push(e.id))}),c.length||(h.set(e[0].id,0),c.push(e[0].id));let u=e.length*e.length+e.length;for(;c.length&&u-- >0;){const e=c.shift(),t=h.get(e)||0;(p.get(e)||[]).forEach(e=>{const i=t+1;(void 0===h.get(e)?-1:h.get(e))<i&&(h.set(e,i),c.push(e))})}e.forEach(e=>{h.has(e.id)||h.set(e.id,0)});const m=new Map;e.forEach(e=>{const t=h.get(e.id)||0;m.has(t)||m.set(t,[]),m.get(t).push(e)});const f=[...m.keys()].sort((e,t)=>e-t);if("horizontal"===i.direction){const e=f.map(e=>Math.max(...m.get(e).map(e=>e.width)));let t=0;f.forEach((i,n)=>{const s=m.get(i);let l=-(s.reduce((e,t)=>e+t.height,0)+Math.max(s.length-1,0)*r)/2;s.forEach(i=>{a.set(i.id,{left:Math.round(t+(e[n]-i.width)/2),top:Math.round(l)}),l+=i.height+r}),t+=e[n]+o})}else{const e=f.map(e=>Math.max(...m.get(e).map(e=>e.height)));let t=0;f.forEach((i,n)=>{const s=m.get(i);let l=-(s.reduce((e,t)=>e+t.width,0)+Math.max(s.length-1,0)*o)/2;s.forEach(i=>{a.set(i.id,{left:Math.round(l),top:Math.round(t+(e[n]-i.height)/2)}),l+=i.width+o}),t+=e[n]+r})}const g=Math.min(...e.map(e=>a.get(e.id).left)),y=Math.min(...e.map(e=>a.get(e.id).top));return a.forEach(e=>{e.left+=n-g,e.top+=s-y}),a}const h={terminator:{width:e.FLOW_NODE_KINDS.terminator.width,height:e.FLOW_NODE_KINDS.terminator.height,fill:e.FLOW_NODE_KINDS.terminator.fill,stroke:e.FLOW_NODE_KINDS.terminator.stroke},process:{width:e.FLOW_NODE_KINDS.process.width,height:e.FLOW_NODE_KINDS.process.height,fill:e.FLOW_NODE_KINDS.process.fill,stroke:e.FLOW_NODE_KINDS.process.stroke},decision:{width:e.FLOW_NODE_KINDS.decision.width,height:e.FLOW_NODE_KINDS.decision.height,fill:e.FLOW_NODE_KINDS.decision.fill,stroke:e.FLOW_NODE_KINDS.decision.stroke},io:{width:e.FLOW_NODE_KINDS.io.width,height:e.FLOW_NODE_KINDS.io.height,fill:e.FLOW_NODE_KINDS.io.fill,stroke:e.FLOW_NODE_KINDS.io.stroke}};function compileFlowDsl(e){const t=e.options||{},i=(e.nodes||[]).map(e=>{const t=function nodeKind$1(e){return e.kind&&h[e.kind]?e.kind:"process"}(e),i=h[t];return{id:e.id,typeId:"FlowNode",kind:t,title:(o=e,o.title||o.name||o.id),left:"number"==typeof e.left?e.left:Number.NaN,top:"number"==typeof e.top?e.top:Number.NaN,width:"number"==typeof e.width?e.width:i.width,height:"number"==typeof e.height?e.height:i.height,fillColor:e.fillColor||i.fill,strokeColor:e.strokeColor||i.stroke};var o}),o=(e.edges||[]).map((e,t)=>({id:e.id||"edge-"+t,sourceId:e.source,targetId:e.target,sourcePort:e.sourcePort||"B",targetPort:e.targetPort||"T",label:e.label||"",linkShape:e.linkShape||"visio"})),r=t.layout||"layered";return"none"!==r&&i.some(e=>Number.isNaN(e.left)||Number.isNaN(e.top))&&(i.forEach(e=>{Number.isNaN(e.left)&&(e.left=0),Number.isNaN(e.top)&&(e.top=0)}),function autoLayout(e,t,i,o){const r=layeredLayout(e,t,{gapX:i,gapY:o});e.forEach(e=>{const t=r.get(e.id);t&&(e.left=t.left,e.top=t.top)})}(i,o,Number(t.gapX)||90,Number(t.gapY)||90)),i.forEach(e=>{Number.isNaN(e.left)&&(e.left=0),Number.isNaN(e.top)&&(e.top=0)}),{kind:"flowchart",nodes:i,edges:o,layout:r,options:t}}const c={pool:"bpmnPool",lane:"bpmnLane",task:"bpmnTask",event:"bpmnEvent",gateway:"bpmnGateway",subprocess:"bpmnSubprocess",dataObject:"bpmnDataObject",annotation:"bpmnAnnotation"},u=Number(e.FLOW_NODE_KINDS.bpmnPool.bandSize)||32,m=Number(e.FLOW_NODE_KINDS.bpmnLane.bandSize)||32,f=Number(e.FLOW_NODE_KINDS.bpmnLane.height)||130,g=Number(e.FLOW_NODE_KINDS.bpmnPool.width)||900;function toWorkingNode(t){const i=t.kind||"task",o=function presetOf(t){return e.FLOW_NODE_KINDS[t]||e.FLOW_NODE_KINDS.bpmnTask}(c[i]||"bpmnTask"),r={id:t.id,typeId:"FlowNode",kind:c[i]||"bpmnTask",title:t.title||t.name||t.id,left:"number"==typeof t.left?t.left:0,top:"number"==typeof t.top?t.top:0,width:"number"==typeof t.width?t.width:o.width,height:"number"==typeof t.height?t.height:o.height,fillColor:t.fillColor,strokeColor:t.strokeColor,dslKind:i,parent:t.parent,explicitLeft:"number"==typeof t.left,explicitTop:"number"==typeof t.top,explicitWidth:"number"==typeof t.width,explicitHeight:"number"==typeof t.height};return"event"===i&&(r.eventKind=t.eventKind||o.eventKind||"start",r.trigger=t.trigger||o.trigger||"none"),"gateway"===i&&(r.gatewayType=t.gatewayType||o.gatewayType||"exclusive"),"task"!==i&&"subprocess"!==i||(r.taskType=t.taskType||o.taskType||"none"),r}function buildGroups(e,t){const i=new Map;t.forEach(e=>i.set(e.id,e));const o=1===t.length?t[0]:null,r=[];return e.forEach(e=>{(e=>{let t=r.filter(t=>t.owner===e)[0];return t||(t={owner:e,nodes:[],box:null,didLayout:!1},r.push(t)),t})((e.parent?i.get(e.parent):void 0)||o).nodes.push(e)}),r}function layoutGroups(e,t,i,o){e.forEach(e=>{if(e.nodes.some(e=>!e.explicitLeft||!e.explicitTop)){const r=layeredLayout(e.nodes,t,{gapX:i,gapY:o,originX:0,originY:0,direction:"horizontal"});e.nodes.forEach(e=>{const t=r.get(e.id);t&&(e.left=t.left,e.top=t.top)}),e.didLayout=!0}e.box=function unionBox(e){if(!e.length)return null;let t=1/0,i=1/0,o=-1/0,r=-1/0;return e.forEach(e=>{t=Math.min(t,e.left),i=Math.min(i,e.top),o=Math.max(o,e.left+e.width),r=Math.max(r,e.top+e.height)}),{minX:t,minY:i,maxX:o,maxY:r}}(e.nodes)})}function compileBpmnDsl(e){const t=e.options||{},i=(e.nodes||[]).map(toWorkingNode),o=i.filter(e=>"pool"===e.dslKind),r=i.filter(e=>"lane"===e.dslKind),n=i.filter(e=>!function isContainer(e){return"pool"===e.dslKind||"lane"===e.dslKind}(e)),s=(e.edges||[]).map((e,t)=>({id:e.id||"edge-"+t,sourceId:e.source,targetId:e.target,flowType:e.type||e.flowType||"sequence",label:e.label||"",condition:e.condition||"",isDefault:!!e.isDefault,linkShape:e.linkShape||"visio"})),a=t.layout||"auto",l=function resolveLaneOwners(e,t){const i=new Map;return e.forEach(e=>{let o=e.parent;o||1!==t.length||(o=t[0].id),o&&i.set(e.id,o)}),i}(r,o),lanesOf=e=>r.filter(t=>l.get(t.id)===e);let d=[];"none"!==a&&(d=buildGroups(n,o.concat(r)),layoutGroups(d,s,Number(t.gapX)||90,Number(t.gapY)||60)),r.forEach(e=>{const t=d.filter(t=>t.owner===e)[0],i=t?t.box:null;e.explicitHeight||(e.height=Math.round(Math.max(56+(i?i.maxY-i.minY:0),f))),e.explicitWidth||(e.width=Math.round(Math.max((i?i.maxX-i.minX:0)+m+56,g)))}),o.forEach(e=>{const t=lanesOf(e.id);if(t.length){const i=t.reduce((e,t)=>Math.max(e,t.width),g);return e.explicitWidth||(e.width=i),e.explicitWidth&&t.forEach(t=>{t.explicitWidth||(t.width=e.width)}),void(e.explicitHeight||(e.height=u+t.reduce((e,t)=>e+t.height,0)))}const i=d.filter(t=>t.owner===e)[0],o=i?i.box:null;e.explicitWidth||(e.width=Math.round(Math.max(56+(o?o.maxX-o.minX:0),g))),e.explicitHeight||(e.height=Math.round(Math.max((o?o.maxY-o.minY:0)+u+56,160)))});let p=60;o.forEach(e=>{e.explicitLeft||(e.left=60),e.explicitTop||(e.top=p),p=Math.max(p,e.top+e.height+60)}),o.forEach(e=>{const t=lanesOf(e.id);if(!t.length)return;const i=e.top+u,o=Math.max(e.height-u,1),r=t.reduce((e,t)=>e+(t.explicitHeight?t.height:0),0),n=t.filter(e=>!e.explicitHeight),s=n.length?Math.max(o-r,0)/n.length:0;let a=i;t.forEach(t=>{t.explicitLeft||(t.left=e.left),t.explicitTop||(t.top=a),!t.explicitHeight&&e.explicitHeight&&(t.height=Math.round(s||f)),a=t.top+t.height})});let h=60;r.forEach(e=>{l.get(e.id)||(e.explicitLeft||(e.left=60),e.explicitTop||(e.top=h,h=e.top+e.height+60))}),d.forEach(e=>{const t=e.box;if(!t||!e.didLayout)return;const i=e.owner;let o=80,r=80;i&&(o=i.left+28,r=i.top+28,"pool"===i.dslKind?r+=u:o+=m),e.nodes.forEach(e=>{e.left=Math.round(o+(e.left-t.minX)),e.top=Math.round(r+(e.top-t.minY))})});return{kind:"bpmn",nodes:o.concat(r).concat(n).map(e=>{const t={id:e.id,typeId:"FlowNode",kind:e.kind,title:e.title,left:e.left,top:e.top,width:e.width,height:e.height};return void 0!==e.eventKind&&(t.eventKind=e.eventKind),void 0!==e.trigger&&(t.trigger=e.trigger),void 0!==e.gatewayType&&(t.gatewayType=e.gatewayType),void 0!==e.taskType&&(t.taskType=e.taskType),void 0!==e.fillColor&&(t.fillColor=e.fillColor),void 0!==e.strokeColor&&(t.strokeColor=e.strokeColor),t}),edges:s,layout:a,options:t}}function compileUmlDsl(e){const t=e.options||{},i=(e.nodes||[]).map(e=>{return{id:e.id,kind:(t=e,t.kind||"class"),className:e.title||e.name||e.id,abstract:!!e.abstract,attributes:Array.isArray(e.attributes)?e.attributes.map(e=>String(e)):[],methods:Array.isArray(e.methods)?e.methods.map(e=>String(e)):[],left:"number"==typeof e.left?e.left:Number.NaN,top:"number"==typeof e.top?e.top:Number.NaN,width:"number"==typeof e.width?e.width:240,height:"number"==typeof e.height?e.height:120+24*(e.attributes?e.attributes.length:0)+24*(e.methods?e.methods.length:0)};var t}),o=(e.edges||[]).map((e,t)=>({id:e.id||"relation-"+t,sourceId:e.source,targetId:e.target,relationKind:e.type||e.relation||"association",label:e.label||""})),r=t.layout||"layered";if("none"!==r&&i.some(e=>Number.isNaN(e.left)||Number.isNaN(e.top))){i.forEach(e=>{Number.isNaN(e.left)&&(e.left=0),Number.isNaN(e.top)&&(e.top=0)});const e=layeredLayout(i,o.filter(e=>"inheritance"===e.relationKind||"realization"===e.relationKind).map(e=>({sourceId:e.targetId,targetId:e.sourceId})),{gapX:Number(t.gapX)||80,gapY:Number(t.gapY)||110,originX:80,originY:80,direction:"vertical"});i.forEach(t=>{const i=e.get(t.id);i&&(t.left=i.left,t.top=i.top)})}return i.forEach(e=>{Number.isNaN(e.left)&&(e.left=0),Number.isNaN(e.top)&&(e.top=0)}),{kind:"uml",nodes:i,edges:o,layout:r,options:t}}function renderUmlDsl(t,i){const o=compileUmlDsl(i),r=o.options||{},n=(new e.ICE).init(t),s=new e.UmlDesigner(n);return o.nodes.forEach(e=>{s.createClass({id:e.id,kind:e.kind,className:e.className,abstract:e.abstract,attributes:e.attributes,methods:e.methods,left:e.left,top:e.top,width:e.width})}),o.edges.forEach(e=>{s.createRelation(e)}),s.select(null),r.viewport?n.setViewport(r.viewport.scale,r.viewport.tx,r.viewport.ty):!1!==r.fitViewport&&s.fitViewport(r.fitViewportPadding),s.resetHistory(),{kind:"uml",ice:n,designer:s}}function renderBpmnDsl(t,i){const o=compileBpmnDsl(i),r=o.options||{},n=(new e.ICE).init(t),s=new e.BpmnDesigner(n);return o.nodes.forEach(e=>{const t={id:e.id,title:e.title,left:e.left,top:e.top,width:e.width,height:e.height};["eventKind","trigger","gatewayType","taskType","fillColor","strokeColor"].forEach(i=>{void 0!==e[i]&&(t[i]=e[i])}),s.createNode(e.kind,t)}),o.edges.forEach(e=>{s.createEdge(e)}),s.select(null),r.viewport?n.setViewport(r.viewport.scale,r.viewport.tx,r.viewport.ty):!1!==r.fitViewport&&s.fitViewport(r.fitViewportPadding),s.resetHistory(),{kind:"bpmn",ice:n,designer:s}}function renderFlowDsl(t,i){const o=compileFlowDsl(i),r=o.options||{},n=(new e.ICE).init(t),s=new e.FlowDesigner(n);return o.nodes.forEach(e=>{s.createNode(e.kind,e)}),o.edges.forEach(e=>{s.createEdge(e)}),s.select(null),r.viewport?n.setViewport(r.viewport.scale,r.viewport.tx,r.viewport.ty):!1!==r.fitViewport&&s.fitViewport(r.fitViewportPadding),s.resetHistory(),{kind:"flowchart",ice:n,designer:s}}exports.DSL_SCHEMA_VERSION=1,exports.compileBpmnDsl=compileBpmnDsl,exports.compileDsl=compileDsl,exports.compileFlowDsl=compileFlowDsl,exports.compileUmlDsl=compileUmlDsl,exports.isBpmnDsl=isBpmnDsl,exports.isFlowDsl=isFlowDsl,exports.isUmlDsl=isUmlDsl,exports.layeredLayout=layeredLayout,exports.renderBpmnDsl=renderBpmnDsl,exports.renderDsl=function renderDsl(t,i){const o=validateDsl(i);if(!o.valid)throw new Error(o.errors.join("\n"));return isUmlDsl(i)?renderUmlDsl(t,i):isBpmnDsl(i)?renderBpmnDsl(t,i):isFlowDsl(i)?renderFlowDsl(t,i):function renderErDsl(t,i){const o=compileDsl(i),r=o.options||{},n=(new e.ICE).init(t),s=new e.EntityDesigner(n);o.entities.forEach(e=>{s.createEntity(e)}),function positionLinks(e,t,i){const o=new Map;return e.entities.forEach(e=>{o.set(e.state.id,e.getMinBoundingBox(!0))}),t.relations.map(e=>{const t=o.get(e.sourceId),r=o.get(e.targetId);let n="R",s="L";if(t&&r){const e=r.center[0]-t.center[0],i=r.center[1]-t.center[1];Math.abs(e)>Math.abs(i)?(n=e>=0?"R":"L",s=e>=0?"L":"R"):(n=i>=0?"B":"T",s=i>=0?"T":"B")}return{...e,routeType:e.routeType||i||"orthogonal",linkShape:e.linkShape||"visio",links:{start:{id:e.sourceId,position:n},end:{id:e.targetId,position:s}}}})}(s,o,r.routeType).forEach(e=>{s.createRelation(e)}),("layered"===o.layout||"horizontal"===o.layout)&&new e.ICELayeredLayout({gapX:r.gapX||120,gapY:r.gapY||50}).layoutContainer(n);r.viewport?n.setViewport(r.viewport.scale,r.viewport.tx,r.viewport.ty):r.fitViewport&&function fitViewport(e,t,i){const o=t.entities||[];let r=1/0,n=1/0,s=-1/0,a=-1/0;o.forEach(e=>{const t=e.getMinBoundingBox(!0).getMinAndMaxPoint();r=Math.min(r,t.minX),n=Math.min(n,t.minY),s=Math.max(s,t.maxX),a=Math.max(a,t.maxY)});const l=s-r,d=a-n,p=e.canvasWidth||0,h=e.canvasHeight||0;if(!p||!h||l<=0||d<=0)return;const c=Number.isFinite(i)&&i>=0?i:40,u=Math.max(1,p-2*c),m=Math.max(1,h-2*c),f=Math.min(u/l,m/d,1),g=(p-l*f)/2-r*f,y=(h-d*f)/2-n*f;e.setViewport(f,g,y)}(n,s,r.fitViewportPadding);return{kind:"entity",ice:n,designer:s}}(t,i)},exports.renderFlowDsl=renderFlowDsl,exports.renderUmlDsl=renderUmlDsl,exports.validateBpmnDsl=validateBpmnDsl,exports.validateDsl=validateDsl,exports.validateFlowDsl=validateFlowDsl,exports.validateUmlDsl=validateUmlDsl;
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{FLOW_NODE_KINDS as e,ICE as t,BpmnDesigner as i,FlowDesigner as o,EntityDesigner as n,ICELayeredLayout as r}from"ice-entity-designer";function isFlowDsl(e){return!!e&&"object"==typeof e&&"flowchart"===e.kind}function isBpmnDsl(e){return!!e&&"object"==typeof e&&"bpmn"===e.kind}const s=1,a=["terminator","process","decision","io"],l=["T","R","B","L","C"],d=["pool","lane","task","event","gateway","subprocess","dataObject","annotation"],p=["start","intermediate","end"],h=["none","message","timer","error","terminate"],c=["exclusive","parallel","inclusive","event"],u=["none","user","service","script","send","receive","manual"],f=["sequence","message","association"];function validateDsl(e){return isBpmnDsl(e)?validateBpmnDsl(e):isFlowDsl(e)?validateFlowDsl(e):function validateErDsl(e){const t=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&t.push("Unsupported schemaVersion: "+e.schemaVersion);if(Array.isArray(e.entities)){const i=new Set;e.entities.forEach((e,o)=>{const n=`entities[${o}]`;e&&"object"==typeof e?("string"==typeof e.id&&e.id.trim()?i.has(e.id)?t.push(`${n}.id is duplicated: ${e.id}`):i.add(e.id):t.push(n+".id must be a non-empty string"),Array.isArray(e.fields)?e.fields.forEach((e,i)=>{e&&"object"==typeof e&&"string"==typeof e.name&&e.name.trim()||t.push(`${n}.fields[${i}].name must be a non-empty string`)}):t.push(n+".fields must be an array")):t.push(n+" must be an object")})}else t.push("entities must be an array");void 0===e.relations||Array.isArray(e.relations)?(e.relations||[]).forEach((e,i)=>{const o=`relations[${i}]`;e&&"object"==typeof e?("string"==typeof e.source&&e.source.trim()||t.push(o+".source must be a non-empty string"),"string"==typeof e.target&&e.target.trim()||t.push(o+".target must be a non-empty string")):t.push(o+" must be an object")}):t.push("relations must be an array");return{valid:0===t.length,errors:t}}(e)}function validateBpmnDsl(e){const t=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&t.push("Unsupported schemaVersion: "+e.schemaVersion);const i=new Set,o=new Map;return Array.isArray(e.nodes)?(e.nodes.forEach((e,n)=>{const r=`nodes[${n}]`;if(!e||"object"!=typeof e)return void t.push(r+" must be an object");"string"==typeof e.id&&e.id.trim()?i.has(e.id)?t.push(`${r}.id is duplicated: ${e.id}`):(i.add(e.id),o.set(e.id,e.kind||"task")):t.push(r+".id must be a non-empty string"),void 0!==e.kind&&-1===d.indexOf(e.kind)&&t.push(`${r}.kind must be one of ${d.join("/")}`),["left","top","width","height"].forEach(i=>{const o=e[i];void 0!==o&&"number"!=typeof o&&t.push(`${r}.${i} must be a number when present`)});[["eventKind",p],["trigger",h],["gatewayType",c],["taskType",u]].forEach(([i,o])=>{const n=e[i];void 0!==n&&-1===o.indexOf(n)&&t.push(`${r}.${i} must be one of ${o.join("/")}`)})}),e.nodes.forEach((e,n)=>{if(!e||"object"!=typeof e||void 0===e.parent)return;const r=`nodes[${n}]`;if("string"!=typeof e.parent||!e.parent.trim())return void t.push(r+".parent must be a non-empty string when present");if(!i.has(e.parent))return void t.push(r+".parent must reference an existing node id");if(e.parent===e.id)return void t.push(r+".parent must not reference itself");const s=o.get(e.parent);"pool"===e.kind?t.push(r+".parent is not allowed on a pool (池是最外层容器)"):"lane"===e.kind&&"pool"!==s?t.push(r+".parent must reference a pool"):"pool"!==s&&"lane"!==s&&t.push(r+".parent must reference a pool or a lane")})):t.push("nodes must be an array"),void 0===e.edges||Array.isArray(e.edges)?(e.edges||[]).forEach((e,o)=>{const n=`edges[${o}]`;if(!e||"object"!=typeof e)return void t.push(n+" must be an object");"string"==typeof e.source&&e.source.trim()&&i.has(e.source)||t.push(n+".source must reference an existing node id"),"string"==typeof e.target&&e.target.trim()&&i.has(e.target)||t.push(n+".target must reference an existing node id");const r=void 0!==e.type?e.type:e.flowType;void 0!==r&&-1===f.indexOf(r)&&t.push(`${n}.type must be one of ${f.join("/")}`),void 0!==e.label&&"string"!=typeof e.label&&t.push(n+".label must be a string when present"),void 0!==e.condition&&"string"!=typeof e.condition&&t.push(n+".condition must be a string when present"),void 0!==e.linkShape&&"visio"!==e.linkShape&&"bezier"!==e.linkShape&&t.push(n+'.linkShape must be "visio" or "bezier" when present')}):t.push("edges must be an array when present"),{valid:0===t.length,errors:t}}function validateFlowDsl(e){const t=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&t.push("Unsupported schemaVersion: "+e.schemaVersion);const i=new Set;return Array.isArray(e.nodes)?e.nodes.forEach((e,o)=>{const n=`nodes[${o}]`;e&&"object"==typeof e?("string"==typeof e.id&&e.id.trim()?i.has(e.id)?t.push(`${n}.id is duplicated: ${e.id}`):i.add(e.id):t.push(n+".id must be a non-empty string"),void 0!==e.kind&&-1===a.indexOf(e.kind)&&t.push(`${n}.kind must be one of ${a.join("/")}`),["left","top","width","height"].forEach(i=>{const o=e[i];void 0!==o&&"number"!=typeof o&&t.push(`${n}.${i} must be a number when present`)})):t.push(n+" must be an object")}):t.push("nodes must be an array"),void 0===e.edges||Array.isArray(e.edges)?(e.edges||[]).forEach((e,o)=>{const n=`edges[${o}]`;e&&"object"==typeof e?("string"==typeof e.source&&e.source.trim()&&i.has(e.source)||t.push(n+".source must reference an existing node id"),"string"==typeof e.target&&e.target.trim()&&i.has(e.target)||t.push(n+".target must reference an existing node id"),void 0!==e.label&&"string"!=typeof e.label&&t.push(n+".label must be a string when present"),void 0!==e.sourcePort&&-1===l.indexOf(e.sourcePort)&&t.push(`${n}.sourcePort must be one of ${l.join("/")}`),void 0!==e.targetPort&&-1===l.indexOf(e.targetPort)&&t.push(`${n}.targetPort must be one of ${l.join("/")}`),void 0!==e.linkShape&&"visio"!==e.linkShape&&"bezier"!==e.linkShape&&t.push(n+'.linkShape must be "visio" or "bezier" when present')):t.push(n+" must be an object")}):t.push("edges must be an array when present"),{valid:0===t.length,errors:t}}function entityName(e){return e.entityName||e.name||e.id}function relationType(e){return e.relationType||e.type||"one-to-many"}function compileDsl(e){if(isFlowDsl(e))throw new Error("compileDsl() 只处理 ER 文档;流程图文档请使用 compileFlowDsl()");if(!e||!Array.isArray(e.entities))throw new Error("ER 文档必须包含 entities 数组");return{entities:e.entities.map(e=>({id:e.id,entityName:entityName(e),fields:e.fields||[],left:e.left,top:e.top,width:e.width,height:e.height,style:e.style,headerStyle:e.headerStyle,fieldStyle:e.fieldStyle,dividerStyle:e.dividerStyle,draggable:e.draggable,interactive:e.interactive})),relations:(e.relations||[]).map((e,t)=>({id:e.id||"relation-"+t,relationType:relationType(e),sourceId:e.source,targetId:e.target,sourceField:e.sourceField||"id",targetField:e.targetField||"id",nullable:e.nullable,onDelete:e.onDelete,onUpdate:e.onUpdate,joinTableName:e.joinTableName,fromKey:e.fromKey,toKey:e.toKey,sourceCardinality:e.sourceCardinality,targetCardinality:e.targetCardinality,label:e.label,style:e.style,arrow:e.arrow,linkShape:e.linkShape,routeType:e.routeType,routeOffset:e.routeOffset,curveType:e.curveType,lineDash:e.lineDash})),layout:e.layout,options:e.options}}function layeredLayout(e,t,i={}){const o=Number(i.gapX)||90,n=Number(i.gapY)||90,r=void 0===i.originX?80:i.originX,s=void 0===i.originY?80:i.originY,a=new Map;if(!e.length)return a;const l=new Map;e.forEach(e=>l.set(e.id,e));const d=new Map,p=new Map;e.forEach(e=>{d.set(e.id,0),p.set(e.id,[])}),t.forEach(e=>{l.has(e.sourceId)&&l.has(e.targetId)&&(d.set(e.targetId,(d.get(e.targetId)||0)+1),p.get(e.sourceId).push(e.targetId))});const h=new Map,c=[];e.forEach(e=>{0===(d.get(e.id)||0)&&(h.set(e.id,0),c.push(e.id))}),c.length||(h.set(e[0].id,0),c.push(e[0].id));let u=e.length*e.length+e.length;for(;c.length&&u-- >0;){const e=c.shift(),t=h.get(e)||0;(p.get(e)||[]).forEach(e=>{const i=t+1;(void 0===h.get(e)?-1:h.get(e))<i&&(h.set(e,i),c.push(e))})}e.forEach(e=>{h.has(e.id)||h.set(e.id,0)});const f=new Map;e.forEach(e=>{const t=h.get(e.id)||0;f.has(t)||f.set(t,[]),f.get(t).push(e)});const g=[...f.keys()].sort((e,t)=>e-t);if("horizontal"===i.direction){const e=g.map(e=>Math.max(...f.get(e).map(e=>e.width)));let t=0;g.forEach((i,r)=>{const s=f.get(i);let l=-(s.reduce((e,t)=>e+t.height,0)+Math.max(s.length-1,0)*n)/2;s.forEach(i=>{a.set(i.id,{left:Math.round(t+(e[r]-i.width)/2),top:Math.round(l)}),l+=i.height+n}),t+=e[r]+o})}else{const e=g.map(e=>Math.max(...f.get(e).map(e=>e.height)));let t=0;g.forEach((i,r)=>{const s=f.get(i);let l=-(s.reduce((e,t)=>e+t.width,0)+Math.max(s.length-1,0)*o)/2;s.forEach(i=>{a.set(i.id,{left:Math.round(l),top:Math.round(t+(e[r]-i.height)/2)}),l+=i.width+o}),t+=e[r]+n})}const m=Math.min(...e.map(e=>a.get(e.id).left)),y=Math.min(...e.map(e=>a.get(e.id).top));return a.forEach(e=>{e.left+=r-m,e.top+=s-y}),a}const g={terminator:{width:e.terminator.width,height:e.terminator.height,fill:e.terminator.fill,stroke:e.terminator.stroke},process:{width:e.process.width,height:e.process.height,fill:e.process.fill,stroke:e.process.stroke},decision:{width:e.decision.width,height:e.decision.height,fill:e.decision.fill,stroke:e.decision.stroke},io:{width:e.io.width,height:e.io.height,fill:e.io.fill,stroke:e.io.stroke}};function compileFlowDsl(e){const t=e.options||{},i=(e.nodes||[]).map(e=>{const t=function nodeKind(e){return e.kind&&g[e.kind]?e.kind:"process"}(e),i=g[t];return{id:e.id,typeId:"FlowNode",kind:t,title:(o=e,o.title||o.name||o.id),left:"number"==typeof e.left?e.left:Number.NaN,top:"number"==typeof e.top?e.top:Number.NaN,width:"number"==typeof e.width?e.width:i.width,height:"number"==typeof e.height?e.height:i.height,fillColor:e.fillColor||i.fill,strokeColor:e.strokeColor||i.stroke};var o}),o=(e.edges||[]).map((e,t)=>({id:e.id||"edge-"+t,sourceId:e.source,targetId:e.target,sourcePort:e.sourcePort||"B",targetPort:e.targetPort||"T",label:e.label||"",linkShape:e.linkShape||"visio"})),n=t.layout||"layered";return"none"!==n&&i.some(e=>Number.isNaN(e.left)||Number.isNaN(e.top))&&(i.forEach(e=>{Number.isNaN(e.left)&&(e.left=0),Number.isNaN(e.top)&&(e.top=0)}),function autoLayout(e,t,i,o){const n=layeredLayout(e,t,{gapX:i,gapY:o});e.forEach(e=>{const t=n.get(e.id);t&&(e.left=t.left,e.top=t.top)})}(i,o,Number(t.gapX)||90,Number(t.gapY)||90)),i.forEach(e=>{Number.isNaN(e.left)&&(e.left=0),Number.isNaN(e.top)&&(e.top=0)}),{kind:"flowchart",nodes:i,edges:o,layout:n,options:t}}const m={pool:"bpmnPool",lane:"bpmnLane",task:"bpmnTask",event:"bpmnEvent",gateway:"bpmnGateway",subprocess:"bpmnSubprocess",dataObject:"bpmnDataObject",annotation:"bpmnAnnotation"},y=Number(e.bpmnPool.bandSize)||32,b=Number(e.bpmnLane.bandSize)||32,w=Number(e.bpmnLane.height)||130,v=Number(e.bpmnPool.width)||900;function toWorkingNode(t){const i=t.kind||"task",o=function presetOf(t){return e[t]||e.bpmnTask}(m[i]||"bpmnTask"),n={id:t.id,typeId:"FlowNode",kind:m[i]||"bpmnTask",title:t.title||t.name||t.id,left:"number"==typeof t.left?t.left:0,top:"number"==typeof t.top?t.top:0,width:"number"==typeof t.width?t.width:o.width,height:"number"==typeof t.height?t.height:o.height,fillColor:t.fillColor,strokeColor:t.strokeColor,dslKind:i,parent:t.parent,explicitLeft:"number"==typeof t.left,explicitTop:"number"==typeof t.top,explicitWidth:"number"==typeof t.width,explicitHeight:"number"==typeof t.height};return"event"===i&&(n.eventKind=t.eventKind||o.eventKind||"start",n.trigger=t.trigger||o.trigger||"none"),"gateway"===i&&(n.gatewayType=t.gatewayType||o.gatewayType||"exclusive"),"task"!==i&&"subprocess"!==i||(n.taskType=t.taskType||o.taskType||"none"),n}function buildGroups(e,t){const i=new Map;t.forEach(e=>i.set(e.id,e));const o=1===t.length?t[0]:null,n=[];return e.forEach(e=>{(e=>{let t=n.filter(t=>t.owner===e)[0];return t||(t={owner:e,nodes:[],box:null,didLayout:!1},n.push(t)),t})((e.parent?i.get(e.parent):void 0)||o).nodes.push(e)}),n}function layoutGroups(e,t,i,o){e.forEach(e=>{if(e.nodes.some(e=>!e.explicitLeft||!e.explicitTop)){const n=layeredLayout(e.nodes,t,{gapX:i,gapY:o,originX:0,originY:0,direction:"horizontal"});e.nodes.forEach(e=>{const t=n.get(e.id);t&&(e.left=t.left,e.top=t.top)}),e.didLayout=!0}e.box=function unionBox(e){if(!e.length)return null;let t=1/0,i=1/0,o=-1/0,n=-1/0;return e.forEach(e=>{t=Math.min(t,e.left),i=Math.min(i,e.top),o=Math.max(o,e.left+e.width),n=Math.max(n,e.top+e.height)}),{minX:t,minY:i,maxX:o,maxY:n}}(e.nodes)})}function compileBpmnDsl(e){const t=e.options||{},i=(e.nodes||[]).map(toWorkingNode),o=i.filter(e=>"pool"===e.dslKind),n=i.filter(e=>"lane"===e.dslKind),r=i.filter(e=>!function isContainer(e){return"pool"===e.dslKind||"lane"===e.dslKind}(e)),s=(e.edges||[]).map((e,t)=>({id:e.id||"edge-"+t,sourceId:e.source,targetId:e.target,flowType:e.type||e.flowType||"sequence",label:e.label||"",condition:e.condition||"",isDefault:!!e.isDefault,linkShape:e.linkShape||"visio"})),a=t.layout||"auto",l=function resolveLaneOwners(e,t){const i=new Map;return e.forEach(e=>{let o=e.parent;o||1!==t.length||(o=t[0].id),o&&i.set(e.id,o)}),i}(n,o),lanesOf=e=>n.filter(t=>l.get(t.id)===e);let d=[];"none"!==a&&(d=buildGroups(r,o.concat(n)),layoutGroups(d,s,Number(t.gapX)||90,Number(t.gapY)||60)),n.forEach(e=>{const t=d.filter(t=>t.owner===e)[0],i=t?t.box:null;e.explicitHeight||(e.height=Math.round(Math.max(56+(i?i.maxY-i.minY:0),w))),e.explicitWidth||(e.width=Math.round(Math.max((i?i.maxX-i.minX:0)+b+56,v)))}),o.forEach(e=>{const t=lanesOf(e.id);if(t.length){const i=t.reduce((e,t)=>Math.max(e,t.width),v);return e.explicitWidth||(e.width=i),e.explicitWidth&&t.forEach(t=>{t.explicitWidth||(t.width=e.width)}),void(e.explicitHeight||(e.height=y+t.reduce((e,t)=>e+t.height,0)))}const i=d.filter(t=>t.owner===e)[0],o=i?i.box:null;e.explicitWidth||(e.width=Math.round(Math.max(56+(o?o.maxX-o.minX:0),v))),e.explicitHeight||(e.height=Math.round(Math.max((o?o.maxY-o.minY:0)+y+56,160)))});let p=60;o.forEach(e=>{e.explicitLeft||(e.left=60),e.explicitTop||(e.top=p),p=Math.max(p,e.top+e.height+60)}),o.forEach(e=>{const t=lanesOf(e.id);if(!t.length)return;const i=e.top+y,o=Math.max(e.height-y,1),n=t.reduce((e,t)=>e+(t.explicitHeight?t.height:0),0),r=t.filter(e=>!e.explicitHeight),s=r.length?Math.max(o-n,0)/r.length:0;let a=i;t.forEach(t=>{t.explicitLeft||(t.left=e.left),t.explicitTop||(t.top=a),!t.explicitHeight&&e.explicitHeight&&(t.height=Math.round(s||w)),a=t.top+t.height})});let h=60;n.forEach(e=>{l.get(e.id)||(e.explicitLeft||(e.left=60),e.explicitTop||(e.top=h,h=e.top+e.height+60))}),d.forEach(e=>{const t=e.box;if(!t||!e.didLayout)return;const i=e.owner;let o=80,n=80;i&&(o=i.left+28,n=i.top+28,"pool"===i.dslKind?n+=y:o+=b),e.nodes.forEach(e=>{e.left=Math.round(o+(e.left-t.minX)),e.top=Math.round(n+(e.top-t.minY))})});return{kind:"bpmn",nodes:o.concat(n).concat(r).map(e=>{const t={id:e.id,typeId:"FlowNode",kind:e.kind,title:e.title,left:e.left,top:e.top,width:e.width,height:e.height};return void 0!==e.eventKind&&(t.eventKind=e.eventKind),void 0!==e.trigger&&(t.trigger=e.trigger),void 0!==e.gatewayType&&(t.gatewayType=e.gatewayType),void 0!==e.taskType&&(t.taskType=e.taskType),void 0!==e.fillColor&&(t.fillColor=e.fillColor),void 0!==e.strokeColor&&(t.strokeColor=e.strokeColor),t}),edges:s,layout:a,options:t}}function renderDsl(e,i){const o=validateDsl(i);if(!o.valid)throw new Error(o.errors.join("\n"));return isBpmnDsl(i)?renderBpmnDsl(e,i):isFlowDsl(i)?renderFlowDsl(e,i):function renderErDsl(e,i){const o=compileDsl(i),s=o.options||{},a=(new t).init(e),l=new n(a);o.entities.forEach(e=>{l.createEntity(e)}),function positionLinks(e,t,i){const o=new Map;return e.entities.forEach(e=>{o.set(e.state.id,e.getMinBoundingBox(!0))}),t.relations.map(e=>{const t=o.get(e.sourceId),n=o.get(e.targetId);let r="R",s="L";if(t&&n){const e=n.center[0]-t.center[0],i=n.center[1]-t.center[1];Math.abs(e)>Math.abs(i)?(r=e>=0?"R":"L",s=e>=0?"L":"R"):(r=i>=0?"B":"T",s=i>=0?"T":"B")}return{...e,routeType:e.routeType||i||"orthogonal",linkShape:e.linkShape||"visio",links:{start:{id:e.sourceId,position:r},end:{id:e.targetId,position:s}}}})}(l,o,s.routeType).forEach(e=>{l.createRelation(e)}),("layered"===o.layout||"horizontal"===o.layout)&&new r({gapX:s.gapX||120,gapY:s.gapY||50}).layoutContainer(a);s.viewport?a.setViewport(s.viewport.scale,s.viewport.tx,s.viewport.ty):s.fitViewport&&function fitViewport(e,t,i){const o=t.entities||[];let n=1/0,r=1/0,s=-1/0,a=-1/0;o.forEach(e=>{const t=e.getMinBoundingBox(!0).getMinAndMaxPoint();n=Math.min(n,t.minX),r=Math.min(r,t.minY),s=Math.max(s,t.maxX),a=Math.max(a,t.maxY)});const l=s-n,d=a-r,p=e.canvasWidth||0,h=e.canvasHeight||0;if(!p||!h||l<=0||d<=0)return;const c=Number.isFinite(i)&&i>=0?i:40,u=Math.max(1,p-2*c),f=Math.max(1,h-2*c),g=Math.min(u/l,f/d,1),m=(p-l*g)/2-n*g,y=(h-d*g)/2-r*g;e.setViewport(g,m,y)}(a,l,s.fitViewportPadding);return{kind:"entity",ice:a,designer:l}}(e,i)}function renderBpmnDsl(e,o){const n=compileBpmnDsl(o),r=n.options||{},s=(new t).init(e),a=new i(s);return n.nodes.forEach(e=>{const t={id:e.id,title:e.title,left:e.left,top:e.top,width:e.width,height:e.height};["eventKind","trigger","gatewayType","taskType","fillColor","strokeColor"].forEach(i=>{void 0!==e[i]&&(t[i]=e[i])}),a.createNode(e.kind,t)}),n.edges.forEach(e=>{a.createEdge(e)}),a.select(null),r.viewport?s.setViewport(r.viewport.scale,r.viewport.tx,r.viewport.ty):!1!==r.fitViewport&&a.fitViewport(r.fitViewportPadding),a.resetHistory(),{kind:"bpmn",ice:s,designer:a}}function renderFlowDsl(e,i){const n=compileFlowDsl(i),r=n.options||{},s=(new t).init(e),a=new o(s);return n.nodes.forEach(e=>{a.createNode(e.kind,e)}),n.edges.forEach(e=>{a.createEdge(e)}),a.select(null),r.viewport?s.setViewport(r.viewport.scale,r.viewport.tx,r.viewport.ty):!1!==r.fitViewport&&a.fitViewport(r.fitViewportPadding),a.resetHistory(),{kind:"flowchart",ice:s,designer:a}}export{s as DSL_SCHEMA_VERSION,compileBpmnDsl,compileDsl,compileFlowDsl,isBpmnDsl,isFlowDsl,layeredLayout,renderBpmnDsl,renderDsl,renderFlowDsl,validateBpmnDsl,validateDsl,validateFlowDsl};
|
|
1
|
+
import{FLOW_NODE_KINDS as e,ICE as t,UmlDesigner as i,BpmnDesigner as o,FlowDesigner as n,EntityDesigner as r,ICELayeredLayout as s}from"ice-entity-designer";function isFlowDsl(e){return!!e&&"object"==typeof e&&"flowchart"===e.kind}function isBpmnDsl(e){return!!e&&"object"==typeof e&&"bpmn"===e.kind}function isUmlDsl(e){return!!e&&"object"==typeof e&&"uml"===e.kind}const a=1,l=["terminator","process","decision","io"],d=["T","R","B","L","C"],p=["pool","lane","task","event","gateway","subprocess","dataObject","annotation"],h=["start","intermediate","end"],c=["none","message","timer","error","terminate"],u=["exclusive","parallel","inclusive","event"],f=["none","user","service","script","send","receive","manual"],m=["sequence","message","association"],g=["class","interface","enum"],y=["inheritance","realization","association","aggregation","composition","dependency"];function validateDsl(e){return isUmlDsl(e)?validateUmlDsl(e):isBpmnDsl(e)?validateBpmnDsl(e):isFlowDsl(e)?validateFlowDsl(e):function validateErDsl(e){const t=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&t.push("Unsupported schemaVersion: "+e.schemaVersion);if(Array.isArray(e.entities)){const i=new Set;e.entities.forEach((e,o)=>{const n=`entities[${o}]`;e&&"object"==typeof e?("string"==typeof e.id&&e.id.trim()?i.has(e.id)?t.push(`${n}.id is duplicated: ${e.id}`):i.add(e.id):t.push(n+".id must be a non-empty string"),Array.isArray(e.fields)?e.fields.forEach((e,i)=>{e&&"object"==typeof e&&"string"==typeof e.name&&e.name.trim()||t.push(`${n}.fields[${i}].name must be a non-empty string`)}):t.push(n+".fields must be an array")):t.push(n+" must be an object")})}else t.push("entities must be an array");void 0===e.relations||Array.isArray(e.relations)?(e.relations||[]).forEach((e,i)=>{const o=`relations[${i}]`;e&&"object"==typeof e?("string"==typeof e.source&&e.source.trim()||t.push(o+".source must be a non-empty string"),"string"==typeof e.target&&e.target.trim()||t.push(o+".target must be a non-empty string")):t.push(o+" must be an object")}):t.push("relations must be an array");return{valid:0===t.length,errors:t}}(e)}function validateBpmnDsl(e){const t=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&t.push("Unsupported schemaVersion: "+e.schemaVersion);const i=new Set,o=new Map;return Array.isArray(e.nodes)?(e.nodes.forEach((e,n)=>{const r=`nodes[${n}]`;if(!e||"object"!=typeof e)return void t.push(r+" must be an object");"string"==typeof e.id&&e.id.trim()?i.has(e.id)?t.push(`${r}.id is duplicated: ${e.id}`):(i.add(e.id),o.set(e.id,e.kind||"task")):t.push(r+".id must be a non-empty string"),void 0!==e.kind&&-1===p.indexOf(e.kind)&&t.push(`${r}.kind must be one of ${p.join("/")}`),["left","top","width","height"].forEach(i=>{const o=e[i];void 0!==o&&"number"!=typeof o&&t.push(`${r}.${i} must be a number when present`)});[["eventKind",h],["trigger",c],["gatewayType",u],["taskType",f]].forEach(([i,o])=>{const n=e[i];void 0!==n&&-1===o.indexOf(n)&&t.push(`${r}.${i} must be one of ${o.join("/")}`)})}),e.nodes.forEach((e,n)=>{if(!e||"object"!=typeof e||void 0===e.parent)return;const r=`nodes[${n}]`;if("string"!=typeof e.parent||!e.parent.trim())return void t.push(r+".parent must be a non-empty string when present");if(!i.has(e.parent))return void t.push(r+".parent must reference an existing node id");if(e.parent===e.id)return void t.push(r+".parent must not reference itself");const s=o.get(e.parent);"pool"===e.kind?t.push(r+".parent is not allowed on a pool (池是最外层容器)"):"lane"===e.kind&&"pool"!==s?t.push(r+".parent must reference a pool"):"pool"!==s&&"lane"!==s&&t.push(r+".parent must reference a pool or a lane")})):t.push("nodes must be an array"),void 0===e.edges||Array.isArray(e.edges)?(e.edges||[]).forEach((e,o)=>{const n=`edges[${o}]`;if(!e||"object"!=typeof e)return void t.push(n+" must be an object");"string"==typeof e.source&&e.source.trim()&&i.has(e.source)||t.push(n+".source must reference an existing node id"),"string"==typeof e.target&&e.target.trim()&&i.has(e.target)||t.push(n+".target must reference an existing node id");const r=void 0!==e.type?e.type:e.flowType;void 0!==r&&-1===m.indexOf(r)&&t.push(`${n}.type must be one of ${m.join("/")}`),void 0!==e.label&&"string"!=typeof e.label&&t.push(n+".label must be a string when present"),void 0!==e.condition&&"string"!=typeof e.condition&&t.push(n+".condition must be a string when present"),void 0!==e.linkShape&&"visio"!==e.linkShape&&"bezier"!==e.linkShape&&t.push(n+'.linkShape must be "visio" or "bezier" when present')}):t.push("edges must be an array when present"),{valid:0===t.length,errors:t}}function validateFlowDsl(e){const t=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&t.push("Unsupported schemaVersion: "+e.schemaVersion);const i=new Set;return Array.isArray(e.nodes)?e.nodes.forEach((e,o)=>{const n=`nodes[${o}]`;e&&"object"==typeof e?("string"==typeof e.id&&e.id.trim()?i.has(e.id)?t.push(`${n}.id is duplicated: ${e.id}`):i.add(e.id):t.push(n+".id must be a non-empty string"),void 0!==e.kind&&-1===l.indexOf(e.kind)&&t.push(`${n}.kind must be one of ${l.join("/")}`),["left","top","width","height"].forEach(i=>{const o=e[i];void 0!==o&&"number"!=typeof o&&t.push(`${n}.${i} must be a number when present`)})):t.push(n+" must be an object")}):t.push("nodes must be an array"),void 0===e.edges||Array.isArray(e.edges)?(e.edges||[]).forEach((e,o)=>{const n=`edges[${o}]`;e&&"object"==typeof e?("string"==typeof e.source&&e.source.trim()&&i.has(e.source)||t.push(n+".source must reference an existing node id"),"string"==typeof e.target&&e.target.trim()&&i.has(e.target)||t.push(n+".target must reference an existing node id"),void 0!==e.label&&"string"!=typeof e.label&&t.push(n+".label must be a string when present"),void 0!==e.sourcePort&&-1===d.indexOf(e.sourcePort)&&t.push(`${n}.sourcePort must be one of ${d.join("/")}`),void 0!==e.targetPort&&-1===d.indexOf(e.targetPort)&&t.push(`${n}.targetPort must be one of ${d.join("/")}`),void 0!==e.linkShape&&"visio"!==e.linkShape&&"bezier"!==e.linkShape&&t.push(n+'.linkShape must be "visio" or "bezier" when present')):t.push(n+" must be an object")}):t.push("edges must be an array when present"),{valid:0===t.length,errors:t}}function validateUmlDsl(e){const t=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&t.push("Unsupported schemaVersion: "+e.schemaVersion);const i=new Set;return Array.isArray(e.nodes)?e.nodes.forEach((e,o)=>{const n=`nodes[${o}]`;e&&"object"==typeof e?("string"==typeof e.id&&e.id.trim()?i.has(e.id)?t.push(`${n}.id is duplicated: ${e.id}`):i.add(e.id):t.push(n+".id must be a non-empty string"),void 0!==e.kind&&-1===g.indexOf(e.kind)&&t.push(`${n}.kind must be one of ${g.join("/")}`),["attributes","methods"].forEach(i=>{const o=e[i];void 0!==o&&(Array.isArray(o)&&!o.some(e=>"string"!=typeof e)||t.push(`${n}.${i} must be an array of strings when present`))}),["left","top","width","height"].forEach(i=>{const o=e[i];void 0!==o&&"number"!=typeof o&&t.push(`${n}.${i} must be a number when present`)})):t.push(n+" must be an object")}):t.push("nodes must be an array"),void 0===e.edges||Array.isArray(e.edges)?(e.edges||[]).forEach((e,o)=>{const n=`edges[${o}]`;if(!e||"object"!=typeof e)return void t.push(n+" must be an object");"string"==typeof e.source&&e.source.trim()&&i.has(e.source)||t.push(n+".source must reference an existing node id"),"string"==typeof e.target&&e.target.trim()&&i.has(e.target)||t.push(n+".target must reference an existing node id");const r=void 0!==e.type?e.type:e.relation;void 0!==r&&-1===y.indexOf(r)&&t.push(`${n}.type must be one of ${y.join("/")}`),void 0!==e.label&&"string"!=typeof e.label&&t.push(n+".label must be a string when present")}):t.push("edges must be an array when present"),{valid:0===t.length,errors:t}}function entityName(e){return e.entityName||e.name||e.id}function relationType(e){return e.relationType||e.type||"one-to-many"}function compileDsl(e){if(isFlowDsl(e))throw new Error("compileDsl() 只处理 ER 文档;流程图文档请使用 compileFlowDsl()");if(!e||!Array.isArray(e.entities))throw new Error("ER 文档必须包含 entities 数组");return{entities:e.entities.map(e=>({id:e.id,entityName:entityName(e),fields:e.fields||[],left:e.left,top:e.top,width:e.width,height:e.height,style:e.style,headerStyle:e.headerStyle,fieldStyle:e.fieldStyle,dividerStyle:e.dividerStyle,draggable:e.draggable,interactive:e.interactive})),relations:(e.relations||[]).map((e,t)=>({id:e.id||"relation-"+t,relationType:relationType(e),sourceId:e.source,targetId:e.target,sourceField:e.sourceField||"id",targetField:e.targetField||"id",nullable:e.nullable,onDelete:e.onDelete,onUpdate:e.onUpdate,joinTableName:e.joinTableName,fromKey:e.fromKey,toKey:e.toKey,sourceCardinality:e.sourceCardinality,targetCardinality:e.targetCardinality,label:e.label,style:e.style,arrow:e.arrow,linkShape:e.linkShape,routeType:e.routeType,routeOffset:e.routeOffset,curveType:e.curveType,lineDash:e.lineDash})),layout:e.layout,options:e.options}}function layeredLayout(e,t,i={}){const o=Number(i.gapX)||90,n=Number(i.gapY)||90,r=void 0===i.originX?80:i.originX,s=void 0===i.originY?80:i.originY,a=new Map;if(!e.length)return a;const l=new Map;e.forEach(e=>l.set(e.id,e));const d=new Map,p=new Map;e.forEach(e=>{d.set(e.id,0),p.set(e.id,[])}),t.forEach(e=>{l.has(e.sourceId)&&l.has(e.targetId)&&(d.set(e.targetId,(d.get(e.targetId)||0)+1),p.get(e.sourceId).push(e.targetId))});const h=new Map,c=[];e.forEach(e=>{0===(d.get(e.id)||0)&&(h.set(e.id,0),c.push(e.id))}),c.length||(h.set(e[0].id,0),c.push(e[0].id));let u=e.length*e.length+e.length;for(;c.length&&u-- >0;){const e=c.shift(),t=h.get(e)||0;(p.get(e)||[]).forEach(e=>{const i=t+1;(void 0===h.get(e)?-1:h.get(e))<i&&(h.set(e,i),c.push(e))})}e.forEach(e=>{h.has(e.id)||h.set(e.id,0)});const f=new Map;e.forEach(e=>{const t=h.get(e.id)||0;f.has(t)||f.set(t,[]),f.get(t).push(e)});const m=[...f.keys()].sort((e,t)=>e-t);if("horizontal"===i.direction){const e=m.map(e=>Math.max(...f.get(e).map(e=>e.width)));let t=0;m.forEach((i,r)=>{const s=f.get(i);let l=-(s.reduce((e,t)=>e+t.height,0)+Math.max(s.length-1,0)*n)/2;s.forEach(i=>{a.set(i.id,{left:Math.round(t+(e[r]-i.width)/2),top:Math.round(l)}),l+=i.height+n}),t+=e[r]+o})}else{const e=m.map(e=>Math.max(...f.get(e).map(e=>e.height)));let t=0;m.forEach((i,r)=>{const s=f.get(i);let l=-(s.reduce((e,t)=>e+t.width,0)+Math.max(s.length-1,0)*o)/2;s.forEach(i=>{a.set(i.id,{left:Math.round(l),top:Math.round(t+(e[r]-i.height)/2)}),l+=i.width+o}),t+=e[r]+n})}const g=Math.min(...e.map(e=>a.get(e.id).left)),y=Math.min(...e.map(e=>a.get(e.id).top));return a.forEach(e=>{e.left+=r-g,e.top+=s-y}),a}const b={terminator:{width:e.terminator.width,height:e.terminator.height,fill:e.terminator.fill,stroke:e.terminator.stroke},process:{width:e.process.width,height:e.process.height,fill:e.process.fill,stroke:e.process.stroke},decision:{width:e.decision.width,height:e.decision.height,fill:e.decision.fill,stroke:e.decision.stroke},io:{width:e.io.width,height:e.io.height,fill:e.io.fill,stroke:e.io.stroke}};function compileFlowDsl(e){const t=e.options||{},i=(e.nodes||[]).map(e=>{const t=function nodeKind$1(e){return e.kind&&b[e.kind]?e.kind:"process"}(e),i=b[t];return{id:e.id,typeId:"FlowNode",kind:t,title:(o=e,o.title||o.name||o.id),left:"number"==typeof e.left?e.left:Number.NaN,top:"number"==typeof e.top?e.top:Number.NaN,width:"number"==typeof e.width?e.width:i.width,height:"number"==typeof e.height?e.height:i.height,fillColor:e.fillColor||i.fill,strokeColor:e.strokeColor||i.stroke};var o}),o=(e.edges||[]).map((e,t)=>({id:e.id||"edge-"+t,sourceId:e.source,targetId:e.target,sourcePort:e.sourcePort||"B",targetPort:e.targetPort||"T",label:e.label||"",linkShape:e.linkShape||"visio"})),n=t.layout||"layered";return"none"!==n&&i.some(e=>Number.isNaN(e.left)||Number.isNaN(e.top))&&(i.forEach(e=>{Number.isNaN(e.left)&&(e.left=0),Number.isNaN(e.top)&&(e.top=0)}),function autoLayout(e,t,i,o){const n=layeredLayout(e,t,{gapX:i,gapY:o});e.forEach(e=>{const t=n.get(e.id);t&&(e.left=t.left,e.top=t.top)})}(i,o,Number(t.gapX)||90,Number(t.gapY)||90)),i.forEach(e=>{Number.isNaN(e.left)&&(e.left=0),Number.isNaN(e.top)&&(e.top=0)}),{kind:"flowchart",nodes:i,edges:o,layout:n,options:t}}const w={pool:"bpmnPool",lane:"bpmnLane",task:"bpmnTask",event:"bpmnEvent",gateway:"bpmnGateway",subprocess:"bpmnSubprocess",dataObject:"bpmnDataObject",annotation:"bpmnAnnotation"},v=Number(e.bpmnPool.bandSize)||32,k=Number(e.bpmnLane.bandSize)||32,x=Number(e.bpmnLane.height)||130,N=Number(e.bpmnPool.width)||900;function toWorkingNode(t){const i=t.kind||"task",o=function presetOf(t){return e[t]||e.bpmnTask}(w[i]||"bpmnTask"),n={id:t.id,typeId:"FlowNode",kind:w[i]||"bpmnTask",title:t.title||t.name||t.id,left:"number"==typeof t.left?t.left:0,top:"number"==typeof t.top?t.top:0,width:"number"==typeof t.width?t.width:o.width,height:"number"==typeof t.height?t.height:o.height,fillColor:t.fillColor,strokeColor:t.strokeColor,dslKind:i,parent:t.parent,explicitLeft:"number"==typeof t.left,explicitTop:"number"==typeof t.top,explicitWidth:"number"==typeof t.width,explicitHeight:"number"==typeof t.height};return"event"===i&&(n.eventKind=t.eventKind||o.eventKind||"start",n.trigger=t.trigger||o.trigger||"none"),"gateway"===i&&(n.gatewayType=t.gatewayType||o.gatewayType||"exclusive"),"task"!==i&&"subprocess"!==i||(n.taskType=t.taskType||o.taskType||"none"),n}function buildGroups(e,t){const i=new Map;t.forEach(e=>i.set(e.id,e));const o=1===t.length?t[0]:null,n=[];return e.forEach(e=>{(e=>{let t=n.filter(t=>t.owner===e)[0];return t||(t={owner:e,nodes:[],box:null,didLayout:!1},n.push(t)),t})((e.parent?i.get(e.parent):void 0)||o).nodes.push(e)}),n}function layoutGroups(e,t,i,o){e.forEach(e=>{if(e.nodes.some(e=>!e.explicitLeft||!e.explicitTop)){const n=layeredLayout(e.nodes,t,{gapX:i,gapY:o,originX:0,originY:0,direction:"horizontal"});e.nodes.forEach(e=>{const t=n.get(e.id);t&&(e.left=t.left,e.top=t.top)}),e.didLayout=!0}e.box=function unionBox(e){if(!e.length)return null;let t=1/0,i=1/0,o=-1/0,n=-1/0;return e.forEach(e=>{t=Math.min(t,e.left),i=Math.min(i,e.top),o=Math.max(o,e.left+e.width),n=Math.max(n,e.top+e.height)}),{minX:t,minY:i,maxX:o,maxY:n}}(e.nodes)})}function compileBpmnDsl(e){const t=e.options||{},i=(e.nodes||[]).map(toWorkingNode),o=i.filter(e=>"pool"===e.dslKind),n=i.filter(e=>"lane"===e.dslKind),r=i.filter(e=>!function isContainer(e){return"pool"===e.dslKind||"lane"===e.dslKind}(e)),s=(e.edges||[]).map((e,t)=>({id:e.id||"edge-"+t,sourceId:e.source,targetId:e.target,flowType:e.type||e.flowType||"sequence",label:e.label||"",condition:e.condition||"",isDefault:!!e.isDefault,linkShape:e.linkShape||"visio"})),a=t.layout||"auto",l=function resolveLaneOwners(e,t){const i=new Map;return e.forEach(e=>{let o=e.parent;o||1!==t.length||(o=t[0].id),o&&i.set(e.id,o)}),i}(n,o),lanesOf=e=>n.filter(t=>l.get(t.id)===e);let d=[];"none"!==a&&(d=buildGroups(r,o.concat(n)),layoutGroups(d,s,Number(t.gapX)||90,Number(t.gapY)||60)),n.forEach(e=>{const t=d.filter(t=>t.owner===e)[0],i=t?t.box:null;e.explicitHeight||(e.height=Math.round(Math.max(56+(i?i.maxY-i.minY:0),x))),e.explicitWidth||(e.width=Math.round(Math.max((i?i.maxX-i.minX:0)+k+56,N)))}),o.forEach(e=>{const t=lanesOf(e.id);if(t.length){const i=t.reduce((e,t)=>Math.max(e,t.width),N);return e.explicitWidth||(e.width=i),e.explicitWidth&&t.forEach(t=>{t.explicitWidth||(t.width=e.width)}),void(e.explicitHeight||(e.height=v+t.reduce((e,t)=>e+t.height,0)))}const i=d.filter(t=>t.owner===e)[0],o=i?i.box:null;e.explicitWidth||(e.width=Math.round(Math.max(56+(o?o.maxX-o.minX:0),N))),e.explicitHeight||(e.height=Math.round(Math.max((o?o.maxY-o.minY:0)+v+56,160)))});let p=60;o.forEach(e=>{e.explicitLeft||(e.left=60),e.explicitTop||(e.top=p),p=Math.max(p,e.top+e.height+60)}),o.forEach(e=>{const t=lanesOf(e.id);if(!t.length)return;const i=e.top+v,o=Math.max(e.height-v,1),n=t.reduce((e,t)=>e+(t.explicitHeight?t.height:0),0),r=t.filter(e=>!e.explicitHeight),s=r.length?Math.max(o-n,0)/r.length:0;let a=i;t.forEach(t=>{t.explicitLeft||(t.left=e.left),t.explicitTop||(t.top=a),!t.explicitHeight&&e.explicitHeight&&(t.height=Math.round(s||x)),a=t.top+t.height})});let h=60;n.forEach(e=>{l.get(e.id)||(e.explicitLeft||(e.left=60),e.explicitTop||(e.top=h,h=e.top+e.height+60))}),d.forEach(e=>{const t=e.box;if(!t||!e.didLayout)return;const i=e.owner;let o=80,n=80;i&&(o=i.left+28,n=i.top+28,"pool"===i.dslKind?n+=v:o+=k),e.nodes.forEach(e=>{e.left=Math.round(o+(e.left-t.minX)),e.top=Math.round(n+(e.top-t.minY))})});return{kind:"bpmn",nodes:o.concat(n).concat(r).map(e=>{const t={id:e.id,typeId:"FlowNode",kind:e.kind,title:e.title,left:e.left,top:e.top,width:e.width,height:e.height};return void 0!==e.eventKind&&(t.eventKind=e.eventKind),void 0!==e.trigger&&(t.trigger=e.trigger),void 0!==e.gatewayType&&(t.gatewayType=e.gatewayType),void 0!==e.taskType&&(t.taskType=e.taskType),void 0!==e.fillColor&&(t.fillColor=e.fillColor),void 0!==e.strokeColor&&(t.strokeColor=e.strokeColor),t}),edges:s,layout:a,options:t}}function compileUmlDsl(e){const t=e.options||{},i=(e.nodes||[]).map(e=>{return{id:e.id,kind:(t=e,t.kind||"class"),className:e.title||e.name||e.id,abstract:!!e.abstract,attributes:Array.isArray(e.attributes)?e.attributes.map(e=>String(e)):[],methods:Array.isArray(e.methods)?e.methods.map(e=>String(e)):[],left:"number"==typeof e.left?e.left:Number.NaN,top:"number"==typeof e.top?e.top:Number.NaN,width:"number"==typeof e.width?e.width:240,height:"number"==typeof e.height?e.height:120+24*(e.attributes?e.attributes.length:0)+24*(e.methods?e.methods.length:0)};var t}),o=(e.edges||[]).map((e,t)=>({id:e.id||"relation-"+t,sourceId:e.source,targetId:e.target,relationKind:e.type||e.relation||"association",label:e.label||""})),n=t.layout||"layered";if("none"!==n&&i.some(e=>Number.isNaN(e.left)||Number.isNaN(e.top))){i.forEach(e=>{Number.isNaN(e.left)&&(e.left=0),Number.isNaN(e.top)&&(e.top=0)});const e=layeredLayout(i,o.filter(e=>"inheritance"===e.relationKind||"realization"===e.relationKind).map(e=>({sourceId:e.targetId,targetId:e.sourceId})),{gapX:Number(t.gapX)||80,gapY:Number(t.gapY)||110,originX:80,originY:80,direction:"vertical"});i.forEach(t=>{const i=e.get(t.id);i&&(t.left=i.left,t.top=i.top)})}return i.forEach(e=>{Number.isNaN(e.left)&&(e.left=0),Number.isNaN(e.top)&&(e.top=0)}),{kind:"uml",nodes:i,edges:o,layout:n,options:t}}function renderDsl(e,i){const o=validateDsl(i);if(!o.valid)throw new Error(o.errors.join("\n"));return isUmlDsl(i)?renderUmlDsl(e,i):isBpmnDsl(i)?renderBpmnDsl(e,i):isFlowDsl(i)?renderFlowDsl(e,i):function renderErDsl(e,i){const o=compileDsl(i),n=o.options||{},a=(new t).init(e),l=new r(a);o.entities.forEach(e=>{l.createEntity(e)}),function positionLinks(e,t,i){const o=new Map;return e.entities.forEach(e=>{o.set(e.state.id,e.getMinBoundingBox(!0))}),t.relations.map(e=>{const t=o.get(e.sourceId),n=o.get(e.targetId);let r="R",s="L";if(t&&n){const e=n.center[0]-t.center[0],i=n.center[1]-t.center[1];Math.abs(e)>Math.abs(i)?(r=e>=0?"R":"L",s=e>=0?"L":"R"):(r=i>=0?"B":"T",s=i>=0?"T":"B")}return{...e,routeType:e.routeType||i||"orthogonal",linkShape:e.linkShape||"visio",links:{start:{id:e.sourceId,position:r},end:{id:e.targetId,position:s}}}})}(l,o,n.routeType).forEach(e=>{l.createRelation(e)}),("layered"===o.layout||"horizontal"===o.layout)&&new s({gapX:n.gapX||120,gapY:n.gapY||50}).layoutContainer(a);n.viewport?a.setViewport(n.viewport.scale,n.viewport.tx,n.viewport.ty):n.fitViewport&&function fitViewport(e,t,i){const o=t.entities||[];let n=1/0,r=1/0,s=-1/0,a=-1/0;o.forEach(e=>{const t=e.getMinBoundingBox(!0).getMinAndMaxPoint();n=Math.min(n,t.minX),r=Math.min(r,t.minY),s=Math.max(s,t.maxX),a=Math.max(a,t.maxY)});const l=s-n,d=a-r,p=e.canvasWidth||0,h=e.canvasHeight||0;if(!p||!h||l<=0||d<=0)return;const c=Number.isFinite(i)&&i>=0?i:40,u=Math.max(1,p-2*c),f=Math.max(1,h-2*c),m=Math.min(u/l,f/d,1),g=(p-l*m)/2-n*m,y=(h-d*m)/2-r*m;e.setViewport(m,g,y)}(a,l,n.fitViewportPadding);return{kind:"entity",ice:a,designer:l}}(e,i)}function renderUmlDsl(e,o){const n=compileUmlDsl(o),r=n.options||{},s=(new t).init(e),a=new i(s);return n.nodes.forEach(e=>{a.createClass({id:e.id,kind:e.kind,className:e.className,abstract:e.abstract,attributes:e.attributes,methods:e.methods,left:e.left,top:e.top,width:e.width})}),n.edges.forEach(e=>{a.createRelation(e)}),a.select(null),r.viewport?s.setViewport(r.viewport.scale,r.viewport.tx,r.viewport.ty):!1!==r.fitViewport&&a.fitViewport(r.fitViewportPadding),a.resetHistory(),{kind:"uml",ice:s,designer:a}}function renderBpmnDsl(e,i){const n=compileBpmnDsl(i),r=n.options||{},s=(new t).init(e),a=new o(s);return n.nodes.forEach(e=>{const t={id:e.id,title:e.title,left:e.left,top:e.top,width:e.width,height:e.height};["eventKind","trigger","gatewayType","taskType","fillColor","strokeColor"].forEach(i=>{void 0!==e[i]&&(t[i]=e[i])}),a.createNode(e.kind,t)}),n.edges.forEach(e=>{a.createEdge(e)}),a.select(null),r.viewport?s.setViewport(r.viewport.scale,r.viewport.tx,r.viewport.ty):!1!==r.fitViewport&&a.fitViewport(r.fitViewportPadding),a.resetHistory(),{kind:"bpmn",ice:s,designer:a}}function renderFlowDsl(e,i){const o=compileFlowDsl(i),r=o.options||{},s=(new t).init(e),a=new n(s);return o.nodes.forEach(e=>{a.createNode(e.kind,e)}),o.edges.forEach(e=>{a.createEdge(e)}),a.select(null),r.viewport?s.setViewport(r.viewport.scale,r.viewport.tx,r.viewport.ty):!1!==r.fitViewport&&a.fitViewport(r.fitViewportPadding),a.resetHistory(),{kind:"flowchart",ice:s,designer:a}}export{a as DSL_SCHEMA_VERSION,compileBpmnDsl,compileDsl,compileFlowDsl,compileUmlDsl,isBpmnDsl,isFlowDsl,isUmlDsl,layeredLayout,renderBpmnDsl,renderDsl,renderFlowDsl,renderUmlDsl,validateBpmnDsl,validateDsl,validateFlowDsl,validateUmlDsl};
|
package/dist/index.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("ice-entity-designer")):"function"==typeof define&&define.amd?define(["exports","ice-entity-designer"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ICEDSL={},e.IED)}(this,(function(e,t){"use strict";function isFlowDsl(e){return!!e&&"object"==typeof e&&"flowchart"===e.kind}function isBpmnDsl(e){return!!e&&"object"==typeof e&&"bpmn"===e.kind}const i=["terminator","process","decision","io"],o=["T","R","B","L","C"],n=["pool","lane","task","event","gateway","subprocess","dataObject","annotation"],r=["start","intermediate","end"],s=["none","message","timer","error","terminate"],a=["exclusive","parallel","inclusive","event"],l=["none","user","service","script","send","receive","manual"],d=["sequence","message","association"];function validateDsl(e){return isBpmnDsl(e)?validateBpmnDsl(e):isFlowDsl(e)?validateFlowDsl(e):function validateErDsl(e){const t=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&t.push("Unsupported schemaVersion: "+e.schemaVersion);if(Array.isArray(e.entities)){const i=new Set;e.entities.forEach((e,o)=>{const n=`entities[${o}]`;e&&"object"==typeof e?("string"==typeof e.id&&e.id.trim()?i.has(e.id)?t.push(`${n}.id is duplicated: ${e.id}`):i.add(e.id):t.push(n+".id must be a non-empty string"),Array.isArray(e.fields)?e.fields.forEach((e,i)=>{e&&"object"==typeof e&&"string"==typeof e.name&&e.name.trim()||t.push(`${n}.fields[${i}].name must be a non-empty string`)}):t.push(n+".fields must be an array")):t.push(n+" must be an object")})}else t.push("entities must be an array");void 0===e.relations||Array.isArray(e.relations)?(e.relations||[]).forEach((e,i)=>{const o=`relations[${i}]`;e&&"object"==typeof e?("string"==typeof e.source&&e.source.trim()||t.push(o+".source must be a non-empty string"),"string"==typeof e.target&&e.target.trim()||t.push(o+".target must be a non-empty string")):t.push(o+" must be an object")}):t.push("relations must be an array");return{valid:0===t.length,errors:t}}(e)}function validateBpmnDsl(e){const t=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&t.push("Unsupported schemaVersion: "+e.schemaVersion);const i=new Set,o=new Map;return Array.isArray(e.nodes)?(e.nodes.forEach((e,d)=>{const p=`nodes[${d}]`;if(!e||"object"!=typeof e)return void t.push(p+" must be an object");"string"==typeof e.id&&e.id.trim()?i.has(e.id)?t.push(`${p}.id is duplicated: ${e.id}`):(i.add(e.id),o.set(e.id,e.kind||"task")):t.push(p+".id must be a non-empty string"),void 0!==e.kind&&-1===n.indexOf(e.kind)&&t.push(`${p}.kind must be one of ${n.join("/")}`),["left","top","width","height"].forEach(i=>{const o=e[i];void 0!==o&&"number"!=typeof o&&t.push(`${p}.${i} must be a number when present`)});[["eventKind",r],["trigger",s],["gatewayType",a],["taskType",l]].forEach(([i,o])=>{const n=e[i];void 0!==n&&-1===o.indexOf(n)&&t.push(`${p}.${i} must be one of ${o.join("/")}`)})}),e.nodes.forEach((e,n)=>{if(!e||"object"!=typeof e||void 0===e.parent)return;const r=`nodes[${n}]`;if("string"!=typeof e.parent||!e.parent.trim())return void t.push(r+".parent must be a non-empty string when present");if(!i.has(e.parent))return void t.push(r+".parent must reference an existing node id");if(e.parent===e.id)return void t.push(r+".parent must not reference itself");const s=o.get(e.parent);"pool"===e.kind?t.push(r+".parent is not allowed on a pool (池是最外层容器)"):"lane"===e.kind&&"pool"!==s?t.push(r+".parent must reference a pool"):"pool"!==s&&"lane"!==s&&t.push(r+".parent must reference a pool or a lane")})):t.push("nodes must be an array"),void 0===e.edges||Array.isArray(e.edges)?(e.edges||[]).forEach((e,o)=>{const n=`edges[${o}]`;if(!e||"object"!=typeof e)return void t.push(n+" must be an object");"string"==typeof e.source&&e.source.trim()&&i.has(e.source)||t.push(n+".source must reference an existing node id"),"string"==typeof e.target&&e.target.trim()&&i.has(e.target)||t.push(n+".target must reference an existing node id");const r=void 0!==e.type?e.type:e.flowType;void 0!==r&&-1===d.indexOf(r)&&t.push(`${n}.type must be one of ${d.join("/")}`),void 0!==e.label&&"string"!=typeof e.label&&t.push(n+".label must be a string when present"),void 0!==e.condition&&"string"!=typeof e.condition&&t.push(n+".condition must be a string when present"),void 0!==e.linkShape&&"visio"!==e.linkShape&&"bezier"!==e.linkShape&&t.push(n+'.linkShape must be "visio" or "bezier" when present')}):t.push("edges must be an array when present"),{valid:0===t.length,errors:t}}function validateFlowDsl(e){const t=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&t.push("Unsupported schemaVersion: "+e.schemaVersion);const n=new Set;return Array.isArray(e.nodes)?e.nodes.forEach((e,o)=>{const r=`nodes[${o}]`;e&&"object"==typeof e?("string"==typeof e.id&&e.id.trim()?n.has(e.id)?t.push(`${r}.id is duplicated: ${e.id}`):n.add(e.id):t.push(r+".id must be a non-empty string"),void 0!==e.kind&&-1===i.indexOf(e.kind)&&t.push(`${r}.kind must be one of ${i.join("/")}`),["left","top","width","height"].forEach(i=>{const o=e[i];void 0!==o&&"number"!=typeof o&&t.push(`${r}.${i} must be a number when present`)})):t.push(r+" must be an object")}):t.push("nodes must be an array"),void 0===e.edges||Array.isArray(e.edges)?(e.edges||[]).forEach((e,i)=>{const r=`edges[${i}]`;e&&"object"==typeof e?("string"==typeof e.source&&e.source.trim()&&n.has(e.source)||t.push(r+".source must reference an existing node id"),"string"==typeof e.target&&e.target.trim()&&n.has(e.target)||t.push(r+".target must reference an existing node id"),void 0!==e.label&&"string"!=typeof e.label&&t.push(r+".label must be a string when present"),void 0!==e.sourcePort&&-1===o.indexOf(e.sourcePort)&&t.push(`${r}.sourcePort must be one of ${o.join("/")}`),void 0!==e.targetPort&&-1===o.indexOf(e.targetPort)&&t.push(`${r}.targetPort must be one of ${o.join("/")}`),void 0!==e.linkShape&&"visio"!==e.linkShape&&"bezier"!==e.linkShape&&t.push(r+'.linkShape must be "visio" or "bezier" when present')):t.push(r+" must be an object")}):t.push("edges must be an array when present"),{valid:0===t.length,errors:t}}function entityName(e){return e.entityName||e.name||e.id}function relationType(e){return e.relationType||e.type||"one-to-many"}function compileDsl(e){if(isFlowDsl(e))throw new Error("compileDsl() 只处理 ER 文档;流程图文档请使用 compileFlowDsl()");if(!e||!Array.isArray(e.entities))throw new Error("ER 文档必须包含 entities 数组");return{entities:e.entities.map(e=>({id:e.id,entityName:entityName(e),fields:e.fields||[],left:e.left,top:e.top,width:e.width,height:e.height,style:e.style,headerStyle:e.headerStyle,fieldStyle:e.fieldStyle,dividerStyle:e.dividerStyle,draggable:e.draggable,interactive:e.interactive})),relations:(e.relations||[]).map((e,t)=>({id:e.id||"relation-"+t,relationType:relationType(e),sourceId:e.source,targetId:e.target,sourceField:e.sourceField||"id",targetField:e.targetField||"id",nullable:e.nullable,onDelete:e.onDelete,onUpdate:e.onUpdate,joinTableName:e.joinTableName,fromKey:e.fromKey,toKey:e.toKey,sourceCardinality:e.sourceCardinality,targetCardinality:e.targetCardinality,label:e.label,style:e.style,arrow:e.arrow,linkShape:e.linkShape,routeType:e.routeType,routeOffset:e.routeOffset,curveType:e.curveType,lineDash:e.lineDash})),layout:e.layout,options:e.options}}function layeredLayout(e,t,i={}){const o=Number(i.gapX)||90,n=Number(i.gapY)||90,r=void 0===i.originX?80:i.originX,s=void 0===i.originY?80:i.originY,a=new Map;if(!e.length)return a;const l=new Map;e.forEach(e=>l.set(e.id,e));const d=new Map,p=new Map;e.forEach(e=>{d.set(e.id,0),p.set(e.id,[])}),t.forEach(e=>{l.has(e.sourceId)&&l.has(e.targetId)&&(d.set(e.targetId,(d.get(e.targetId)||0)+1),p.get(e.sourceId).push(e.targetId))});const h=new Map,c=[];e.forEach(e=>{0===(d.get(e.id)||0)&&(h.set(e.id,0),c.push(e.id))}),c.length||(h.set(e[0].id,0),c.push(e[0].id));let u=e.length*e.length+e.length;for(;c.length&&u-- >0;){const e=c.shift(),t=h.get(e)||0;(p.get(e)||[]).forEach(e=>{const i=t+1;(void 0===h.get(e)?-1:h.get(e))<i&&(h.set(e,i),c.push(e))})}e.forEach(e=>{h.has(e.id)||h.set(e.id,0)});const f=new Map;e.forEach(e=>{const t=h.get(e.id)||0;f.has(t)||f.set(t,[]),f.get(t).push(e)});const m=[...f.keys()].sort((e,t)=>e-t);if("horizontal"===i.direction){const e=m.map(e=>Math.max(...f.get(e).map(e=>e.width)));let t=0;m.forEach((i,r)=>{const s=f.get(i);let l=-(s.reduce((e,t)=>e+t.height,0)+Math.max(s.length-1,0)*n)/2;s.forEach(i=>{a.set(i.id,{left:Math.round(t+(e[r]-i.width)/2),top:Math.round(l)}),l+=i.height+n}),t+=e[r]+o})}else{const e=m.map(e=>Math.max(...f.get(e).map(e=>e.height)));let t=0;m.forEach((i,r)=>{const s=f.get(i);let l=-(s.reduce((e,t)=>e+t.width,0)+Math.max(s.length-1,0)*o)/2;s.forEach(i=>{a.set(i.id,{left:Math.round(l),top:Math.round(t+(e[r]-i.height)/2)}),l+=i.width+o}),t+=e[r]+n})}const g=Math.min(...e.map(e=>a.get(e.id).left)),y=Math.min(...e.map(e=>a.get(e.id).top));return a.forEach(e=>{e.left+=r-g,e.top+=s-y}),a}const p={terminator:{width:t.FLOW_NODE_KINDS.terminator.width,height:t.FLOW_NODE_KINDS.terminator.height,fill:t.FLOW_NODE_KINDS.terminator.fill,stroke:t.FLOW_NODE_KINDS.terminator.stroke},process:{width:t.FLOW_NODE_KINDS.process.width,height:t.FLOW_NODE_KINDS.process.height,fill:t.FLOW_NODE_KINDS.process.fill,stroke:t.FLOW_NODE_KINDS.process.stroke},decision:{width:t.FLOW_NODE_KINDS.decision.width,height:t.FLOW_NODE_KINDS.decision.height,fill:t.FLOW_NODE_KINDS.decision.fill,stroke:t.FLOW_NODE_KINDS.decision.stroke},io:{width:t.FLOW_NODE_KINDS.io.width,height:t.FLOW_NODE_KINDS.io.height,fill:t.FLOW_NODE_KINDS.io.fill,stroke:t.FLOW_NODE_KINDS.io.stroke}};function compileFlowDsl(e){const t=e.options||{},i=(e.nodes||[]).map(e=>{const t=function nodeKind(e){return e.kind&&p[e.kind]?e.kind:"process"}(e),i=p[t];return{id:e.id,typeId:"FlowNode",kind:t,title:(o=e,o.title||o.name||o.id),left:"number"==typeof e.left?e.left:Number.NaN,top:"number"==typeof e.top?e.top:Number.NaN,width:"number"==typeof e.width?e.width:i.width,height:"number"==typeof e.height?e.height:i.height,fillColor:e.fillColor||i.fill,strokeColor:e.strokeColor||i.stroke};var o}),o=(e.edges||[]).map((e,t)=>({id:e.id||"edge-"+t,sourceId:e.source,targetId:e.target,sourcePort:e.sourcePort||"B",targetPort:e.targetPort||"T",label:e.label||"",linkShape:e.linkShape||"visio"})),n=t.layout||"layered";return"none"!==n&&i.some(e=>Number.isNaN(e.left)||Number.isNaN(e.top))&&(i.forEach(e=>{Number.isNaN(e.left)&&(e.left=0),Number.isNaN(e.top)&&(e.top=0)}),function autoLayout(e,t,i,o){const n=layeredLayout(e,t,{gapX:i,gapY:o});e.forEach(e=>{const t=n.get(e.id);t&&(e.left=t.left,e.top=t.top)})}(i,o,Number(t.gapX)||90,Number(t.gapY)||90)),i.forEach(e=>{Number.isNaN(e.left)&&(e.left=0),Number.isNaN(e.top)&&(e.top=0)}),{kind:"flowchart",nodes:i,edges:o,layout:n,options:t}}const h={pool:"bpmnPool",lane:"bpmnLane",task:"bpmnTask",event:"bpmnEvent",gateway:"bpmnGateway",subprocess:"bpmnSubprocess",dataObject:"bpmnDataObject",annotation:"bpmnAnnotation"},c=Number(t.FLOW_NODE_KINDS.bpmnPool.bandSize)||32,u=Number(t.FLOW_NODE_KINDS.bpmnLane.bandSize)||32,f=Number(t.FLOW_NODE_KINDS.bpmnLane.height)||130,m=Number(t.FLOW_NODE_KINDS.bpmnPool.width)||900;function toWorkingNode(e){const i=e.kind||"task",o=function presetOf(e){return t.FLOW_NODE_KINDS[e]||t.FLOW_NODE_KINDS.bpmnTask}(h[i]||"bpmnTask"),n={id:e.id,typeId:"FlowNode",kind:h[i]||"bpmnTask",title:e.title||e.name||e.id,left:"number"==typeof e.left?e.left:0,top:"number"==typeof e.top?e.top:0,width:"number"==typeof e.width?e.width:o.width,height:"number"==typeof e.height?e.height:o.height,fillColor:e.fillColor,strokeColor:e.strokeColor,dslKind:i,parent:e.parent,explicitLeft:"number"==typeof e.left,explicitTop:"number"==typeof e.top,explicitWidth:"number"==typeof e.width,explicitHeight:"number"==typeof e.height};return"event"===i&&(n.eventKind=e.eventKind||o.eventKind||"start",n.trigger=e.trigger||o.trigger||"none"),"gateway"===i&&(n.gatewayType=e.gatewayType||o.gatewayType||"exclusive"),"task"!==i&&"subprocess"!==i||(n.taskType=e.taskType||o.taskType||"none"),n}function buildGroups(e,t){const i=new Map;t.forEach(e=>i.set(e.id,e));const o=1===t.length?t[0]:null,n=[];return e.forEach(e=>{(e=>{let t=n.filter(t=>t.owner===e)[0];return t||(t={owner:e,nodes:[],box:null,didLayout:!1},n.push(t)),t})((e.parent?i.get(e.parent):void 0)||o).nodes.push(e)}),n}function layoutGroups(e,t,i,o){e.forEach(e=>{if(e.nodes.some(e=>!e.explicitLeft||!e.explicitTop)){const n=layeredLayout(e.nodes,t,{gapX:i,gapY:o,originX:0,originY:0,direction:"horizontal"});e.nodes.forEach(e=>{const t=n.get(e.id);t&&(e.left=t.left,e.top=t.top)}),e.didLayout=!0}e.box=function unionBox(e){if(!e.length)return null;let t=1/0,i=1/0,o=-1/0,n=-1/0;return e.forEach(e=>{t=Math.min(t,e.left),i=Math.min(i,e.top),o=Math.max(o,e.left+e.width),n=Math.max(n,e.top+e.height)}),{minX:t,minY:i,maxX:o,maxY:n}}(e.nodes)})}function compileBpmnDsl(e){const t=e.options||{},i=(e.nodes||[]).map(toWorkingNode),o=i.filter(e=>"pool"===e.dslKind),n=i.filter(e=>"lane"===e.dslKind),r=i.filter(e=>!function isContainer(e){return"pool"===e.dslKind||"lane"===e.dslKind}(e)),s=(e.edges||[]).map((e,t)=>({id:e.id||"edge-"+t,sourceId:e.source,targetId:e.target,flowType:e.type||e.flowType||"sequence",label:e.label||"",condition:e.condition||"",isDefault:!!e.isDefault,linkShape:e.linkShape||"visio"})),a=t.layout||"auto",l=function resolveLaneOwners(e,t){const i=new Map;return e.forEach(e=>{let o=e.parent;o||1!==t.length||(o=t[0].id),o&&i.set(e.id,o)}),i}(n,o),lanesOf=e=>n.filter(t=>l.get(t.id)===e);let d=[];"none"!==a&&(d=buildGroups(r,o.concat(n)),layoutGroups(d,s,Number(t.gapX)||90,Number(t.gapY)||60)),n.forEach(e=>{const t=d.filter(t=>t.owner===e)[0],i=t?t.box:null;e.explicitHeight||(e.height=Math.round(Math.max(56+(i?i.maxY-i.minY:0),f))),e.explicitWidth||(e.width=Math.round(Math.max((i?i.maxX-i.minX:0)+u+56,m)))}),o.forEach(e=>{const t=lanesOf(e.id);if(t.length){const i=t.reduce((e,t)=>Math.max(e,t.width),m);return e.explicitWidth||(e.width=i),e.explicitWidth&&t.forEach(t=>{t.explicitWidth||(t.width=e.width)}),void(e.explicitHeight||(e.height=c+t.reduce((e,t)=>e+t.height,0)))}const i=d.filter(t=>t.owner===e)[0],o=i?i.box:null;e.explicitWidth||(e.width=Math.round(Math.max(56+(o?o.maxX-o.minX:0),m))),e.explicitHeight||(e.height=Math.round(Math.max((o?o.maxY-o.minY:0)+c+56,160)))});let p=60;o.forEach(e=>{e.explicitLeft||(e.left=60),e.explicitTop||(e.top=p),p=Math.max(p,e.top+e.height+60)}),o.forEach(e=>{const t=lanesOf(e.id);if(!t.length)return;const i=e.top+c,o=Math.max(e.height-c,1),n=t.reduce((e,t)=>e+(t.explicitHeight?t.height:0),0),r=t.filter(e=>!e.explicitHeight),s=r.length?Math.max(o-n,0)/r.length:0;let a=i;t.forEach(t=>{t.explicitLeft||(t.left=e.left),t.explicitTop||(t.top=a),!t.explicitHeight&&e.explicitHeight&&(t.height=Math.round(s||f)),a=t.top+t.height})});let h=60;n.forEach(e=>{l.get(e.id)||(e.explicitLeft||(e.left=60),e.explicitTop||(e.top=h,h=e.top+e.height+60))}),d.forEach(e=>{const t=e.box;if(!t||!e.didLayout)return;const i=e.owner;let o=80,n=80;i&&(o=i.left+28,n=i.top+28,"pool"===i.dslKind?n+=c:o+=u),e.nodes.forEach(e=>{e.left=Math.round(o+(e.left-t.minX)),e.top=Math.round(n+(e.top-t.minY))})});return{kind:"bpmn",nodes:o.concat(n).concat(r).map(e=>{const t={id:e.id,typeId:"FlowNode",kind:e.kind,title:e.title,left:e.left,top:e.top,width:e.width,height:e.height};return void 0!==e.eventKind&&(t.eventKind=e.eventKind),void 0!==e.trigger&&(t.trigger=e.trigger),void 0!==e.gatewayType&&(t.gatewayType=e.gatewayType),void 0!==e.taskType&&(t.taskType=e.taskType),void 0!==e.fillColor&&(t.fillColor=e.fillColor),void 0!==e.strokeColor&&(t.strokeColor=e.strokeColor),t}),edges:s,layout:a,options:t}}function renderBpmnDsl(e,i){const o=compileBpmnDsl(i),n=o.options||{},r=(new t.ICE).init(e),s=new t.BpmnDesigner(r);return o.nodes.forEach(e=>{const t={id:e.id,title:e.title,left:e.left,top:e.top,width:e.width,height:e.height};["eventKind","trigger","gatewayType","taskType","fillColor","strokeColor"].forEach(i=>{void 0!==e[i]&&(t[i]=e[i])}),s.createNode(e.kind,t)}),o.edges.forEach(e=>{s.createEdge(e)}),s.select(null),n.viewport?r.setViewport(n.viewport.scale,n.viewport.tx,n.viewport.ty):!1!==n.fitViewport&&s.fitViewport(n.fitViewportPadding),s.resetHistory(),{kind:"bpmn",ice:r,designer:s}}function renderFlowDsl(e,i){const o=compileFlowDsl(i),n=o.options||{},r=(new t.ICE).init(e),s=new t.FlowDesigner(r);return o.nodes.forEach(e=>{s.createNode(e.kind,e)}),o.edges.forEach(e=>{s.createEdge(e)}),s.select(null),n.viewport?r.setViewport(n.viewport.scale,n.viewport.tx,n.viewport.ty):!1!==n.fitViewport&&s.fitViewport(n.fitViewportPadding),s.resetHistory(),{kind:"flowchart",ice:r,designer:s}}e.DSL_SCHEMA_VERSION=1,e.compileBpmnDsl=compileBpmnDsl,e.compileDsl=compileDsl,e.compileFlowDsl=compileFlowDsl,e.isBpmnDsl=isBpmnDsl,e.isFlowDsl=isFlowDsl,e.layeredLayout=layeredLayout,e.renderBpmnDsl=renderBpmnDsl,e.renderDsl=function renderDsl(e,i){const o=validateDsl(i);if(!o.valid)throw new Error(o.errors.join("\n"));return isBpmnDsl(i)?renderBpmnDsl(e,i):isFlowDsl(i)?renderFlowDsl(e,i):function renderErDsl(e,i){const o=compileDsl(i),n=o.options||{},r=(new t.ICE).init(e),s=new t.EntityDesigner(r);o.entities.forEach(e=>{s.createEntity(e)}),function positionLinks(e,t,i){const o=new Map;return e.entities.forEach(e=>{o.set(e.state.id,e.getMinBoundingBox(!0))}),t.relations.map(e=>{const t=o.get(e.sourceId),n=o.get(e.targetId);let r="R",s="L";if(t&&n){const e=n.center[0]-t.center[0],i=n.center[1]-t.center[1];Math.abs(e)>Math.abs(i)?(r=e>=0?"R":"L",s=e>=0?"L":"R"):(r=i>=0?"B":"T",s=i>=0?"T":"B")}return{...e,routeType:e.routeType||i||"orthogonal",linkShape:e.linkShape||"visio",links:{start:{id:e.sourceId,position:r},end:{id:e.targetId,position:s}}}})}(s,o,n.routeType).forEach(e=>{s.createRelation(e)}),("layered"===o.layout||"horizontal"===o.layout)&&new t.ICELayeredLayout({gapX:n.gapX||120,gapY:n.gapY||50}).layoutContainer(r);n.viewport?r.setViewport(n.viewport.scale,n.viewport.tx,n.viewport.ty):n.fitViewport&&function fitViewport(e,t,i){const o=t.entities||[];let n=1/0,r=1/0,s=-1/0,a=-1/0;o.forEach(e=>{const t=e.getMinBoundingBox(!0).getMinAndMaxPoint();n=Math.min(n,t.minX),r=Math.min(r,t.minY),s=Math.max(s,t.maxX),a=Math.max(a,t.maxY)});const l=s-n,d=a-r,p=e.canvasWidth||0,h=e.canvasHeight||0;if(!p||!h||l<=0||d<=0)return;const c=Number.isFinite(i)&&i>=0?i:40,u=Math.max(1,p-2*c),f=Math.max(1,h-2*c),m=Math.min(u/l,f/d,1),g=(p-l*m)/2-n*m,y=(h-d*m)/2-r*m;e.setViewport(m,g,y)}(r,s,n.fitViewportPadding);return{kind:"entity",ice:r,designer:s}}(e,i)},e.renderFlowDsl=renderFlowDsl,e.validateBpmnDsl=validateBpmnDsl,e.validateDsl=validateDsl,e.validateFlowDsl=validateFlowDsl,Object.defineProperty(e,"__esModule",{value:!0})}));
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("ice-entity-designer")):"function"==typeof define&&define.amd?define(["exports","ice-entity-designer"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ICEDSL={},e.IED)}(this,(function(e,t){"use strict";function isFlowDsl(e){return!!e&&"object"==typeof e&&"flowchart"===e.kind}function isBpmnDsl(e){return!!e&&"object"==typeof e&&"bpmn"===e.kind}function isUmlDsl(e){return!!e&&"object"==typeof e&&"uml"===e.kind}const i=["terminator","process","decision","io"],o=["T","R","B","L","C"],n=["pool","lane","task","event","gateway","subprocess","dataObject","annotation"],r=["start","intermediate","end"],s=["none","message","timer","error","terminate"],a=["exclusive","parallel","inclusive","event"],l=["none","user","service","script","send","receive","manual"],d=["sequence","message","association"],p=["class","interface","enum"],h=["inheritance","realization","association","aggregation","composition","dependency"];function validateDsl(e){return isUmlDsl(e)?validateUmlDsl(e):isBpmnDsl(e)?validateBpmnDsl(e):isFlowDsl(e)?validateFlowDsl(e):function validateErDsl(e){const t=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&t.push("Unsupported schemaVersion: "+e.schemaVersion);if(Array.isArray(e.entities)){const i=new Set;e.entities.forEach((e,o)=>{const n=`entities[${o}]`;e&&"object"==typeof e?("string"==typeof e.id&&e.id.trim()?i.has(e.id)?t.push(`${n}.id is duplicated: ${e.id}`):i.add(e.id):t.push(n+".id must be a non-empty string"),Array.isArray(e.fields)?e.fields.forEach((e,i)=>{e&&"object"==typeof e&&"string"==typeof e.name&&e.name.trim()||t.push(`${n}.fields[${i}].name must be a non-empty string`)}):t.push(n+".fields must be an array")):t.push(n+" must be an object")})}else t.push("entities must be an array");void 0===e.relations||Array.isArray(e.relations)?(e.relations||[]).forEach((e,i)=>{const o=`relations[${i}]`;e&&"object"==typeof e?("string"==typeof e.source&&e.source.trim()||t.push(o+".source must be a non-empty string"),"string"==typeof e.target&&e.target.trim()||t.push(o+".target must be a non-empty string")):t.push(o+" must be an object")}):t.push("relations must be an array");return{valid:0===t.length,errors:t}}(e)}function validateBpmnDsl(e){const t=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&t.push("Unsupported schemaVersion: "+e.schemaVersion);const i=new Set,o=new Map;return Array.isArray(e.nodes)?(e.nodes.forEach((e,d)=>{const p=`nodes[${d}]`;if(!e||"object"!=typeof e)return void t.push(p+" must be an object");"string"==typeof e.id&&e.id.trim()?i.has(e.id)?t.push(`${p}.id is duplicated: ${e.id}`):(i.add(e.id),o.set(e.id,e.kind||"task")):t.push(p+".id must be a non-empty string"),void 0!==e.kind&&-1===n.indexOf(e.kind)&&t.push(`${p}.kind must be one of ${n.join("/")}`),["left","top","width","height"].forEach(i=>{const o=e[i];void 0!==o&&"number"!=typeof o&&t.push(`${p}.${i} must be a number when present`)});[["eventKind",r],["trigger",s],["gatewayType",a],["taskType",l]].forEach(([i,o])=>{const n=e[i];void 0!==n&&-1===o.indexOf(n)&&t.push(`${p}.${i} must be one of ${o.join("/")}`)})}),e.nodes.forEach((e,n)=>{if(!e||"object"!=typeof e||void 0===e.parent)return;const r=`nodes[${n}]`;if("string"!=typeof e.parent||!e.parent.trim())return void t.push(r+".parent must be a non-empty string when present");if(!i.has(e.parent))return void t.push(r+".parent must reference an existing node id");if(e.parent===e.id)return void t.push(r+".parent must not reference itself");const s=o.get(e.parent);"pool"===e.kind?t.push(r+".parent is not allowed on a pool (池是最外层容器)"):"lane"===e.kind&&"pool"!==s?t.push(r+".parent must reference a pool"):"pool"!==s&&"lane"!==s&&t.push(r+".parent must reference a pool or a lane")})):t.push("nodes must be an array"),void 0===e.edges||Array.isArray(e.edges)?(e.edges||[]).forEach((e,o)=>{const n=`edges[${o}]`;if(!e||"object"!=typeof e)return void t.push(n+" must be an object");"string"==typeof e.source&&e.source.trim()&&i.has(e.source)||t.push(n+".source must reference an existing node id"),"string"==typeof e.target&&e.target.trim()&&i.has(e.target)||t.push(n+".target must reference an existing node id");const r=void 0!==e.type?e.type:e.flowType;void 0!==r&&-1===d.indexOf(r)&&t.push(`${n}.type must be one of ${d.join("/")}`),void 0!==e.label&&"string"!=typeof e.label&&t.push(n+".label must be a string when present"),void 0!==e.condition&&"string"!=typeof e.condition&&t.push(n+".condition must be a string when present"),void 0!==e.linkShape&&"visio"!==e.linkShape&&"bezier"!==e.linkShape&&t.push(n+'.linkShape must be "visio" or "bezier" when present')}):t.push("edges must be an array when present"),{valid:0===t.length,errors:t}}function validateFlowDsl(e){const t=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&t.push("Unsupported schemaVersion: "+e.schemaVersion);const n=new Set;return Array.isArray(e.nodes)?e.nodes.forEach((e,o)=>{const r=`nodes[${o}]`;e&&"object"==typeof e?("string"==typeof e.id&&e.id.trim()?n.has(e.id)?t.push(`${r}.id is duplicated: ${e.id}`):n.add(e.id):t.push(r+".id must be a non-empty string"),void 0!==e.kind&&-1===i.indexOf(e.kind)&&t.push(`${r}.kind must be one of ${i.join("/")}`),["left","top","width","height"].forEach(i=>{const o=e[i];void 0!==o&&"number"!=typeof o&&t.push(`${r}.${i} must be a number when present`)})):t.push(r+" must be an object")}):t.push("nodes must be an array"),void 0===e.edges||Array.isArray(e.edges)?(e.edges||[]).forEach((e,i)=>{const r=`edges[${i}]`;e&&"object"==typeof e?("string"==typeof e.source&&e.source.trim()&&n.has(e.source)||t.push(r+".source must reference an existing node id"),"string"==typeof e.target&&e.target.trim()&&n.has(e.target)||t.push(r+".target must reference an existing node id"),void 0!==e.label&&"string"!=typeof e.label&&t.push(r+".label must be a string when present"),void 0!==e.sourcePort&&-1===o.indexOf(e.sourcePort)&&t.push(`${r}.sourcePort must be one of ${o.join("/")}`),void 0!==e.targetPort&&-1===o.indexOf(e.targetPort)&&t.push(`${r}.targetPort must be one of ${o.join("/")}`),void 0!==e.linkShape&&"visio"!==e.linkShape&&"bezier"!==e.linkShape&&t.push(r+'.linkShape must be "visio" or "bezier" when present')):t.push(r+" must be an object")}):t.push("edges must be an array when present"),{valid:0===t.length,errors:t}}function validateUmlDsl(e){const t=[];if(!e||"object"!=typeof e||Array.isArray(e))return{valid:!1,errors:["DSL root must be an object"]};void 0!==e.schemaVersion&&1!==e.schemaVersion&&t.push("Unsupported schemaVersion: "+e.schemaVersion);const i=new Set;return Array.isArray(e.nodes)?e.nodes.forEach((e,o)=>{const n=`nodes[${o}]`;e&&"object"==typeof e?("string"==typeof e.id&&e.id.trim()?i.has(e.id)?t.push(`${n}.id is duplicated: ${e.id}`):i.add(e.id):t.push(n+".id must be a non-empty string"),void 0!==e.kind&&-1===p.indexOf(e.kind)&&t.push(`${n}.kind must be one of ${p.join("/")}`),["attributes","methods"].forEach(i=>{const o=e[i];void 0!==o&&(Array.isArray(o)&&!o.some(e=>"string"!=typeof e)||t.push(`${n}.${i} must be an array of strings when present`))}),["left","top","width","height"].forEach(i=>{const o=e[i];void 0!==o&&"number"!=typeof o&&t.push(`${n}.${i} must be a number when present`)})):t.push(n+" must be an object")}):t.push("nodes must be an array"),void 0===e.edges||Array.isArray(e.edges)?(e.edges||[]).forEach((e,o)=>{const n=`edges[${o}]`;if(!e||"object"!=typeof e)return void t.push(n+" must be an object");"string"==typeof e.source&&e.source.trim()&&i.has(e.source)||t.push(n+".source must reference an existing node id"),"string"==typeof e.target&&e.target.trim()&&i.has(e.target)||t.push(n+".target must reference an existing node id");const r=void 0!==e.type?e.type:e.relation;void 0!==r&&-1===h.indexOf(r)&&t.push(`${n}.type must be one of ${h.join("/")}`),void 0!==e.label&&"string"!=typeof e.label&&t.push(n+".label must be a string when present")}):t.push("edges must be an array when present"),{valid:0===t.length,errors:t}}function entityName(e){return e.entityName||e.name||e.id}function relationType(e){return e.relationType||e.type||"one-to-many"}function compileDsl(e){if(isFlowDsl(e))throw new Error("compileDsl() 只处理 ER 文档;流程图文档请使用 compileFlowDsl()");if(!e||!Array.isArray(e.entities))throw new Error("ER 文档必须包含 entities 数组");return{entities:e.entities.map(e=>({id:e.id,entityName:entityName(e),fields:e.fields||[],left:e.left,top:e.top,width:e.width,height:e.height,style:e.style,headerStyle:e.headerStyle,fieldStyle:e.fieldStyle,dividerStyle:e.dividerStyle,draggable:e.draggable,interactive:e.interactive})),relations:(e.relations||[]).map((e,t)=>({id:e.id||"relation-"+t,relationType:relationType(e),sourceId:e.source,targetId:e.target,sourceField:e.sourceField||"id",targetField:e.targetField||"id",nullable:e.nullable,onDelete:e.onDelete,onUpdate:e.onUpdate,joinTableName:e.joinTableName,fromKey:e.fromKey,toKey:e.toKey,sourceCardinality:e.sourceCardinality,targetCardinality:e.targetCardinality,label:e.label,style:e.style,arrow:e.arrow,linkShape:e.linkShape,routeType:e.routeType,routeOffset:e.routeOffset,curveType:e.curveType,lineDash:e.lineDash})),layout:e.layout,options:e.options}}function layeredLayout(e,t,i={}){const o=Number(i.gapX)||90,n=Number(i.gapY)||90,r=void 0===i.originX?80:i.originX,s=void 0===i.originY?80:i.originY,a=new Map;if(!e.length)return a;const l=new Map;e.forEach(e=>l.set(e.id,e));const d=new Map,p=new Map;e.forEach(e=>{d.set(e.id,0),p.set(e.id,[])}),t.forEach(e=>{l.has(e.sourceId)&&l.has(e.targetId)&&(d.set(e.targetId,(d.get(e.targetId)||0)+1),p.get(e.sourceId).push(e.targetId))});const h=new Map,c=[];e.forEach(e=>{0===(d.get(e.id)||0)&&(h.set(e.id,0),c.push(e.id))}),c.length||(h.set(e[0].id,0),c.push(e[0].id));let u=e.length*e.length+e.length;for(;c.length&&u-- >0;){const e=c.shift(),t=h.get(e)||0;(p.get(e)||[]).forEach(e=>{const i=t+1;(void 0===h.get(e)?-1:h.get(e))<i&&(h.set(e,i),c.push(e))})}e.forEach(e=>{h.has(e.id)||h.set(e.id,0)});const f=new Map;e.forEach(e=>{const t=h.get(e.id)||0;f.has(t)||f.set(t,[]),f.get(t).push(e)});const m=[...f.keys()].sort((e,t)=>e-t);if("horizontal"===i.direction){const e=m.map(e=>Math.max(...f.get(e).map(e=>e.width)));let t=0;m.forEach((i,r)=>{const s=f.get(i);let l=-(s.reduce((e,t)=>e+t.height,0)+Math.max(s.length-1,0)*n)/2;s.forEach(i=>{a.set(i.id,{left:Math.round(t+(e[r]-i.width)/2),top:Math.round(l)}),l+=i.height+n}),t+=e[r]+o})}else{const e=m.map(e=>Math.max(...f.get(e).map(e=>e.height)));let t=0;m.forEach((i,r)=>{const s=f.get(i);let l=-(s.reduce((e,t)=>e+t.width,0)+Math.max(s.length-1,0)*o)/2;s.forEach(i=>{a.set(i.id,{left:Math.round(l),top:Math.round(t+(e[r]-i.height)/2)}),l+=i.width+o}),t+=e[r]+n})}const g=Math.min(...e.map(e=>a.get(e.id).left)),y=Math.min(...e.map(e=>a.get(e.id).top));return a.forEach(e=>{e.left+=r-g,e.top+=s-y}),a}const c={terminator:{width:t.FLOW_NODE_KINDS.terminator.width,height:t.FLOW_NODE_KINDS.terminator.height,fill:t.FLOW_NODE_KINDS.terminator.fill,stroke:t.FLOW_NODE_KINDS.terminator.stroke},process:{width:t.FLOW_NODE_KINDS.process.width,height:t.FLOW_NODE_KINDS.process.height,fill:t.FLOW_NODE_KINDS.process.fill,stroke:t.FLOW_NODE_KINDS.process.stroke},decision:{width:t.FLOW_NODE_KINDS.decision.width,height:t.FLOW_NODE_KINDS.decision.height,fill:t.FLOW_NODE_KINDS.decision.fill,stroke:t.FLOW_NODE_KINDS.decision.stroke},io:{width:t.FLOW_NODE_KINDS.io.width,height:t.FLOW_NODE_KINDS.io.height,fill:t.FLOW_NODE_KINDS.io.fill,stroke:t.FLOW_NODE_KINDS.io.stroke}};function compileFlowDsl(e){const t=e.options||{},i=(e.nodes||[]).map(e=>{const t=function nodeKind$1(e){return e.kind&&c[e.kind]?e.kind:"process"}(e),i=c[t];return{id:e.id,typeId:"FlowNode",kind:t,title:(o=e,o.title||o.name||o.id),left:"number"==typeof e.left?e.left:Number.NaN,top:"number"==typeof e.top?e.top:Number.NaN,width:"number"==typeof e.width?e.width:i.width,height:"number"==typeof e.height?e.height:i.height,fillColor:e.fillColor||i.fill,strokeColor:e.strokeColor||i.stroke};var o}),o=(e.edges||[]).map((e,t)=>({id:e.id||"edge-"+t,sourceId:e.source,targetId:e.target,sourcePort:e.sourcePort||"B",targetPort:e.targetPort||"T",label:e.label||"",linkShape:e.linkShape||"visio"})),n=t.layout||"layered";return"none"!==n&&i.some(e=>Number.isNaN(e.left)||Number.isNaN(e.top))&&(i.forEach(e=>{Number.isNaN(e.left)&&(e.left=0),Number.isNaN(e.top)&&(e.top=0)}),function autoLayout(e,t,i,o){const n=layeredLayout(e,t,{gapX:i,gapY:o});e.forEach(e=>{const t=n.get(e.id);t&&(e.left=t.left,e.top=t.top)})}(i,o,Number(t.gapX)||90,Number(t.gapY)||90)),i.forEach(e=>{Number.isNaN(e.left)&&(e.left=0),Number.isNaN(e.top)&&(e.top=0)}),{kind:"flowchart",nodes:i,edges:o,layout:n,options:t}}const u={pool:"bpmnPool",lane:"bpmnLane",task:"bpmnTask",event:"bpmnEvent",gateway:"bpmnGateway",subprocess:"bpmnSubprocess",dataObject:"bpmnDataObject",annotation:"bpmnAnnotation"},f=Number(t.FLOW_NODE_KINDS.bpmnPool.bandSize)||32,m=Number(t.FLOW_NODE_KINDS.bpmnLane.bandSize)||32,g=Number(t.FLOW_NODE_KINDS.bpmnLane.height)||130,y=Number(t.FLOW_NODE_KINDS.bpmnPool.width)||900;function toWorkingNode(e){const i=e.kind||"task",o=function presetOf(e){return t.FLOW_NODE_KINDS[e]||t.FLOW_NODE_KINDS.bpmnTask}(u[i]||"bpmnTask"),n={id:e.id,typeId:"FlowNode",kind:u[i]||"bpmnTask",title:e.title||e.name||e.id,left:"number"==typeof e.left?e.left:0,top:"number"==typeof e.top?e.top:0,width:"number"==typeof e.width?e.width:o.width,height:"number"==typeof e.height?e.height:o.height,fillColor:e.fillColor,strokeColor:e.strokeColor,dslKind:i,parent:e.parent,explicitLeft:"number"==typeof e.left,explicitTop:"number"==typeof e.top,explicitWidth:"number"==typeof e.width,explicitHeight:"number"==typeof e.height};return"event"===i&&(n.eventKind=e.eventKind||o.eventKind||"start",n.trigger=e.trigger||o.trigger||"none"),"gateway"===i&&(n.gatewayType=e.gatewayType||o.gatewayType||"exclusive"),"task"!==i&&"subprocess"!==i||(n.taskType=e.taskType||o.taskType||"none"),n}function buildGroups(e,t){const i=new Map;t.forEach(e=>i.set(e.id,e));const o=1===t.length?t[0]:null,n=[];return e.forEach(e=>{(e=>{let t=n.filter(t=>t.owner===e)[0];return t||(t={owner:e,nodes:[],box:null,didLayout:!1},n.push(t)),t})((e.parent?i.get(e.parent):void 0)||o).nodes.push(e)}),n}function layoutGroups(e,t,i,o){e.forEach(e=>{if(e.nodes.some(e=>!e.explicitLeft||!e.explicitTop)){const n=layeredLayout(e.nodes,t,{gapX:i,gapY:o,originX:0,originY:0,direction:"horizontal"});e.nodes.forEach(e=>{const t=n.get(e.id);t&&(e.left=t.left,e.top=t.top)}),e.didLayout=!0}e.box=function unionBox(e){if(!e.length)return null;let t=1/0,i=1/0,o=-1/0,n=-1/0;return e.forEach(e=>{t=Math.min(t,e.left),i=Math.min(i,e.top),o=Math.max(o,e.left+e.width),n=Math.max(n,e.top+e.height)}),{minX:t,minY:i,maxX:o,maxY:n}}(e.nodes)})}function compileBpmnDsl(e){const t=e.options||{},i=(e.nodes||[]).map(toWorkingNode),o=i.filter(e=>"pool"===e.dslKind),n=i.filter(e=>"lane"===e.dslKind),r=i.filter(e=>!function isContainer(e){return"pool"===e.dslKind||"lane"===e.dslKind}(e)),s=(e.edges||[]).map((e,t)=>({id:e.id||"edge-"+t,sourceId:e.source,targetId:e.target,flowType:e.type||e.flowType||"sequence",label:e.label||"",condition:e.condition||"",isDefault:!!e.isDefault,linkShape:e.linkShape||"visio"})),a=t.layout||"auto",l=function resolveLaneOwners(e,t){const i=new Map;return e.forEach(e=>{let o=e.parent;o||1!==t.length||(o=t[0].id),o&&i.set(e.id,o)}),i}(n,o),lanesOf=e=>n.filter(t=>l.get(t.id)===e);let d=[];"none"!==a&&(d=buildGroups(r,o.concat(n)),layoutGroups(d,s,Number(t.gapX)||90,Number(t.gapY)||60)),n.forEach(e=>{const t=d.filter(t=>t.owner===e)[0],i=t?t.box:null;e.explicitHeight||(e.height=Math.round(Math.max(56+(i?i.maxY-i.minY:0),g))),e.explicitWidth||(e.width=Math.round(Math.max((i?i.maxX-i.minX:0)+m+56,y)))}),o.forEach(e=>{const t=lanesOf(e.id);if(t.length){const i=t.reduce((e,t)=>Math.max(e,t.width),y);return e.explicitWidth||(e.width=i),e.explicitWidth&&t.forEach(t=>{t.explicitWidth||(t.width=e.width)}),void(e.explicitHeight||(e.height=f+t.reduce((e,t)=>e+t.height,0)))}const i=d.filter(t=>t.owner===e)[0],o=i?i.box:null;e.explicitWidth||(e.width=Math.round(Math.max(56+(o?o.maxX-o.minX:0),y))),e.explicitHeight||(e.height=Math.round(Math.max((o?o.maxY-o.minY:0)+f+56,160)))});let p=60;o.forEach(e=>{e.explicitLeft||(e.left=60),e.explicitTop||(e.top=p),p=Math.max(p,e.top+e.height+60)}),o.forEach(e=>{const t=lanesOf(e.id);if(!t.length)return;const i=e.top+f,o=Math.max(e.height-f,1),n=t.reduce((e,t)=>e+(t.explicitHeight?t.height:0),0),r=t.filter(e=>!e.explicitHeight),s=r.length?Math.max(o-n,0)/r.length:0;let a=i;t.forEach(t=>{t.explicitLeft||(t.left=e.left),t.explicitTop||(t.top=a),!t.explicitHeight&&e.explicitHeight&&(t.height=Math.round(s||g)),a=t.top+t.height})});let h=60;n.forEach(e=>{l.get(e.id)||(e.explicitLeft||(e.left=60),e.explicitTop||(e.top=h,h=e.top+e.height+60))}),d.forEach(e=>{const t=e.box;if(!t||!e.didLayout)return;const i=e.owner;let o=80,n=80;i&&(o=i.left+28,n=i.top+28,"pool"===i.dslKind?n+=f:o+=m),e.nodes.forEach(e=>{e.left=Math.round(o+(e.left-t.minX)),e.top=Math.round(n+(e.top-t.minY))})});return{kind:"bpmn",nodes:o.concat(n).concat(r).map(e=>{const t={id:e.id,typeId:"FlowNode",kind:e.kind,title:e.title,left:e.left,top:e.top,width:e.width,height:e.height};return void 0!==e.eventKind&&(t.eventKind=e.eventKind),void 0!==e.trigger&&(t.trigger=e.trigger),void 0!==e.gatewayType&&(t.gatewayType=e.gatewayType),void 0!==e.taskType&&(t.taskType=e.taskType),void 0!==e.fillColor&&(t.fillColor=e.fillColor),void 0!==e.strokeColor&&(t.strokeColor=e.strokeColor),t}),edges:s,layout:a,options:t}}function compileUmlDsl(e){const t=e.options||{},i=(e.nodes||[]).map(e=>{return{id:e.id,kind:(t=e,t.kind||"class"),className:e.title||e.name||e.id,abstract:!!e.abstract,attributes:Array.isArray(e.attributes)?e.attributes.map(e=>String(e)):[],methods:Array.isArray(e.methods)?e.methods.map(e=>String(e)):[],left:"number"==typeof e.left?e.left:Number.NaN,top:"number"==typeof e.top?e.top:Number.NaN,width:"number"==typeof e.width?e.width:240,height:"number"==typeof e.height?e.height:120+24*(e.attributes?e.attributes.length:0)+24*(e.methods?e.methods.length:0)};var t}),o=(e.edges||[]).map((e,t)=>({id:e.id||"relation-"+t,sourceId:e.source,targetId:e.target,relationKind:e.type||e.relation||"association",label:e.label||""})),n=t.layout||"layered";if("none"!==n&&i.some(e=>Number.isNaN(e.left)||Number.isNaN(e.top))){i.forEach(e=>{Number.isNaN(e.left)&&(e.left=0),Number.isNaN(e.top)&&(e.top=0)});const e=layeredLayout(i,o.filter(e=>"inheritance"===e.relationKind||"realization"===e.relationKind).map(e=>({sourceId:e.targetId,targetId:e.sourceId})),{gapX:Number(t.gapX)||80,gapY:Number(t.gapY)||110,originX:80,originY:80,direction:"vertical"});i.forEach(t=>{const i=e.get(t.id);i&&(t.left=i.left,t.top=i.top)})}return i.forEach(e=>{Number.isNaN(e.left)&&(e.left=0),Number.isNaN(e.top)&&(e.top=0)}),{kind:"uml",nodes:i,edges:o,layout:n,options:t}}function renderUmlDsl(e,i){const o=compileUmlDsl(i),n=o.options||{},r=(new t.ICE).init(e),s=new t.UmlDesigner(r);return o.nodes.forEach(e=>{s.createClass({id:e.id,kind:e.kind,className:e.className,abstract:e.abstract,attributes:e.attributes,methods:e.methods,left:e.left,top:e.top,width:e.width})}),o.edges.forEach(e=>{s.createRelation(e)}),s.select(null),n.viewport?r.setViewport(n.viewport.scale,n.viewport.tx,n.viewport.ty):!1!==n.fitViewport&&s.fitViewport(n.fitViewportPadding),s.resetHistory(),{kind:"uml",ice:r,designer:s}}function renderBpmnDsl(e,i){const o=compileBpmnDsl(i),n=o.options||{},r=(new t.ICE).init(e),s=new t.BpmnDesigner(r);return o.nodes.forEach(e=>{const t={id:e.id,title:e.title,left:e.left,top:e.top,width:e.width,height:e.height};["eventKind","trigger","gatewayType","taskType","fillColor","strokeColor"].forEach(i=>{void 0!==e[i]&&(t[i]=e[i])}),s.createNode(e.kind,t)}),o.edges.forEach(e=>{s.createEdge(e)}),s.select(null),n.viewport?r.setViewport(n.viewport.scale,n.viewport.tx,n.viewport.ty):!1!==n.fitViewport&&s.fitViewport(n.fitViewportPadding),s.resetHistory(),{kind:"bpmn",ice:r,designer:s}}function renderFlowDsl(e,i){const o=compileFlowDsl(i),n=o.options||{},r=(new t.ICE).init(e),s=new t.FlowDesigner(r);return o.nodes.forEach(e=>{s.createNode(e.kind,e)}),o.edges.forEach(e=>{s.createEdge(e)}),s.select(null),n.viewport?r.setViewport(n.viewport.scale,n.viewport.tx,n.viewport.ty):!1!==n.fitViewport&&s.fitViewport(n.fitViewportPadding),s.resetHistory(),{kind:"flowchart",ice:r,designer:s}}e.DSL_SCHEMA_VERSION=1,e.compileBpmnDsl=compileBpmnDsl,e.compileDsl=compileDsl,e.compileFlowDsl=compileFlowDsl,e.compileUmlDsl=compileUmlDsl,e.isBpmnDsl=isBpmnDsl,e.isFlowDsl=isFlowDsl,e.isUmlDsl=isUmlDsl,e.layeredLayout=layeredLayout,e.renderBpmnDsl=renderBpmnDsl,e.renderDsl=function renderDsl(e,i){const o=validateDsl(i);if(!o.valid)throw new Error(o.errors.join("\n"));return isUmlDsl(i)?renderUmlDsl(e,i):isBpmnDsl(i)?renderBpmnDsl(e,i):isFlowDsl(i)?renderFlowDsl(e,i):function renderErDsl(e,i){const o=compileDsl(i),n=o.options||{},r=(new t.ICE).init(e),s=new t.EntityDesigner(r);o.entities.forEach(e=>{s.createEntity(e)}),function positionLinks(e,t,i){const o=new Map;return e.entities.forEach(e=>{o.set(e.state.id,e.getMinBoundingBox(!0))}),t.relations.map(e=>{const t=o.get(e.sourceId),n=o.get(e.targetId);let r="R",s="L";if(t&&n){const e=n.center[0]-t.center[0],i=n.center[1]-t.center[1];Math.abs(e)>Math.abs(i)?(r=e>=0?"R":"L",s=e>=0?"L":"R"):(r=i>=0?"B":"T",s=i>=0?"T":"B")}return{...e,routeType:e.routeType||i||"orthogonal",linkShape:e.linkShape||"visio",links:{start:{id:e.sourceId,position:r},end:{id:e.targetId,position:s}}}})}(s,o,n.routeType).forEach(e=>{s.createRelation(e)}),("layered"===o.layout||"horizontal"===o.layout)&&new t.ICELayeredLayout({gapX:n.gapX||120,gapY:n.gapY||50}).layoutContainer(r);n.viewport?r.setViewport(n.viewport.scale,n.viewport.tx,n.viewport.ty):n.fitViewport&&function fitViewport(e,t,i){const o=t.entities||[];let n=1/0,r=1/0,s=-1/0,a=-1/0;o.forEach(e=>{const t=e.getMinBoundingBox(!0).getMinAndMaxPoint();n=Math.min(n,t.minX),r=Math.min(r,t.minY),s=Math.max(s,t.maxX),a=Math.max(a,t.maxY)});const l=s-n,d=a-r,p=e.canvasWidth||0,h=e.canvasHeight||0;if(!p||!h||l<=0||d<=0)return;const c=Number.isFinite(i)&&i>=0?i:40,u=Math.max(1,p-2*c),f=Math.max(1,h-2*c),m=Math.min(u/l,f/d,1),g=(p-l*m)/2-n*m,y=(h-d*m)/2-r*m;e.setViewport(m,g,y)}(r,s,n.fitViewportPadding);return{kind:"entity",ice:r,designer:s}}(e,i)},e.renderFlowDsl=renderFlowDsl,e.renderUmlDsl=renderUmlDsl,e.validateBpmnDsl=validateBpmnDsl,e.validateDsl=validateDsl,e.validateFlowDsl=validateFlowDsl,e.validateUmlDsl=validateUmlDsl,Object.defineProperty(e,"__esModule",{value:!0})}));
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { DslUmlDocument, DslUmlNodeKind, DslUmlRelationType } from '../types';
|
|
2
|
+
export declare type CompiledUmlNode = {
|
|
3
|
+
id: string;
|
|
4
|
+
kind: DslUmlNodeKind;
|
|
5
|
+
className: string;
|
|
6
|
+
abstract: boolean;
|
|
7
|
+
attributes: string[];
|
|
8
|
+
methods: string[];
|
|
9
|
+
left: number;
|
|
10
|
+
top: number;
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
};
|
|
14
|
+
export declare type CompiledUmlEdge = {
|
|
15
|
+
id: string;
|
|
16
|
+
sourceId: string;
|
|
17
|
+
targetId: string;
|
|
18
|
+
relationKind: DslUmlRelationType;
|
|
19
|
+
label: string;
|
|
20
|
+
};
|
|
21
|
+
export declare type CompiledUmlScene = {
|
|
22
|
+
kind: 'uml';
|
|
23
|
+
nodes: CompiledUmlNode[];
|
|
24
|
+
edges: CompiledUmlEdge[];
|
|
25
|
+
layout: string;
|
|
26
|
+
options?: Record<string, any>;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* UML 文档 → `UmlClass` / `UmlRelation` 构造参数。
|
|
30
|
+
*
|
|
31
|
+
* 与流程图/BPMN 同一套自动布局:只要有一个节点缺坐标,就对整张图做分层布局。
|
|
32
|
+
* 类图的分层方向是**继承自上而下**(父类在上、子类在下),所以用 `direction: 'vertical'`
|
|
33
|
+
* 并且把继承/实现边当作层级关系 —— 读起来就是标准的类图排布。
|
|
34
|
+
*/
|
|
35
|
+
export declare function compileUmlDsl(dsl: DslUmlDocument): CompiledUmlScene;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * from './types';
|
|
2
|
-
export { DSL_SCHEMA_VERSION, validateDsl, validateFlowDsl, validateBpmnDsl } from './validate';
|
|
2
|
+
export { DSL_SCHEMA_VERSION, validateDsl, validateFlowDsl, validateBpmnDsl, validateUmlDsl } from './validate';
|
|
3
3
|
export { compileDsl } from './compiler/dslToScene';
|
|
4
4
|
export type { CompiledScene } from './compiler/dslToScene';
|
|
5
5
|
export { compileFlowDsl } from './compiler/flowToScene';
|
|
@@ -8,5 +8,7 @@ export { compileBpmnDsl } from './compiler/bpmnToScene';
|
|
|
8
8
|
export type { CompiledBpmnScene, CompiledBpmnNode, CompiledBpmnEdge } from './compiler/bpmnToScene';
|
|
9
9
|
export { layeredLayout } from './compiler/layout';
|
|
10
10
|
export type { LayoutItem, LayoutEdge, LayoutOptions } from './compiler/layout';
|
|
11
|
-
export {
|
|
12
|
-
export type {
|
|
11
|
+
export { compileUmlDsl } from './compiler/umlToScene';
|
|
12
|
+
export type { CompiledUmlScene, CompiledUmlNode, CompiledUmlEdge } from './compiler/umlToScene';
|
|
13
|
+
export { renderDsl, renderFlowDsl, renderBpmnDsl, renderUmlDsl } from './runtime/renderDsl';
|
|
14
|
+
export type { RenderDslResult, RenderErDslResult, RenderFlowDslResult, RenderBpmnDslResult, RenderUmlDslResult, } from './runtime/renderDsl';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DslBpmnDocument, DslDocument, DslFlowDocument } from '../types';
|
|
1
|
+
import type { DslBpmnDocument, DslDocument, DslFlowDocument, DslUmlDocument } from '../types';
|
|
2
2
|
export declare type RenderErDslResult = {
|
|
3
3
|
kind: 'entity';
|
|
4
4
|
ice: any;
|
|
@@ -14,7 +14,12 @@ export declare type RenderBpmnDslResult = {
|
|
|
14
14
|
ice: any;
|
|
15
15
|
designer: any;
|
|
16
16
|
};
|
|
17
|
-
export declare type
|
|
17
|
+
export declare type RenderUmlDslResult = {
|
|
18
|
+
kind: 'uml';
|
|
19
|
+
ice: any;
|
|
20
|
+
designer: any;
|
|
21
|
+
};
|
|
22
|
+
export declare type RenderDslResult = RenderErDslResult | RenderFlowDslResult | RenderBpmnDslResult | RenderUmlDslResult;
|
|
18
23
|
/**
|
|
19
24
|
* 渲染一份 DSL 文档:ER 文档(entities/relations)或流程图文档(kind: 'flowchart')。
|
|
20
25
|
*
|
|
@@ -22,6 +27,13 @@ export declare type RenderDslResult = RenderErDslResult | RenderFlowDslResult |
|
|
|
22
27
|
* `designer` 分别是 `EntityDesigner` / `FlowDesigner` 实例。
|
|
23
28
|
*/
|
|
24
29
|
export declare function renderDsl(canvasOrId: any, dsl: DslDocument): RenderDslResult;
|
|
30
|
+
/**
|
|
31
|
+
* 渲染 UML 类图文档:类是复合组件(成员由 state 派生),关系是六种记法之一。
|
|
32
|
+
*
|
|
33
|
+
* 语义校验用 `designer.validateUml()`;文本互操作用 `IED.toPlantUml` / `IED.fromPlantUml`;
|
|
34
|
+
* 矢量导出用 `designer.toSvg()`。
|
|
35
|
+
*/
|
|
36
|
+
export declare function renderUmlDsl(canvasOrId: any, dsl: DslUmlDocument): RenderUmlDslResult;
|
|
25
37
|
/**
|
|
26
38
|
* 渲染 BPMN 文档:池/泳道也是节点(`parent` 声明归属),由 `BpmnDesigner` 按几何真嵌套,
|
|
27
39
|
* 因此拖动池/泳道时内部图元与挂在它们上面的连线会一起走(引擎的容器 + 递归 AFTER_MOVE)。
|
package/dist/types/types.d.ts
CHANGED
|
@@ -189,8 +189,8 @@ export declare type DslBpmnDocument = {
|
|
|
189
189
|
edges?: DslBpmnEdge[];
|
|
190
190
|
options?: DslBpmnDocumentOptions;
|
|
191
191
|
};
|
|
192
|
-
/** 一份 DSL 文档:ER(默认)、流程图(kind: 'flowchart'
|
|
193
|
-
export declare type DslDocument = DslErDocument | DslFlowDocument | DslBpmnDocument;
|
|
192
|
+
/** 一份 DSL 文档:ER(默认)、流程图(kind: 'flowchart')、BPMN(kind: 'bpmn')或 UML(kind: 'uml') */
|
|
193
|
+
export declare type DslDocument = DslErDocument | DslFlowDocument | DslBpmnDocument | DslUmlDocument;
|
|
194
194
|
export declare type DslValidationResult = {
|
|
195
195
|
valid: boolean;
|
|
196
196
|
errors: string[];
|
|
@@ -199,3 +199,56 @@ export declare type DslValidationResult = {
|
|
|
199
199
|
export declare function isFlowDsl(dsl: any): dsl is DslFlowDocument;
|
|
200
200
|
/** 运行时判别:带 kind: 'bpmn' 的按 BPMN 文档处理 */
|
|
201
201
|
export declare function isBpmnDsl(dsl: any): dsl is DslBpmnDocument;
|
|
202
|
+
export declare type DslUmlNodeKind = 'class' | 'interface' | 'enum';
|
|
203
|
+
export declare type DslUmlRelationType = 'inheritance' | 'realization' | 'association' | 'aggregation' | 'composition' | 'dependency';
|
|
204
|
+
export declare type DslUmlNode = {
|
|
205
|
+
id: string;
|
|
206
|
+
/** 节点类型,默认 class */
|
|
207
|
+
kind?: DslUmlNodeKind;
|
|
208
|
+
/** 类名(title / name 二者取一,name 兼容其它文档写法) */
|
|
209
|
+
title?: string;
|
|
210
|
+
name?: string;
|
|
211
|
+
/** 抽象类(`class` 才有意义;接口与枚举自带构造型) */
|
|
212
|
+
abstract?: boolean;
|
|
213
|
+
/** 属性区文本,例如 `['- id: string', '+ total: number']` */
|
|
214
|
+
attributes?: string[];
|
|
215
|
+
/** 方法区文本,例如 `['+ pay(amount: number): void']` */
|
|
216
|
+
methods?: string[];
|
|
217
|
+
left?: number;
|
|
218
|
+
top?: number;
|
|
219
|
+
width?: number;
|
|
220
|
+
height?: number;
|
|
221
|
+
};
|
|
222
|
+
export declare type DslUmlEdge = {
|
|
223
|
+
id?: string;
|
|
224
|
+
source: string;
|
|
225
|
+
target: string;
|
|
226
|
+
/** 关系种类,默认 association;方向语义见 SKILL/README(继承时 source=子类、target=父类) */
|
|
227
|
+
type?: DslUmlRelationType;
|
|
228
|
+
/** 兼容别名:relation 与 type 等价(type 优先) */
|
|
229
|
+
relation?: DslUmlRelationType;
|
|
230
|
+
label?: string;
|
|
231
|
+
};
|
|
232
|
+
export declare type DslUmlDocumentOptions = {
|
|
233
|
+
/** 是否自动适应视图,默认 true */
|
|
234
|
+
fitViewport?: boolean;
|
|
235
|
+
fitViewportPadding?: number;
|
|
236
|
+
viewport?: {
|
|
237
|
+
scale: number;
|
|
238
|
+
tx: number;
|
|
239
|
+
ty: number;
|
|
240
|
+
};
|
|
241
|
+
/** 缺坐标时的分层布局(继承关系自上而下),默认 layered */
|
|
242
|
+
layout?: 'layered' | 'none';
|
|
243
|
+
gapX?: number;
|
|
244
|
+
gapY?: number;
|
|
245
|
+
};
|
|
246
|
+
export declare type DslUmlDocument = {
|
|
247
|
+
schemaVersion?: number;
|
|
248
|
+
kind: 'uml';
|
|
249
|
+
nodes: DslUmlNode[];
|
|
250
|
+
edges?: DslUmlEdge[];
|
|
251
|
+
options?: DslUmlDocumentOptions;
|
|
252
|
+
};
|
|
253
|
+
/** 运行时判别:带 kind: 'uml' 的按类图文档处理 */
|
|
254
|
+
export declare function isUmlDsl(dsl: any): dsl is DslUmlDocument;
|
package/dist/types/validate.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DslBpmnDocument, DslDocument, DslFlowDocument, DslValidationResult } from './types';
|
|
1
|
+
import type { DslBpmnDocument, DslUmlDocument, DslDocument, DslFlowDocument, DslValidationResult } from './types';
|
|
2
2
|
export declare const DSL_SCHEMA_VERSION = 1;
|
|
3
3
|
/**
|
|
4
4
|
* 校验一份 DSL 文档:ER(entities/relations)、流程图(kind: 'flowchart')
|
|
@@ -15,3 +15,10 @@ export declare function validateDsl(dsl: DslDocument): DslValidationResult;
|
|
|
15
15
|
export declare function validateBpmnDsl(dsl: DslBpmnDocument): DslValidationResult;
|
|
16
16
|
/** 流程图文档校验:结构 + 端点必须指向已存在的节点(与 ER 的关系校验同一口径) */
|
|
17
17
|
export declare function validateFlowDsl(dsl: DslFlowDocument): DslValidationResult;
|
|
18
|
+
/**
|
|
19
|
+
* UML 文档校验:结构 + 词汇表 + 端点存在。
|
|
20
|
+
*
|
|
21
|
+
* 语义检查(重名类、继承成环等)交给 `UmlDesigner.validateUml()` —— 与 BPMN 同一分工:
|
|
22
|
+
* 结构在 DSL 侧、语义在设计师侧,不重复实现。
|
|
23
|
+
*/
|
|
24
|
+
export declare function validateUmlDsl(dsl: DslUmlDocument): DslValidationResult;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ice-entity-designer-dsl",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "A JSON-first DSL layer for AI agents to drive ice-entity-designer.",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"types:check": "tsc --noEmit"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"ice-entity-designer": "^0.0.
|
|
22
|
+
"ice-entity-designer": "^0.0.24"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@babel/core": "7.17.8",
|