drawio-mcp-server 2.0.3 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -3
- package/build/assets/downloader.js +16 -17
- package/build/config.js +253 -5
- package/build/config.test.js +449 -1
- package/build/emitter_bus.js +3 -0
- package/build/emitter_bus.test.js +7 -0
- package/build/index.capabilities.test.js +45 -0
- package/build/index.js +496 -106
- package/build/install-desktop-plugin.js +56 -0
- package/build/install-desktop-plugin.test.js +66 -0
- package/build/multi-transport.test.js +277 -0
- package/build/plugin/mcp-plugin.js +2180 -1105
- package/build/prefetch-assets.js +6 -5
- package/build/real-environment/document-targeting.test.js +124 -0
- package/build/real-environment/export-diagram.test.js +473 -0
- package/build/real-environment/harness.js +120 -32
- package/build/real-environment/import-mermaid.test.js +81 -0
- package/build/real-environment/pages-and-concurrency.test.js +448 -0
- package/build/real-environment/shapes.test.js +58 -0
- package/build/real-environment/tools.js +51 -6
- package/build/register-tool.js +31 -0
- package/build/request_queue.js +29 -0
- package/build/request_queue.test.js +98 -0
- package/build/stdio-transport-purity.test.js +88 -0
- package/build/strip-schema.js +61 -0
- package/build/tls/expiry.js +14 -0
- package/build/tls/expiry.test.js +54 -0
- package/build/tls/generate.js +123 -0
- package/build/tls/generate.test.js +115 -0
- package/build/tls/index.js +80 -0
- package/build/tls/index.test.js +141 -0
- package/build/tls/install-hint.js +45 -0
- package/build/tls/install-hint.test.js +32 -0
- package/build/tls/load.js +18 -0
- package/build/tls/load.test.js +40 -0
- package/build/tls/paths.js +30 -0
- package/build/tls/paths.test.js +53 -0
- package/build/tls/san.js +27 -0
- package/build/tls/san.test.js +72 -0
- package/build/tool-registry.test.js +823 -0
- package/build/tool.js +74 -15
- package/build/tool.test.js +250 -7
- package/build/tools/add-cell-of-shape.js +4 -2
- package/build/tools/add-edge.js +3 -1
- package/build/tools/add-rectangle.js +4 -2
- package/build/tools/copy-page.js +13 -0
- package/build/tools/create-layer.js +4 -2
- package/build/tools/create-page.js +8 -0
- package/build/tools/delete-cell-by-id.js +4 -2
- package/build/tools/edit-cell.js +3 -1
- package/build/tools/edit-edge.js +3 -1
- package/build/tools/export-diagram.js +7 -3
- package/build/tools/get-active-layer.js +4 -1
- package/build/tools/get-current-page.js +5 -0
- package/build/tools/get-selected-cell.js +4 -1
- package/build/tools/import-diagram.js +12 -2
- package/build/tools/import-mermaid.js +31 -0
- package/build/tools/index.js +14 -0
- package/build/tools/list-documents.js +17 -0
- package/build/tools/list-layers.js +4 -1
- package/build/tools/list-paged-model.js +4 -3
- package/build/tools/list-pages.js +5 -0
- package/build/tools/move-cell-to-layer.js +3 -1
- package/build/tools/rename-page.js +10 -0
- package/build/tools/set-active-layer.js +4 -2
- package/build/tools/set-cell-data.js +3 -1
- package/build/tools/set-cell-parent.js +3 -1
- package/build/tools/set-cell-shape.js +3 -1
- package/build/tools/shared.js +35 -0
- package/build/tools/shared.test.js +29 -0
- package/package.json +22 -14
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var DrawMcp = (() => {
|
|
3
3
|
// src/shape-library.ts
|
|
4
|
-
var
|
|
4
|
+
var generalShapes = {
|
|
5
5
|
rectangle: {
|
|
6
6
|
category: "general",
|
|
7
7
|
style: "rounded=0;whiteSpace=wrap;html=1;"
|
|
@@ -164,923 +164,776 @@ var DrawMcp = (() => {
|
|
|
164
164
|
directionalConnector: {
|
|
165
165
|
category: "general",
|
|
166
166
|
style: "endArrow=classic;html=1;rounded=0;fontSize=12;startSize=8;endSize=8;curved=1;"
|
|
167
|
-
},
|
|
168
|
-
// AWS / Analytics
|
|
169
|
-
"mxgraph.aws4.athena": {
|
|
170
|
-
category: "mxgraph.aws4.analytics",
|
|
171
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#8C4FFF;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.athena;"
|
|
172
|
-
},
|
|
173
|
-
"mxgraph.aws4.elasticsearch_service": {
|
|
174
|
-
category: "mxgraph.aws4.analytics",
|
|
175
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#8C4FFF;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.elasticsearch_service;"
|
|
176
|
-
},
|
|
177
|
-
"mxgraph.aws4.kinesis": {
|
|
178
|
-
category: "mxgraph.aws4.analytics",
|
|
179
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#8C4FFF;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.kinesis;"
|
|
180
|
-
},
|
|
181
|
-
"mxgraph.aws4.kinesis_data_analytics": {
|
|
182
|
-
category: "mxgraph.aws4.analytics",
|
|
183
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#8C4FFF;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.kinesis_data_analytics;"
|
|
184
|
-
},
|
|
185
|
-
"mxgraph.aws4.kinesis_data_firehose": {
|
|
186
|
-
category: "mxgraph.aws4.analytics",
|
|
187
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#8C4FFF;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.kinesis_data_firehose;"
|
|
188
|
-
},
|
|
189
|
-
"mxgraph.aws4.kinesis_data_streams": {
|
|
190
|
-
category: "mxgraph.aws4.analytics",
|
|
191
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#8C4FFF;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.kinesis_data_streams;"
|
|
192
|
-
},
|
|
193
|
-
"mxgraph.aws4.managed_service_for_apache_flink": {
|
|
194
|
-
category: "mxgraph.aws4.analytics",
|
|
195
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#8C4FFF;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.managed_service_for_apache_flink;"
|
|
196
|
-
},
|
|
197
|
-
"mxgraph.aws4.quicksight": {
|
|
198
|
-
category: "mxgraph.aws4.analytics",
|
|
199
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#8C4FFF;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.quicksight;"
|
|
200
|
-
},
|
|
201
|
-
"mxgraph.aws4.managed_streaming_for_kafka": {
|
|
202
|
-
category: "mxgraph.aws4.analytics",
|
|
203
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#8C4FFF;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.managed_streaming_for_kafka;"
|
|
204
|
-
},
|
|
205
|
-
"mxgraph.aws4.glue": {
|
|
206
|
-
category: "mxgraph.aws4.analytics",
|
|
207
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#8C4FFF;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.glue;"
|
|
208
|
-
},
|
|
209
|
-
// AWS / Compute
|
|
210
|
-
"mxgraph.aws4.compute": {
|
|
211
|
-
category: "mxgraph.aws4.compute",
|
|
212
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#ED7100;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.compute;"
|
|
213
|
-
},
|
|
214
|
-
"mxgraph.aws4.ec2": {
|
|
215
|
-
category: "mxgraph.aws4.compute",
|
|
216
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#ED7100;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.ec2;"
|
|
217
|
-
},
|
|
218
|
-
"mxgraph.aws4.lambda": {
|
|
219
|
-
category: "mxgraph.aws4.compute",
|
|
220
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#ED7100;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.lambda;"
|
|
221
|
-
},
|
|
222
|
-
// AWS / Containers
|
|
223
|
-
"mxgraph.aws4.containers": {
|
|
224
|
-
category: "mxgraph.aws4.containers",
|
|
225
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#ED7100;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.containers;"
|
|
226
|
-
},
|
|
227
|
-
"mxgraph.aws4.eks": {
|
|
228
|
-
category: "mxgraph.aws4.containers",
|
|
229
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#ED7100;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.eks;"
|
|
230
|
-
},
|
|
231
|
-
"mxgraph.aws4.ecr": {
|
|
232
|
-
category: "mxgraph.aws4.containers",
|
|
233
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#ED7100;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.ecr;"
|
|
234
|
-
},
|
|
235
|
-
"mxgraph.aws4.ecs": {
|
|
236
|
-
category: "mxgraph.aws4.containers",
|
|
237
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#ED7100;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.ecs;"
|
|
238
|
-
},
|
|
239
|
-
"mxgraph.aws4.fargate": {
|
|
240
|
-
category: "mxgraph.aws4.containers",
|
|
241
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#ED7100;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.fargate;"
|
|
242
|
-
},
|
|
243
|
-
// AWS / Network & Content Delivery
|
|
244
|
-
"mxgraph.aws4.api_gateway": {
|
|
245
|
-
category: "mxgraph.aws4.network",
|
|
246
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#8C4FFF;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.api_gateway;"
|
|
247
|
-
},
|
|
248
|
-
"mxgraph.aws4.cloudfront": {
|
|
249
|
-
category: "mxgraph.aws4.network",
|
|
250
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#8C4FFF;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.cloudfront;"
|
|
251
|
-
},
|
|
252
|
-
"mxgraph.aws4.route_53": {
|
|
253
|
-
category: "mxgraph.aws4.network",
|
|
254
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#8C4FFF;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.route_53;"
|
|
255
|
-
},
|
|
256
|
-
"mxgraph.aws4.vpc_privatelink": {
|
|
257
|
-
category: "mxgraph.aws4.network",
|
|
258
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#8C4FFF;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.vpc_privatelink;"
|
|
259
|
-
},
|
|
260
|
-
"mxgraph.aws4.vpc": {
|
|
261
|
-
category: "mxgraph.aws4.network",
|
|
262
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#8C4FFF;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.vpc;"
|
|
263
|
-
},
|
|
264
|
-
"mxgraph.aws4.elastic_load_balancing": {
|
|
265
|
-
category: "mxgraph.aws4.network",
|
|
266
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#8C4FFF;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.elastic_load_balancing;"
|
|
267
|
-
},
|
|
268
|
-
"mxgraph.aws4.endpoint": {
|
|
269
|
-
category: "mxgraph.aws4.network",
|
|
270
|
-
style: "sketch=0;outlineConnect=0;fontColor=#232F3E;gradientColor=none;fillColor=#8C4FFF;strokeColor=none;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;pointerEvents=1;shape=mxgraph.aws4.endpoint;"
|
|
271
|
-
},
|
|
272
|
-
"mxgraph.aws4.customer_gateway": {
|
|
273
|
-
category: "mxgraph.aws4.network",
|
|
274
|
-
style: "sketch=0;outlineConnect=0;fontColor=#232F3E;gradientColor=none;fillColor=#8C4FFF;strokeColor=none;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;pointerEvents=1;shape=mxgraph.aws4.customer_gateway;"
|
|
275
|
-
},
|
|
276
|
-
"mxgraph.aws4.application_load_balancer": {
|
|
277
|
-
category: "mxgraph.aws4.network",
|
|
278
|
-
style: "sketch=0;outlineConnect=0;fontColor=#232F3E;gradientColor=none;fillColor=#8C4FFF;strokeColor=none;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;pointerEvents=1;shape=mxgraph.aws4.application_load_balancer;"
|
|
279
|
-
},
|
|
280
|
-
"mxgraph.aws4.network_load_balancer": {
|
|
281
|
-
category: "mxgraph.aws4.network",
|
|
282
|
-
style: "sketch=0;outlineConnect=0;fontColor=#232F3E;gradientColor=none;fillColor=#8C4FFF;strokeColor=none;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;pointerEvents=1;shape=mxgraph.aws4.network_load_balancer;"
|
|
283
|
-
},
|
|
284
|
-
// AWS / Application Integration
|
|
285
|
-
"mxgraph.aws4.sns": {
|
|
286
|
-
category: "mxgraph.aws4.application_integration",
|
|
287
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#E7157B;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.sns;"
|
|
288
|
-
},
|
|
289
|
-
"mxgraph.aws4.sqs": {
|
|
290
|
-
category: "mxgraph.aws4.application_integration",
|
|
291
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#E7157B;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.sqs;"
|
|
292
|
-
},
|
|
293
|
-
"mxgraph.aws4.eventbridge": {
|
|
294
|
-
category: "mxgraph.aws4.application_integration",
|
|
295
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#E7157B;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.eventbridge;"
|
|
296
|
-
},
|
|
297
|
-
"mxgraph.aws4.managed_workflows_for_apache_airflow": {
|
|
298
|
-
category: "mxgraph.aws4.application_integration",
|
|
299
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#E7157B;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.managed_workflows_for_apache_airflow;"
|
|
300
|
-
},
|
|
301
|
-
// AWS / Database
|
|
302
|
-
"mxgraph.aws4.database": {
|
|
303
|
-
category: "mxgraph.aws4.database",
|
|
304
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#C925D1;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.database;"
|
|
305
|
-
},
|
|
306
|
-
"mxgraph.aws4.aurora": {
|
|
307
|
-
category: "mxgraph.aws4.database",
|
|
308
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#C925D1;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.aurora;"
|
|
309
|
-
},
|
|
310
|
-
"mxgraph.aws4.documentdb_with_mongodb_compatibility": {
|
|
311
|
-
category: "mxgraph.aws4.database",
|
|
312
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#C925D1;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.documentdb_with_mongodb_compatibility;"
|
|
313
|
-
},
|
|
314
|
-
"mxgraph.aws4.dynamodb": {
|
|
315
|
-
category: "mxgraph.aws4.database",
|
|
316
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#C925D1;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.dynamodb;"
|
|
317
|
-
},
|
|
318
|
-
"mxgraph.aws4.elasticache": {
|
|
319
|
-
category: "mxgraph.aws4.database",
|
|
320
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#C925D1;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.elasticache;"
|
|
321
|
-
},
|
|
322
|
-
"mxgraph.aws4.neptune": {
|
|
323
|
-
category: "mxgraph.aws4.database",
|
|
324
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#C925D1;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.neptune;"
|
|
325
|
-
},
|
|
326
|
-
"mxgraph.aws4.rds": {
|
|
327
|
-
category: "mxgraph.aws4.database",
|
|
328
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#C925D1;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.rds;"
|
|
329
|
-
},
|
|
330
|
-
"mxgraph.aws4.redshift": {
|
|
331
|
-
category: "mxgraph.aws4.database",
|
|
332
|
-
style: "sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#232F3E;fillColor=#C925D1;strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.redshift;"
|
|
333
|
-
},
|
|
334
|
-
"mxgraph.aws4.": {
|
|
335
|
-
category: "mxgraph.aws4.database",
|
|
336
|
-
style: ""
|
|
337
167
|
}
|
|
338
168
|
};
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
let socket = null;
|
|
343
|
-
let reconnectAttempts = 0;
|
|
344
|
-
let currentState = "disconnected";
|
|
345
|
-
let messageHandler = null;
|
|
346
|
-
let pingIntervalId = null;
|
|
347
|
-
let reconnectTimeoutId = null;
|
|
348
|
-
const {
|
|
349
|
-
url,
|
|
350
|
-
maxReconnectAttempts = 5,
|
|
351
|
-
reconnectDelay = 3e3,
|
|
352
|
-
pingInterval = 3e4
|
|
353
|
-
} = options;
|
|
354
|
-
const updateState = (newState) => {
|
|
355
|
-
if (currentState !== newState) {
|
|
356
|
-
console.debug(
|
|
357
|
-
`[websocketManager] State change: ${currentState} \u2192 ${newState}`
|
|
358
|
-
);
|
|
359
|
-
currentState = newState;
|
|
360
|
-
}
|
|
361
|
-
};
|
|
362
|
-
const connect = () => {
|
|
363
|
-
if (socket && socket.readyState === WebSocket.OPEN) {
|
|
364
|
-
console.debug("[websocketManager] Already connected");
|
|
365
|
-
return;
|
|
366
|
-
}
|
|
367
|
-
updateState("connecting");
|
|
368
|
-
try {
|
|
369
|
-
socket = new WebSocket(url);
|
|
370
|
-
socket.addEventListener("open", () => {
|
|
371
|
-
console.debug("[websocketManager] WebSocket connection established");
|
|
372
|
-
reconnectAttempts = 0;
|
|
373
|
-
updateState("connected");
|
|
374
|
-
startPing();
|
|
375
|
-
});
|
|
376
|
-
socket.addEventListener("message", (event) => {
|
|
377
|
-
try {
|
|
378
|
-
const parsedMessage = JSON.parse(event.data);
|
|
379
|
-
console.debug("[websocketManager] Received message:", parsedMessage);
|
|
380
|
-
if (messageHandler) {
|
|
381
|
-
messageHandler(parsedMessage);
|
|
382
|
-
}
|
|
383
|
-
} catch (error) {
|
|
384
|
-
console.error(
|
|
385
|
-
"[websocketManager] Failed to parse WebSocket message:",
|
|
386
|
-
error
|
|
387
|
-
);
|
|
388
|
-
}
|
|
389
|
-
});
|
|
390
|
-
socket.addEventListener("close", () => {
|
|
391
|
-
console.debug("[websocketManager] WebSocket connection closed");
|
|
392
|
-
updateState("disconnected");
|
|
393
|
-
stopPing();
|
|
394
|
-
attemptReconnect();
|
|
395
|
-
});
|
|
396
|
-
socket.addEventListener("error", (event) => {
|
|
397
|
-
console.error("[websocketManager] WebSocket error:", event);
|
|
398
|
-
updateState("disconnected");
|
|
399
|
-
});
|
|
400
|
-
} catch (error) {
|
|
401
|
-
console.error(
|
|
402
|
-
"[websocketManager] Failed to create WebSocket connection:",
|
|
403
|
-
error
|
|
404
|
-
);
|
|
405
|
-
updateState("disconnected");
|
|
406
|
-
}
|
|
407
|
-
};
|
|
408
|
-
const disconnect = () => {
|
|
409
|
-
if (reconnectTimeoutId) {
|
|
410
|
-
clearTimeout(reconnectTimeoutId);
|
|
411
|
-
reconnectTimeoutId = null;
|
|
412
|
-
}
|
|
413
|
-
stopPing();
|
|
414
|
-
reconnectAttempts = 0;
|
|
415
|
-
if (socket) {
|
|
416
|
-
console.debug("[websocketManager] Closing WebSocket connection");
|
|
417
|
-
socket.close();
|
|
418
|
-
socket = null;
|
|
419
|
-
}
|
|
420
|
-
updateState("disconnected");
|
|
421
|
-
};
|
|
422
|
-
const send = (message) => {
|
|
423
|
-
if (!socket || socket.readyState !== WebSocket.OPEN) {
|
|
424
|
-
console.warn(
|
|
425
|
-
"[websocketManager] Cannot send message: WebSocket not connected"
|
|
426
|
-
);
|
|
427
|
-
return;
|
|
428
|
-
}
|
|
429
|
-
try {
|
|
430
|
-
const serialized = JSON.stringify(message);
|
|
431
|
-
console.debug("[websocketManager] Sending message:", message);
|
|
432
|
-
socket.send(serialized);
|
|
433
|
-
} catch (error) {
|
|
434
|
-
console.error("[websocketManager] Failed to send message:", error);
|
|
435
|
-
}
|
|
436
|
-
};
|
|
437
|
-
const getState = () => currentState;
|
|
438
|
-
const onMessage = (handler) => {
|
|
439
|
-
messageHandler = handler;
|
|
440
|
-
};
|
|
441
|
-
const attemptReconnect = () => {
|
|
442
|
-
if (reconnectAttempts >= maxReconnectAttempts) {
|
|
443
|
-
console.error(
|
|
444
|
-
"[websocketManager] Max reconnection attempts reached. Giving up."
|
|
445
|
-
);
|
|
446
|
-
return;
|
|
447
|
-
}
|
|
448
|
-
reconnectAttempts++;
|
|
449
|
-
const delay = reconnectDelay * Math.pow(1.5, reconnectAttempts - 1);
|
|
450
|
-
console.log(
|
|
451
|
-
`[websocketManager] Attempting to reconnect in ${Math.round(delay / 1e3)} seconds... (attempt ${reconnectAttempts}/${maxReconnectAttempts})`
|
|
452
|
-
);
|
|
453
|
-
reconnectTimeoutId = window.setTimeout(() => {
|
|
454
|
-
reconnectTimeoutId = null;
|
|
455
|
-
connect();
|
|
456
|
-
}, delay);
|
|
457
|
-
};
|
|
458
|
-
const startPing = () => {
|
|
459
|
-
stopPing();
|
|
460
|
-
pingIntervalId = window.setInterval(() => {
|
|
461
|
-
if (getState() === "connected") {
|
|
462
|
-
send({ type: "PING" });
|
|
463
|
-
}
|
|
464
|
-
}, pingInterval);
|
|
465
|
-
};
|
|
466
|
-
const stopPing = () => {
|
|
467
|
-
if (pingIntervalId !== null) {
|
|
468
|
-
clearInterval(pingIntervalId);
|
|
469
|
-
pingIntervalId = null;
|
|
470
|
-
}
|
|
471
|
-
};
|
|
472
|
-
const ping = () => {
|
|
473
|
-
return new Promise((resolve) => {
|
|
474
|
-
if (getState() !== "connected") {
|
|
475
|
-
resolve(false);
|
|
476
|
-
return;
|
|
477
|
-
}
|
|
478
|
-
const timeoutId = setTimeout(() => {
|
|
479
|
-
resolve(false);
|
|
480
|
-
}, 5e3);
|
|
481
|
-
send({ type: "PING", message: "Ping from plugin" });
|
|
482
|
-
setTimeout(() => {
|
|
483
|
-
clearTimeout(timeoutId);
|
|
484
|
-
resolve(getState() === "connected");
|
|
485
|
-
}, 1e3);
|
|
486
|
-
});
|
|
487
|
-
};
|
|
488
|
-
return {
|
|
489
|
-
connect,
|
|
490
|
-
disconnect,
|
|
491
|
-
send,
|
|
492
|
-
getState,
|
|
493
|
-
onMessage,
|
|
494
|
-
ping
|
|
495
|
-
};
|
|
169
|
+
var runtimeCatalog = /* @__PURE__ */ new Map();
|
|
170
|
+
function setRuntimeCatalog(map) {
|
|
171
|
+
runtimeCatalog = map;
|
|
496
172
|
}
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
websocketPort: 3333,
|
|
501
|
-
serverUrl: ""
|
|
502
|
-
};
|
|
503
|
-
var PLUGIN_CONFIG_KEY = "drawio-mcp-plugin-config";
|
|
504
|
-
var cachedConfig = null;
|
|
505
|
-
async function fetchPluginConfig() {
|
|
506
|
-
if (cachedConfig) {
|
|
507
|
-
return cachedConfig;
|
|
173
|
+
function getShape(name) {
|
|
174
|
+
if (Object.prototype.hasOwnProperty.call(generalShapes, name)) {
|
|
175
|
+
return generalShapes[name];
|
|
508
176
|
}
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
177
|
+
const r = runtimeCatalog.get(name);
|
|
178
|
+
if (!r) return void 0;
|
|
179
|
+
return { category: r.category, style: r.style, title: r.name || void 0 };
|
|
180
|
+
}
|
|
181
|
+
function getCategories() {
|
|
182
|
+
const set = /* @__PURE__ */ new Set();
|
|
183
|
+
for (const s of Object.values(generalShapes)) set.add(s.category);
|
|
184
|
+
for (const r of runtimeCatalog.values()) set.add(r.category);
|
|
185
|
+
return [...set];
|
|
186
|
+
}
|
|
187
|
+
function getShapesByCategory(category) {
|
|
188
|
+
const out = [];
|
|
189
|
+
for (const [name, s] of Object.entries(generalShapes)) {
|
|
190
|
+
if (s.category === category) {
|
|
191
|
+
out.push({ id: name, title: s.title || name });
|
|
519
192
|
}
|
|
520
|
-
} catch (error) {
|
|
521
|
-
console.warn("[pluginConfig] Failed to fetch config from server:", error);
|
|
522
193
|
}
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
try {
|
|
527
|
-
const stored = localStorage.getItem(PLUGIN_CONFIG_KEY);
|
|
528
|
-
if (stored) {
|
|
529
|
-
const parsed = JSON.parse(stored);
|
|
530
|
-
const validated = validatePluginConfig(parsed);
|
|
531
|
-
if (validated.isValid && validated.config) {
|
|
532
|
-
return validated.config;
|
|
533
|
-
}
|
|
194
|
+
for (const [name, r] of runtimeCatalog) {
|
|
195
|
+
if (r.category === category) {
|
|
196
|
+
out.push({ id: name, title: r.name || name });
|
|
534
197
|
}
|
|
535
|
-
} catch (error) {
|
|
536
|
-
console.warn("[pluginConfig] Failed to read from localStorage:", error);
|
|
537
198
|
}
|
|
538
|
-
return
|
|
199
|
+
return out;
|
|
539
200
|
}
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
throw error;
|
|
201
|
+
|
|
202
|
+
// src/drawio-tools.ts
|
|
203
|
+
var active_document_id = null;
|
|
204
|
+
function normalize_optional_string(value) {
|
|
205
|
+
if (value === void 0 || value === null || value === "") {
|
|
206
|
+
return null;
|
|
547
207
|
}
|
|
208
|
+
return String(value);
|
|
548
209
|
}
|
|
549
|
-
function
|
|
550
|
-
|
|
551
|
-
|
|
210
|
+
function set_active_document_id(document_id) {
|
|
211
|
+
active_document_id = document_id;
|
|
212
|
+
}
|
|
213
|
+
function assert_target_document_active(target_document) {
|
|
214
|
+
const targetDocumentId = typeof target_document?.id === "string" && target_document.id.length > 0 ? target_document.id : null;
|
|
215
|
+
if (!targetDocumentId) {
|
|
216
|
+
throw new Error("`target_document.id` is required");
|
|
552
217
|
}
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
return { isValid: false, error: "websocketPort must be a number" };
|
|
218
|
+
if (!active_document_id) {
|
|
219
|
+
throw new Error("No active Draw.io document is registered in this tab");
|
|
556
220
|
}
|
|
557
|
-
if (
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
221
|
+
if (targetDocumentId !== active_document_id) {
|
|
222
|
+
throw new Error(
|
|
223
|
+
`Target document ${targetDocumentId} is no longer active in this Draw.io tab; call list-documents and retry`
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
function import_mermaid(ui2, options) {
|
|
228
|
+
const opts = options;
|
|
229
|
+
const mermaidSource = opts.mermaid_source;
|
|
230
|
+
const mode = opts.mode ?? "native";
|
|
231
|
+
const insertMode = opts.insert_mode ?? "add";
|
|
232
|
+
if (!mermaidSource || typeof mermaidSource !== "string") {
|
|
233
|
+
return Promise.resolve({
|
|
234
|
+
success: false,
|
|
235
|
+
message: "mermaid_source must be a non-empty string"
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
if (typeof ui2?.parseMermaidDiagram !== "function") {
|
|
239
|
+
return Promise.resolve({
|
|
240
|
+
success: false,
|
|
241
|
+
message: "ui.parseMermaidDiagram is not available; this Draw.io build does not expose Mermaid support."
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
const enableParser = mode === "native";
|
|
245
|
+
return new Promise((resolve) => {
|
|
246
|
+
let settled = false;
|
|
247
|
+
const settle = (result) => {
|
|
248
|
+
if (settled) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
settled = true;
|
|
252
|
+
resolve(result);
|
|
561
253
|
};
|
|
254
|
+
try {
|
|
255
|
+
ui2.parseMermaidDiagram(
|
|
256
|
+
mermaidSource,
|
|
257
|
+
void 0,
|
|
258
|
+
(xml) => {
|
|
259
|
+
if (!xml || typeof xml !== "string") {
|
|
260
|
+
settle({
|
|
261
|
+
success: false,
|
|
262
|
+
message: "Mermaid parser returned empty XML"
|
|
263
|
+
});
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
try {
|
|
267
|
+
const importResult = import_diagram(ui2, {
|
|
268
|
+
data: xml,
|
|
269
|
+
format: "xml",
|
|
270
|
+
mode: insertMode
|
|
271
|
+
});
|
|
272
|
+
if (!importResult.success) {
|
|
273
|
+
settle({
|
|
274
|
+
success: false,
|
|
275
|
+
message: `Mermaid converted, but inserting into the diagram failed: ${importResult.message}`
|
|
276
|
+
});
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
settle({
|
|
280
|
+
success: true,
|
|
281
|
+
mode,
|
|
282
|
+
message: importResult.message,
|
|
283
|
+
cells: importResult.cells,
|
|
284
|
+
xml
|
|
285
|
+
});
|
|
286
|
+
} catch (err) {
|
|
287
|
+
settle({
|
|
288
|
+
success: false,
|
|
289
|
+
message: `Insert after Mermaid conversion failed: ${err instanceof Error ? err.message : String(err)}`
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
(err) => {
|
|
294
|
+
settle({
|
|
295
|
+
success: false,
|
|
296
|
+
message: `Mermaid render failed: ${err?.message ?? String(err)}`
|
|
297
|
+
});
|
|
298
|
+
},
|
|
299
|
+
(err) => {
|
|
300
|
+
settle({
|
|
301
|
+
success: false,
|
|
302
|
+
message: `Mermaid parse error: ${err?.message ?? String(err)}`
|
|
303
|
+
});
|
|
304
|
+
},
|
|
305
|
+
enableParser
|
|
306
|
+
);
|
|
307
|
+
} catch (err) {
|
|
308
|
+
settle({
|
|
309
|
+
success: false,
|
|
310
|
+
message: `parseMermaidDiagram threw: ${err instanceof Error ? err.message : String(err)}`
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
function transform_NamedNodeMap_to_record(attributes) {
|
|
316
|
+
const tstr = Object.prototype.toString.call(attributes);
|
|
317
|
+
if (tstr !== "[object NamedNodeMap]") {
|
|
318
|
+
return attributes;
|
|
562
319
|
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
320
|
+
if (attributes.length === void 0) {
|
|
321
|
+
return attributes;
|
|
322
|
+
}
|
|
323
|
+
let transformed_attributes = {};
|
|
324
|
+
for (let i = 0; i < attributes.length; i++) {
|
|
325
|
+
const attr = attributes[i];
|
|
326
|
+
if (attr && attr.name && attr.value !== void 0) {
|
|
327
|
+
transformed_attributes[attr.name] = attr.value;
|
|
568
328
|
}
|
|
569
|
-
}
|
|
329
|
+
}
|
|
330
|
+
return transformed_attributes;
|
|
570
331
|
}
|
|
571
|
-
function
|
|
572
|
-
|
|
573
|
-
|
|
332
|
+
function transform_cells_NamedNodeMap_to_attributes(cell) {
|
|
333
|
+
if (cell.value.attributes && typeof cell.value.attributes === "object") {
|
|
334
|
+
const attributes = cell.value.attributes;
|
|
335
|
+
return transform_NamedNodeMap_to_record(attributes);
|
|
336
|
+
}
|
|
337
|
+
return {};
|
|
574
338
|
}
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
top: 0;
|
|
583
|
-
left: 0;
|
|
584
|
-
width: 100%;
|
|
585
|
-
height: 100%;
|
|
586
|
-
background-color: rgba(0, 0, 0, 0.5);
|
|
587
|
-
display: flex;
|
|
588
|
-
justify-content: center;
|
|
589
|
-
align-items: center;
|
|
590
|
-
z-index: 10000;
|
|
591
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
592
|
-
`;
|
|
593
|
-
container.addEventListener("click", (e) => {
|
|
594
|
-
if (e.target === container) {
|
|
595
|
-
e.stopPropagation();
|
|
339
|
+
function remove_circular_dependencies(obj, visited = /* @__PURE__ */ new WeakSet(), path = []) {
|
|
340
|
+
if (obj === null || typeof obj !== "object") {
|
|
341
|
+
return obj;
|
|
342
|
+
}
|
|
343
|
+
if (Array.isArray(obj)) {
|
|
344
|
+
if (visited.has(obj)) {
|
|
345
|
+
return `[Circular ${path.join(".")}]`;
|
|
596
346
|
}
|
|
597
|
-
|
|
598
|
-
|
|
347
|
+
visited.add(obj);
|
|
348
|
+
return obj.map(
|
|
349
|
+
(item, index) => remove_circular_dependencies(item, visited, [...path, `[${index}]`])
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
const tstr = Object.prototype.toString.call(obj);
|
|
353
|
+
if (tstr === "[object NamedNodeMap]") {
|
|
354
|
+
return transform_NamedNodeMap_to_record(obj);
|
|
355
|
+
}
|
|
356
|
+
if (tstr !== "[object Object]" && tstr !== "[object Element]") {
|
|
357
|
+
return obj;
|
|
358
|
+
}
|
|
359
|
+
if (visited.has(obj)) {
|
|
360
|
+
return `[Circular ${path.join(".")}]`;
|
|
361
|
+
}
|
|
362
|
+
visited.add(obj);
|
|
363
|
+
const result = {};
|
|
364
|
+
for (const key in obj) {
|
|
365
|
+
const value = obj[key];
|
|
366
|
+
if (typeof value !== "function" && key !== "children" && key !== "edges" && !key.startsWith("aria") && key !== "ownerDocument" && key !== "part" && key !== "classList" && key !== "childNodes" && key !== "shadowRoot" && key !== "innerHTML" && key !== "outerHTML" && key !== "scrollTop" && key !== "scrollLeft" && key !== "scrollWidth" && key !== "scrollHeight" && key !== "clientTop" && key !== "clientLeft" && key !== "clientWidth" && key !== "clientHeight" && key !== "onbeforecopy" && key !== "onbeforecut" && key !== "onbeforepaste" && key !== "onsearch" && key !== "elementTiming" && key !== "onfullscreenchange" && key !== "onfullscreenerror" && key !== "onwebkitfullscreenchange" && key !== "onwebkitfullscreenerror" && key !== "firstElementChild" && key !== "lastElementChild" && key !== "childElementCount" && key !== "previousElementSibling" && key !== "nextElementSibling" && key !== "currentCSSZoom" && key !== "parentNode" && key !== "parentElement" && key !== "firstChild" && key !== "lastChild" && key !== "previousSibling" && key !== "nextSibling" && key !== "nodeValue" && key !== "textContent" && key !== "ELEMENT_NODE" && key !== "ATTRIBUTE_NODE" && key !== "TEXT_NODE" && key !== "CDATA_SECTION_NODE" && key !== "ENTITY_REFERENCE_NODE" && key !== "ENTITY_NODE" && key !== "PROCESSING_INSTRUCTION_NODE" && key !== "COMMENT_NODE" && key !== "DOCUMENT_NODE" && key !== "DOCUMENT_TYPE_NODE" && key !== "DOCUMENT_FRAGMENT_NODE" && key !== "NOTATION_NODE" && key !== "DOCUMENT_POSITION_DISCONNECTED" && key !== "DOCUMENT_POSITION_PRECEDING" && key !== "DOCUMENT_POSITION_FOLLOWING" && key !== "DOCUMENT_POSITION_CONTAINS" && key !== "DOCUMENT_POSITION_CONTAINED_BY" && key !== "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC") {
|
|
367
|
+
let stripped_value = {};
|
|
368
|
+
if ((key === "parent" || key === "source" || key === "target") && value !== void 0 && value !== null) {
|
|
369
|
+
stripped_value = {
|
|
370
|
+
id: value.id
|
|
371
|
+
};
|
|
372
|
+
} else {
|
|
373
|
+
stripped_value = value;
|
|
374
|
+
}
|
|
375
|
+
result[key] = remove_circular_dependencies(stripped_value, visited, [
|
|
376
|
+
...path,
|
|
377
|
+
key
|
|
378
|
+
]);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return result;
|
|
599
382
|
}
|
|
600
|
-
function
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
|
607
|
-
max-width: 500px;
|
|
608
|
-
width: 90%;
|
|
609
|
-
max-height: 90vh;
|
|
610
|
-
overflow-y: auto;
|
|
611
|
-
position: relative;
|
|
612
|
-
`;
|
|
613
|
-
return content;
|
|
383
|
+
function ensure_pages_api(ui2, selector_name) {
|
|
384
|
+
if (!Array.isArray(ui2?.pages) || ui2.pages.length === 0) {
|
|
385
|
+
throw new Error(
|
|
386
|
+
`Draw.io pages are unavailable; cannot resolve \`${selector_name}\``
|
|
387
|
+
);
|
|
388
|
+
}
|
|
614
389
|
}
|
|
615
|
-
function
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
`;
|
|
625
|
-
const titleEl = document.createElement("h2");
|
|
626
|
-
titleEl.textContent = title;
|
|
627
|
-
titleEl.style.cssText = `
|
|
628
|
-
margin: 0;
|
|
629
|
-
font-size: 18px;
|
|
630
|
-
font-weight: 600;
|
|
631
|
-
color: #333;
|
|
632
|
-
`;
|
|
633
|
-
const closeBtn = document.createElement("button");
|
|
634
|
-
closeBtn.textContent = "\xD7";
|
|
635
|
-
closeBtn.style.cssText = `
|
|
636
|
-
background: none;
|
|
637
|
-
border: none;
|
|
638
|
-
font-size: 24px;
|
|
639
|
-
cursor: pointer;
|
|
640
|
-
padding: 0;
|
|
641
|
-
width: 24px;
|
|
642
|
-
height: 24px;
|
|
643
|
-
display: flex;
|
|
644
|
-
align-items: center;
|
|
645
|
-
justify-content: center;
|
|
646
|
-
color: #666;
|
|
647
|
-
border-radius: 4px;
|
|
648
|
-
`;
|
|
649
|
-
closeBtn.title = "Close";
|
|
650
|
-
closeBtn.addEventListener("mouseenter", () => {
|
|
651
|
-
closeBtn.style.backgroundColor = "#f5f5f5";
|
|
652
|
-
});
|
|
653
|
-
closeBtn.addEventListener("mouseleave", () => {
|
|
654
|
-
closeBtn.style.backgroundColor = "transparent";
|
|
655
|
-
});
|
|
656
|
-
closeBtn.addEventListener("click", onClose);
|
|
657
|
-
header.appendChild(titleEl);
|
|
658
|
-
header.appendChild(closeBtn);
|
|
659
|
-
return header;
|
|
390
|
+
function get_page_id(page) {
|
|
391
|
+
if (typeof page?.getId === "function") {
|
|
392
|
+
return String(page.getId());
|
|
393
|
+
}
|
|
394
|
+
const id = page?.id ?? page?.node?.getAttribute?.("id");
|
|
395
|
+
if (id === void 0 || id === null || id === "") {
|
|
396
|
+
throw new Error("Target page does not expose a stable ID");
|
|
397
|
+
}
|
|
398
|
+
return String(id);
|
|
660
399
|
}
|
|
661
|
-
function
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
400
|
+
function get_page_name(page, index) {
|
|
401
|
+
if (typeof page?.getName === "function") {
|
|
402
|
+
const name = page.getName();
|
|
403
|
+
if (name !== void 0 && name !== null && name !== "") {
|
|
404
|
+
return String(name);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
const fallback = page?.name ?? page?.node?.getAttribute?.("name");
|
|
408
|
+
if (fallback !== void 0 && fallback !== null && fallback !== "") {
|
|
409
|
+
return String(fallback);
|
|
410
|
+
}
|
|
411
|
+
return `Page-${index + 1}`;
|
|
672
412
|
}
|
|
673
|
-
function
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
section.style.cssText = `
|
|
677
|
-
margin-bottom: 24px;
|
|
678
|
-
padding: 16px;
|
|
679
|
-
background: #f8f9fa;
|
|
680
|
-
border-radius: 6px;
|
|
681
|
-
border: 1px solid #e9ecef;
|
|
682
|
-
`;
|
|
683
|
-
const title = document.createElement("div");
|
|
684
|
-
title.style.cssText = `
|
|
685
|
-
font-weight: 600;
|
|
686
|
-
margin-bottom: 8px;
|
|
687
|
-
color: #333;
|
|
688
|
-
`;
|
|
689
|
-
title.textContent = "Connection Status";
|
|
690
|
-
const statusIndicator = document.createElement("div");
|
|
691
|
-
statusIndicator.className = "status-indicator";
|
|
692
|
-
statusIndicator.style.cssText = `
|
|
693
|
-
display: flex;
|
|
694
|
-
align-items: center;
|
|
695
|
-
gap: 8px;
|
|
696
|
-
margin-bottom: 4px;
|
|
697
|
-
`;
|
|
698
|
-
const indicator = document.createElement("div");
|
|
699
|
-
indicator.style.cssText = `
|
|
700
|
-
width: 12px;
|
|
701
|
-
height: 12px;
|
|
702
|
-
border-radius: 50%;
|
|
703
|
-
flex-shrink: 0;
|
|
704
|
-
`;
|
|
705
|
-
switch (state.connectionState) {
|
|
706
|
-
case "connected":
|
|
707
|
-
indicator.style.backgroundColor = "#28a745";
|
|
708
|
-
break;
|
|
709
|
-
case "connecting":
|
|
710
|
-
indicator.style.backgroundColor = "#ffc107";
|
|
711
|
-
break;
|
|
712
|
-
case "disconnected":
|
|
713
|
-
indicator.style.backgroundColor = "#dc3545";
|
|
714
|
-
break;
|
|
413
|
+
function get_page_rename_probe(ui2, explicit_page) {
|
|
414
|
+
if (explicit_page) {
|
|
415
|
+
return explicit_page;
|
|
715
416
|
}
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
font-size: 14px;
|
|
724
|
-
color: #666;
|
|
725
|
-
`;
|
|
726
|
-
portDisplay.textContent = `Port: ${state.config.websocketPort}`;
|
|
727
|
-
section.appendChild(title);
|
|
728
|
-
section.appendChild(statusIndicator);
|
|
729
|
-
section.appendChild(portDisplay);
|
|
730
|
-
return section;
|
|
417
|
+
if (ui2?.currentPage) {
|
|
418
|
+
return ui2.currentPage;
|
|
419
|
+
}
|
|
420
|
+
if (Array.isArray(ui2?.pages) && ui2.pages.length > 0) {
|
|
421
|
+
return ui2.pages[0];
|
|
422
|
+
}
|
|
423
|
+
return null;
|
|
731
424
|
}
|
|
732
|
-
function
|
|
733
|
-
const
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
portGroup.style.cssText = `
|
|
738
|
-
margin-bottom: 16px;
|
|
739
|
-
`;
|
|
740
|
-
const label = document.createElement("label");
|
|
741
|
-
label.textContent = "WebSocket Port";
|
|
742
|
-
label.htmlFor = "mcp-port-input";
|
|
743
|
-
label.style.cssText = `
|
|
744
|
-
display: block;
|
|
745
|
-
margin-bottom: 6px;
|
|
746
|
-
font-weight: 500;
|
|
747
|
-
color: #333;
|
|
748
|
-
`;
|
|
749
|
-
const input = document.createElement("input");
|
|
750
|
-
input.id = "mcp-port-input";
|
|
751
|
-
input.type = "number";
|
|
752
|
-
input.min = "1024";
|
|
753
|
-
input.max = "65535";
|
|
754
|
-
input.value = state.formData.port;
|
|
755
|
-
input.style.cssText = `
|
|
756
|
-
width: 100%;
|
|
757
|
-
padding: 8px 12px;
|
|
758
|
-
border: 1px solid #ddd;
|
|
759
|
-
border-radius: 4px;
|
|
760
|
-
font-size: 14px;
|
|
761
|
-
box-sizing: border-box;
|
|
762
|
-
`;
|
|
763
|
-
if (state.errors.port) {
|
|
764
|
-
input.style.borderColor = "#dc3545";
|
|
765
|
-
}
|
|
766
|
-
input.addEventListener("input", (e) => {
|
|
767
|
-
const value = e.target.value;
|
|
768
|
-
window.dispatchEvent(
|
|
769
|
-
new CustomEvent("mcp-settings-message", {
|
|
770
|
-
detail: { type: "UPDATE_PORT", port: value }
|
|
771
|
-
})
|
|
425
|
+
function assert_page_rename_supported(ui2, action, explicit_page) {
|
|
426
|
+
const page = get_page_rename_probe(ui2, explicit_page);
|
|
427
|
+
if (typeof page?.setName !== "function") {
|
|
428
|
+
throw new Error(
|
|
429
|
+
`Draw.io page renaming is not supported in this version; cannot ${action}`
|
|
772
430
|
);
|
|
773
|
-
});
|
|
774
|
-
const hint = document.createElement("div");
|
|
775
|
-
hint.textContent = "Port must be between 1024 and 65535";
|
|
776
|
-
hint.style.cssText = `
|
|
777
|
-
font-size: 12px;
|
|
778
|
-
color: #666;
|
|
779
|
-
margin-top: 4px;
|
|
780
|
-
`;
|
|
781
|
-
if (state.errors.port) {
|
|
782
|
-
const error = document.createElement("div");
|
|
783
|
-
error.textContent = state.errors.port;
|
|
784
|
-
error.style.cssText = `
|
|
785
|
-
font-size: 12px;
|
|
786
|
-
color: #dc3545;
|
|
787
|
-
margin-top: 4px;
|
|
788
|
-
`;
|
|
789
|
-
portGroup.appendChild(error);
|
|
790
431
|
}
|
|
791
|
-
|
|
792
|
-
portGroup.appendChild(input);
|
|
793
|
-
portGroup.appendChild(hint);
|
|
794
|
-
section.appendChild(portGroup);
|
|
795
|
-
return section;
|
|
432
|
+
return page;
|
|
796
433
|
}
|
|
797
|
-
function
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
flex-wrap: wrap;
|
|
807
|
-
`;
|
|
808
|
-
const leftActions = document.createElement("div");
|
|
809
|
-
leftActions.style.cssText = `
|
|
810
|
-
display: flex;
|
|
811
|
-
gap: 8px;
|
|
812
|
-
flex-wrap: wrap;
|
|
813
|
-
`;
|
|
814
|
-
const rightActions = document.createElement("div");
|
|
815
|
-
rightActions.style.cssText = `
|
|
816
|
-
display: flex;
|
|
817
|
-
gap: 8px;
|
|
818
|
-
`;
|
|
819
|
-
const cancelBtn = createButton("Cancel", "ghost", () => {
|
|
820
|
-
window.dispatchEvent(
|
|
821
|
-
new CustomEvent("mcp-settings-message", {
|
|
822
|
-
detail: { type: "CLOSE" }
|
|
823
|
-
})
|
|
824
|
-
);
|
|
825
|
-
});
|
|
826
|
-
const saveBtn = createButton(
|
|
827
|
-
state.isSaving ? "Saving..." : "Save",
|
|
828
|
-
"primary",
|
|
829
|
-
() => {
|
|
830
|
-
window.dispatchEvent(
|
|
831
|
-
new CustomEvent("mcp-settings-message", {
|
|
832
|
-
detail: { type: "SAVE" }
|
|
833
|
-
})
|
|
834
|
-
);
|
|
835
|
-
},
|
|
836
|
-
state.isSaving
|
|
837
|
-
);
|
|
838
|
-
rightActions.appendChild(cancelBtn);
|
|
839
|
-
rightActions.appendChild(saveBtn);
|
|
840
|
-
footer.appendChild(leftActions);
|
|
841
|
-
footer.appendChild(rightActions);
|
|
842
|
-
return footer;
|
|
434
|
+
function rollback_created_page(ui2, page) {
|
|
435
|
+
if (!page || typeof ui2?.removePage !== "function") {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
try {
|
|
439
|
+
ui2.removePage(page);
|
|
440
|
+
} catch (error) {
|
|
441
|
+
console.warn("Could not roll back created page:", error);
|
|
442
|
+
}
|
|
843
443
|
}
|
|
844
|
-
function
|
|
845
|
-
const
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
transition: all 0.2s;
|
|
855
|
-
`;
|
|
856
|
-
switch (variant) {
|
|
857
|
-
case "primary":
|
|
858
|
-
btn.style.cssText += `
|
|
859
|
-
background-color: #007bff;
|
|
860
|
-
color: white;
|
|
861
|
-
border-color: #007bff;
|
|
862
|
-
`;
|
|
863
|
-
btn.addEventListener("mouseenter", () => {
|
|
864
|
-
if (!disabled) btn.style.backgroundColor = "#0056b3";
|
|
865
|
-
});
|
|
866
|
-
btn.addEventListener("mouseleave", () => {
|
|
867
|
-
if (!disabled) btn.style.backgroundColor = "#007bff";
|
|
868
|
-
});
|
|
869
|
-
break;
|
|
870
|
-
case "secondary":
|
|
871
|
-
btn.style.cssText += `
|
|
872
|
-
background-color: #6c757d;
|
|
873
|
-
color: white;
|
|
874
|
-
border-color: #6c757d;
|
|
875
|
-
`;
|
|
876
|
-
btn.addEventListener("mouseenter", () => {
|
|
877
|
-
if (!disabled) btn.style.backgroundColor = "#545b62";
|
|
878
|
-
});
|
|
879
|
-
btn.addEventListener("mouseleave", () => {
|
|
880
|
-
if (!disabled) btn.style.backgroundColor = "#6c757d";
|
|
881
|
-
});
|
|
882
|
-
break;
|
|
883
|
-
case "ghost":
|
|
884
|
-
btn.style.cssText += `
|
|
885
|
-
background-color: transparent;
|
|
886
|
-
color: #6c757d;
|
|
887
|
-
border-color: #6c757d;
|
|
888
|
-
`;
|
|
889
|
-
btn.addEventListener("mouseenter", () => {
|
|
890
|
-
if (!disabled) {
|
|
891
|
-
btn.style.backgroundColor = "#f8f9fa";
|
|
892
|
-
}
|
|
893
|
-
});
|
|
894
|
-
btn.addEventListener("mouseleave", () => {
|
|
895
|
-
if (!disabled) btn.style.backgroundColor = "transparent";
|
|
896
|
-
});
|
|
897
|
-
break;
|
|
444
|
+
function get_drawio_runtime_ctor(name) {
|
|
445
|
+
const maybeWindow = typeof window === "undefined" ? void 0 : window;
|
|
446
|
+
const globalCtor = globalThis?.[name] ?? maybeWindow?.[name];
|
|
447
|
+
return typeof globalCtor === "function" ? globalCtor : null;
|
|
448
|
+
}
|
|
449
|
+
function change_page_without_switch(ui2, page, index) {
|
|
450
|
+
const ChangePage = get_drawio_runtime_ctor("ChangePage");
|
|
451
|
+
const execute = ui2?.editor?.graph?.model?.execute;
|
|
452
|
+
if (typeof ChangePage !== "function" || typeof execute !== "function") {
|
|
453
|
+
return false;
|
|
898
454
|
}
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
455
|
+
execute.call(ui2.editor.graph.model, new ChangePage(ui2, page, page, index, true));
|
|
456
|
+
return true;
|
|
457
|
+
}
|
|
458
|
+
function insert_page_without_switch(ui2, page, index) {
|
|
459
|
+
return change_page_without_switch(ui2, page, index);
|
|
460
|
+
}
|
|
461
|
+
function move_page_without_switch(ui2, oldIndex, newIndex) {
|
|
462
|
+
if (typeof ui2?.movePage === "function") {
|
|
463
|
+
ui2.movePage(oldIndex, newIndex);
|
|
464
|
+
return true;
|
|
904
465
|
}
|
|
905
|
-
|
|
906
|
-
|
|
466
|
+
const MovePage = get_drawio_runtime_ctor("MovePage");
|
|
467
|
+
const execute = ui2?.editor?.graph?.model?.execute;
|
|
468
|
+
if (typeof MovePage !== "function" || typeof execute !== "function") {
|
|
469
|
+
return false;
|
|
470
|
+
}
|
|
471
|
+
execute.call(ui2.editor.graph.model, new MovePage(ui2, oldIndex, newIndex));
|
|
472
|
+
return true;
|
|
907
473
|
}
|
|
908
|
-
function
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
474
|
+
function rename_page_without_switch(ui2, page, name) {
|
|
475
|
+
const RenamePage = get_drawio_runtime_ctor("RenamePage");
|
|
476
|
+
const execute = ui2?.editor?.graph?.model?.execute;
|
|
477
|
+
if (typeof RenamePage === "function" && typeof execute === "function") {
|
|
478
|
+
execute.call(ui2.editor.graph.model, new RenamePage(ui2, page, name));
|
|
479
|
+
return true;
|
|
480
|
+
}
|
|
481
|
+
if (typeof page?.setName !== "function") {
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
484
|
+
page.setName(name);
|
|
485
|
+
return true;
|
|
486
|
+
}
|
|
487
|
+
function find_page_index_by_id(ui2, pageId) {
|
|
488
|
+
if (!Array.isArray(ui2?.pages)) {
|
|
489
|
+
return -1;
|
|
490
|
+
}
|
|
491
|
+
return ui2.pages.findIndex((page) => {
|
|
492
|
+
try {
|
|
493
|
+
return get_page_id(page) === pageId;
|
|
494
|
+
} catch {
|
|
495
|
+
return false;
|
|
916
496
|
}
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
function move_page_to_end(ui2, page) {
|
|
500
|
+
const pageId = get_page_id(page);
|
|
501
|
+
const currentIndex = find_page_index_by_id(ui2, pageId);
|
|
502
|
+
if (currentIndex === -1) {
|
|
503
|
+
throw new Error("Copied page is not present in the page list");
|
|
504
|
+
}
|
|
505
|
+
const lastIndex = ui2.pages.length - 1;
|
|
506
|
+
if (currentIndex === lastIndex) {
|
|
507
|
+
return currentIndex;
|
|
508
|
+
}
|
|
509
|
+
if (!move_page_without_switch(ui2, currentIndex, lastIndex)) {
|
|
510
|
+
throw new Error(
|
|
511
|
+
"Draw.io page reordering is not supported in this version; cannot move the copied page to the end"
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
const movedIndex = find_page_index_by_id(ui2, pageId);
|
|
515
|
+
if (movedIndex !== lastIndex) {
|
|
516
|
+
throw new Error("Failed to move the copied page to the end");
|
|
517
|
+
}
|
|
518
|
+
return movedIndex;
|
|
519
|
+
}
|
|
520
|
+
function can_insert_page_without_switch(ui2) {
|
|
521
|
+
const graph = ui2?.editor?.graph;
|
|
522
|
+
if (!graph || typeof graph.isEnabled !== "function" || graph.isEnabled() !== true) {
|
|
523
|
+
return false;
|
|
524
|
+
}
|
|
525
|
+
if (typeof graph.isEditing === "function" && graph.isEditing() === true) {
|
|
526
|
+
graph.stopEditing?.(false);
|
|
527
|
+
}
|
|
528
|
+
return true;
|
|
529
|
+
}
|
|
530
|
+
function serialize_page_info(ui2, page, index, isCurrent = (() => {
|
|
531
|
+
if (ui2?.currentPage === void 0 || ui2?.currentPage === null) {
|
|
532
|
+
return false;
|
|
533
|
+
}
|
|
534
|
+
try {
|
|
535
|
+
return get_page_id(page) === get_page_id(ui2.currentPage);
|
|
536
|
+
} catch {
|
|
537
|
+
return false;
|
|
538
|
+
}
|
|
539
|
+
})()) {
|
|
540
|
+
return {
|
|
541
|
+
index,
|
|
542
|
+
id: get_page_id(page),
|
|
543
|
+
name: get_page_name(page, index),
|
|
544
|
+
is_current: isCurrent
|
|
917
545
|
};
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
return container;
|
|
546
|
+
}
|
|
547
|
+
function serialize_document_info(ui2, document_id) {
|
|
548
|
+
const file = ui2?.getCurrentFile?.();
|
|
549
|
+
const pages = Array.isArray(ui2?.pages) ? ui2.pages : [];
|
|
550
|
+
const currentId = ui2?.currentPage !== void 0 && ui2?.currentPage !== null ? get_page_id(ui2.currentPage) : null;
|
|
551
|
+
const currentIndex = pages.findIndex(
|
|
552
|
+
(page) => currentId !== null && get_page_id(page) === currentId
|
|
553
|
+
);
|
|
554
|
+
return {
|
|
555
|
+
id: document_id,
|
|
556
|
+
title: normalize_optional_string(file?.getTitle?.()),
|
|
557
|
+
mode: normalize_optional_string(file?.getMode?.()),
|
|
558
|
+
hash: normalize_optional_string(file?.getHash?.()),
|
|
559
|
+
file_url: normalize_optional_string(file?.getFileUrl?.()),
|
|
560
|
+
page_count: pages.length,
|
|
561
|
+
current_page: currentIndex >= 0 && ui2?.currentPage ? serialize_page_info(ui2, ui2.currentPage, currentIndex, true) : null
|
|
935
562
|
};
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
}
|
|
948
|
-
break;
|
|
949
|
-
case "CLOSE":
|
|
950
|
-
actions2.onClose();
|
|
951
|
-
break;
|
|
952
|
-
}
|
|
953
|
-
};
|
|
954
|
-
window.addEventListener(
|
|
955
|
-
"mcp-settings-message",
|
|
956
|
-
handleMessage
|
|
563
|
+
}
|
|
564
|
+
function resolve_target_page(ui2, target_page, selector_name = "target_page") {
|
|
565
|
+
ensure_pages_api(ui2, selector_name);
|
|
566
|
+
if (!target_page || typeof target_page !== "object") {
|
|
567
|
+
throw new Error(`\`${selector_name}\` is required`);
|
|
568
|
+
}
|
|
569
|
+
const hasIndex = Number.isInteger(target_page.index);
|
|
570
|
+
const hasId = typeof target_page.id === "string" && target_page.id.length > 0;
|
|
571
|
+
if (hasIndex === hasId) {
|
|
572
|
+
throw new Error(
|
|
573
|
+
`\`${selector_name}\` must include exactly one of \`index\` or \`id\``
|
|
957
574
|
);
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
);
|
|
966
|
-
observer.disconnect();
|
|
967
|
-
}
|
|
968
|
-
});
|
|
969
|
-
});
|
|
970
|
-
});
|
|
971
|
-
if (container.parentNode) {
|
|
972
|
-
observer.observe(container.parentNode, { childList: true });
|
|
973
|
-
}
|
|
974
|
-
};
|
|
975
|
-
const validateAndSave = () => {
|
|
976
|
-
const portNum = parseInt(currentState.formData.port, 10);
|
|
977
|
-
if (isNaN(portNum)) {
|
|
978
|
-
currentState.errors.port = "Port must be a number";
|
|
979
|
-
return false;
|
|
575
|
+
}
|
|
576
|
+
if (hasIndex) {
|
|
577
|
+
const index2 = Number(target_page.index);
|
|
578
|
+
if (index2 < 0 || index2 >= ui2.pages.length) {
|
|
579
|
+
throw new Error(
|
|
580
|
+
`\`${selector_name}.index\` ${index2} is out of range for ${ui2.pages.length} pages`
|
|
581
|
+
);
|
|
980
582
|
}
|
|
981
|
-
|
|
982
|
-
|
|
583
|
+
return {
|
|
584
|
+
page: ui2.pages[index2],
|
|
585
|
+
index: index2
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
const index = ui2.pages.findIndex((page) => {
|
|
589
|
+
try {
|
|
590
|
+
return get_page_id(page) === target_page.id;
|
|
591
|
+
} catch {
|
|
983
592
|
return false;
|
|
984
593
|
}
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
return true;
|
|
594
|
+
});
|
|
595
|
+
if (index === -1) {
|
|
596
|
+
throw new Error(`Page with ID ${target_page.id} was not found`);
|
|
597
|
+
}
|
|
598
|
+
return {
|
|
599
|
+
page: ui2.pages[index],
|
|
600
|
+
index
|
|
993
601
|
};
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
602
|
+
}
|
|
603
|
+
function switch_to_target_page(ui2, page) {
|
|
604
|
+
const currentId = ui2?.currentPage !== void 0 && ui2?.currentPage !== null ? get_page_id(ui2.currentPage) : null;
|
|
605
|
+
const targetId = get_page_id(page);
|
|
606
|
+
if (currentId !== null && currentId === targetId) {
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
if (typeof ui2?.selectPage !== "function") {
|
|
610
|
+
throw new Error("Draw.io page switching is not supported in this version");
|
|
611
|
+
}
|
|
612
|
+
ui2.selectPage(page);
|
|
613
|
+
}
|
|
614
|
+
function create_noop_execution(ui2, page, index) {
|
|
615
|
+
return {
|
|
616
|
+
ui: ui2,
|
|
617
|
+
page,
|
|
618
|
+
index,
|
|
619
|
+
is_background: false,
|
|
620
|
+
did_change: () => false,
|
|
621
|
+
cleanup: () => {
|
|
622
|
+
}
|
|
1002
623
|
};
|
|
1003
|
-
return dialogProxy;
|
|
1004
624
|
}
|
|
1005
|
-
function
|
|
1006
|
-
if (!
|
|
1007
|
-
|
|
625
|
+
function sync_live_current_page_state(ui2) {
|
|
626
|
+
if (!ui2?.currentPage || !ui2?.editor?.graph) {
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
const liveGraph = ui2.editor.graph;
|
|
630
|
+
const model = typeof liveGraph?.getModel === "function" ? liveGraph.getModel() : null;
|
|
631
|
+
if (!model?.root) {
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
ui2.currentPage.root = model.root;
|
|
635
|
+
ui2.currentPage.graphModelNode = null;
|
|
636
|
+
if (typeof liveGraph?.getViewState === "function") {
|
|
637
|
+
ui2.currentPage.viewState = liveGraph.getViewState();
|
|
1008
638
|
}
|
|
639
|
+
ui2.currentPage.needsUpdate = true;
|
|
1009
640
|
}
|
|
1010
|
-
function
|
|
1011
|
-
|
|
1012
|
-
|
|
641
|
+
function create_background_page_ui(ui2, page) {
|
|
642
|
+
const runtimeWindow = globalThis.window;
|
|
643
|
+
const runtimeDocument = globalThis.document;
|
|
644
|
+
const liveGraph = ui2?.editor?.graph;
|
|
645
|
+
if (!liveGraph || typeof liveGraph?.getStylesheet !== "function" || typeof ui2?.createTemporaryGraph !== "function" || typeof ui2?.updatePageRoot !== "function") {
|
|
646
|
+
return null;
|
|
647
|
+
}
|
|
648
|
+
const resolvedPage = ui2.updatePageRoot(page);
|
|
649
|
+
const tempGraph = ui2.createTemporaryGraph(liveGraph.getStylesheet());
|
|
650
|
+
if (!tempGraph || typeof tempGraph?.getModel !== "function") {
|
|
651
|
+
return null;
|
|
652
|
+
}
|
|
653
|
+
const tempModel = tempGraph.getModel();
|
|
654
|
+
if (!tempModel || typeof tempModel?.setRoot !== "function") {
|
|
655
|
+
return null;
|
|
656
|
+
}
|
|
657
|
+
let didChange = false;
|
|
658
|
+
const mxEvent = runtimeWindow?.mxEvent;
|
|
659
|
+
const changeEventName = mxEvent?.CHANGE ?? "change";
|
|
660
|
+
const changeListener = () => {
|
|
661
|
+
didChange = true;
|
|
662
|
+
};
|
|
663
|
+
if (typeof tempModel?.addListener === "function") {
|
|
664
|
+
tempModel.addListener(changeEventName, changeListener);
|
|
665
|
+
}
|
|
666
|
+
let containerAttached = false;
|
|
667
|
+
const cleanup = () => {
|
|
668
|
+
if (typeof tempModel?.removeListener === "function") {
|
|
669
|
+
tempModel.removeListener(changeListener);
|
|
670
|
+
}
|
|
671
|
+
if (typeof tempGraph?.destroy === "function") {
|
|
672
|
+
try {
|
|
673
|
+
tempGraph.destroy();
|
|
674
|
+
} catch (error) {
|
|
675
|
+
console.warn("Could not destroy temporary draw.io graph:", error);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
if (containerAttached && tempGraph.container?.parentNode) {
|
|
679
|
+
try {
|
|
680
|
+
tempGraph.container.parentNode.removeChild(tempGraph.container);
|
|
681
|
+
} catch (error) {
|
|
682
|
+
console.warn("Could not detach temporary draw.io graph container:", error);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
};
|
|
686
|
+
try {
|
|
687
|
+
if (runtimeDocument?.body && tempGraph.container && tempGraph.container.parentNode == null) {
|
|
688
|
+
runtimeDocument.body.appendChild(tempGraph.container);
|
|
689
|
+
containerAttached = true;
|
|
690
|
+
}
|
|
691
|
+
tempModel.setRoot(resolvedPage.root);
|
|
692
|
+
if (typeof tempGraph?.setViewState === "function" && resolvedPage.viewState) {
|
|
693
|
+
tempGraph.setViewState(resolvedPage.viewState);
|
|
694
|
+
} else if (resolvedPage.viewState?.defaultParent && typeof tempGraph?.setDefaultParent === "function") {
|
|
695
|
+
tempGraph.setDefaultParent(resolvedPage.viewState.defaultParent);
|
|
696
|
+
}
|
|
697
|
+
if (typeof tempGraph?.setAdaptiveColors === "function") {
|
|
698
|
+
tempGraph.setAdaptiveColors(resolvedPage.viewState?.adaptiveColors ?? null);
|
|
699
|
+
}
|
|
700
|
+
if (typeof tempGraph?.setBackgroundImage === "function") {
|
|
701
|
+
tempGraph.setBackgroundImage(resolvedPage.viewState?.backgroundImage ?? null);
|
|
702
|
+
}
|
|
703
|
+
if (resolvedPage.viewState?.background !== void 0) {
|
|
704
|
+
tempGraph.background = resolvedPage.viewState.background;
|
|
705
|
+
}
|
|
706
|
+
} catch (error) {
|
|
707
|
+
cleanup();
|
|
708
|
+
throw error;
|
|
1013
709
|
}
|
|
710
|
+
const scopedUi = Object.create(ui2);
|
|
711
|
+
scopedUi.editor = Object.create(ui2.editor);
|
|
712
|
+
scopedUi.editor.graph = tempGraph;
|
|
713
|
+
scopedUi.currentPage = resolvedPage;
|
|
714
|
+
return {
|
|
715
|
+
ui: scopedUi,
|
|
716
|
+
page: resolvedPage,
|
|
717
|
+
index: -1,
|
|
718
|
+
is_background: true,
|
|
719
|
+
did_change: () => didChange,
|
|
720
|
+
cleanup
|
|
721
|
+
};
|
|
1014
722
|
}
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
if (tstr !== "[object NamedNodeMap]") {
|
|
1020
|
-
return attributes;
|
|
723
|
+
function create_page_export_graph(ui2, sourceGraph, page) {
|
|
724
|
+
const runtimeDocument = globalThis.document;
|
|
725
|
+
if (!page || typeof ui2?.createTemporaryGraph !== "function" || typeof ui2?.updatePageRoot !== "function" || typeof sourceGraph?.getStylesheet !== "function") {
|
|
726
|
+
return null;
|
|
1021
727
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
728
|
+
const resolvedPage = ui2.updatePageRoot(page);
|
|
729
|
+
const tempGraph = ui2.createTemporaryGraph(sourceGraph.getStylesheet());
|
|
730
|
+
const tempModel = tempGraph?.getModel?.();
|
|
731
|
+
if (!tempGraph || !tempModel || typeof tempModel?.setRoot !== "function") {
|
|
732
|
+
return null;
|
|
1024
733
|
}
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
734
|
+
const pageIndex = Array.isArray(ui2?.pages) ? ui2.pages.findIndex((candidate) => {
|
|
735
|
+
try {
|
|
736
|
+
return get_page_id(candidate) === get_page_id(resolvedPage);
|
|
737
|
+
} catch {
|
|
738
|
+
return false;
|
|
1030
739
|
}
|
|
740
|
+
}) : -1;
|
|
741
|
+
const fallbackGetGlobalVariable = typeof sourceGraph?.getGlobalVariable === "function" ? sourceGraph.getGlobalVariable : null;
|
|
742
|
+
if (fallbackGetGlobalVariable) {
|
|
743
|
+
tempGraph.getGlobalVariable = function(name) {
|
|
744
|
+
if (name === "pagenumber" && pageIndex >= 0) {
|
|
745
|
+
return pageIndex + 1;
|
|
746
|
+
}
|
|
747
|
+
if (name === "page") {
|
|
748
|
+
return get_page_name(resolvedPage, Math.max(pageIndex, 0));
|
|
749
|
+
}
|
|
750
|
+
return fallbackGetGlobalVariable.apply(this, arguments);
|
|
751
|
+
};
|
|
1031
752
|
}
|
|
1032
|
-
|
|
753
|
+
if (typeof tempGraph?.setAdaptiveColors === "function") {
|
|
754
|
+
tempGraph.setAdaptiveColors(resolvedPage.viewState?.adaptiveColors ?? null);
|
|
755
|
+
}
|
|
756
|
+
if (typeof tempGraph?.setBackgroundImage === "function") {
|
|
757
|
+
tempGraph.setBackgroundImage(resolvedPage.viewState?.backgroundImage ?? null);
|
|
758
|
+
}
|
|
759
|
+
if (resolvedPage.viewState?.background !== void 0) {
|
|
760
|
+
tempGraph.background = resolvedPage.viewState.background;
|
|
761
|
+
}
|
|
762
|
+
let containerAttached = false;
|
|
763
|
+
try {
|
|
764
|
+
if (runtimeDocument?.body && tempGraph.container && tempGraph.container.parentNode == null) {
|
|
765
|
+
runtimeDocument.body.appendChild(tempGraph.container);
|
|
766
|
+
containerAttached = true;
|
|
767
|
+
}
|
|
768
|
+
} catch (error) {
|
|
769
|
+
console.warn(
|
|
770
|
+
"Could not attach temporary draw.io export graph container:",
|
|
771
|
+
error
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
tempModel.setRoot(resolvedPage.root);
|
|
775
|
+
return {
|
|
776
|
+
graph: tempGraph,
|
|
777
|
+
cleanup: () => {
|
|
778
|
+
if (typeof tempGraph?.destroy === "function") {
|
|
779
|
+
try {
|
|
780
|
+
tempGraph.destroy();
|
|
781
|
+
} catch (error) {
|
|
782
|
+
console.warn("Could not destroy temporary draw.io export graph:", error);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
if (containerAttached && tempGraph.container?.parentNode) {
|
|
786
|
+
try {
|
|
787
|
+
tempGraph.container.parentNode.removeChild(tempGraph.container);
|
|
788
|
+
} catch (error) {
|
|
789
|
+
console.warn(
|
|
790
|
+
"Could not detach temporary draw.io export graph container:",
|
|
791
|
+
error
|
|
792
|
+
);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
};
|
|
1033
797
|
}
|
|
1034
|
-
function
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
798
|
+
function prepare_target_page_execution(ui2, target_page, options = {}) {
|
|
799
|
+
const resolved = resolve_target_page(ui2, target_page);
|
|
800
|
+
const currentId = ui2?.currentPage !== void 0 && ui2?.currentPage !== null ? get_page_id(ui2.currentPage) : null;
|
|
801
|
+
const targetId = get_page_id(resolved.page);
|
|
802
|
+
if (options.prefer_background && currentId !== null && currentId !== targetId) {
|
|
803
|
+
const backgroundExecution = create_background_page_ui(ui2, resolved.page);
|
|
804
|
+
if (backgroundExecution) {
|
|
805
|
+
if (options.sync_live_current_page_state) {
|
|
806
|
+
sync_live_current_page_state(ui2);
|
|
807
|
+
}
|
|
808
|
+
return {
|
|
809
|
+
...backgroundExecution,
|
|
810
|
+
index: resolved.index
|
|
811
|
+
};
|
|
812
|
+
}
|
|
1038
813
|
}
|
|
1039
|
-
|
|
814
|
+
if (currentId !== targetId) {
|
|
815
|
+
switch_to_target_page(ui2, resolved.page);
|
|
816
|
+
}
|
|
817
|
+
return create_noop_execution(ui2, resolved.page, resolved.index);
|
|
1040
818
|
}
|
|
1041
|
-
function
|
|
1042
|
-
if (
|
|
1043
|
-
return
|
|
819
|
+
function mark_page_execution_modified(ui2, execution) {
|
|
820
|
+
if (!execution.is_background || !execution.did_change()) {
|
|
821
|
+
return;
|
|
1044
822
|
}
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
823
|
+
const page = execution.page;
|
|
824
|
+
page.needsUpdate = true;
|
|
825
|
+
page.graphModelNode = null;
|
|
826
|
+
if (typeof page?.setDiagramModified === "function") {
|
|
827
|
+
page.setDiagramModified(true);
|
|
828
|
+
}
|
|
829
|
+
try {
|
|
830
|
+
ui2.getCurrentFile?.()?.fileChanged?.();
|
|
831
|
+
} catch (error) {
|
|
832
|
+
console.warn("Could not notify draw.io file change after background mutation:", error);
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
function get_selected_cell(ui2) {
|
|
836
|
+
return ui2.editor.graph.getSelectionCell() || "no cell selected";
|
|
837
|
+
}
|
|
838
|
+
function list_pages(ui2) {
|
|
839
|
+
ensure_pages_api(ui2, "pages");
|
|
840
|
+
return ui2.pages.map(
|
|
841
|
+
(page, index) => serialize_page_info(ui2, page, index)
|
|
842
|
+
);
|
|
843
|
+
}
|
|
844
|
+
function get_current_page(ui2) {
|
|
845
|
+
ensure_pages_api(ui2, "current page");
|
|
846
|
+
const currentId = ui2?.currentPage !== void 0 && ui2?.currentPage !== null ? get_page_id(ui2.currentPage) : null;
|
|
847
|
+
const currentIndex = ui2.pages.findIndex(
|
|
848
|
+
(page) => currentId !== null && get_page_id(page) === currentId
|
|
849
|
+
);
|
|
850
|
+
if (currentIndex === -1 || !ui2.currentPage) {
|
|
851
|
+
throw new Error("Current page is not available");
|
|
852
|
+
}
|
|
853
|
+
return serialize_page_info(ui2, ui2.currentPage, currentIndex, true);
|
|
854
|
+
}
|
|
855
|
+
function create_page(ui2, options) {
|
|
856
|
+
if (typeof ui2?.insertPage !== "function") {
|
|
857
|
+
throw new Error("Draw.io page creation is not supported in this version");
|
|
858
|
+
}
|
|
859
|
+
if (options.name) {
|
|
860
|
+
assert_page_rename_supported(ui2, "create a named page");
|
|
861
|
+
}
|
|
862
|
+
const pageIndex = Array.isArray(ui2.pages) ? ui2.pages.length : 0;
|
|
863
|
+
let newPage = null;
|
|
864
|
+
if (typeof ui2?.createPage === "function" && typeof ui2?.createPageId === "function" && can_insert_page_without_switch(ui2)) {
|
|
865
|
+
newPage = ui2.createPage(options.name ?? null, ui2.createPageId());
|
|
866
|
+
if (!insert_page_without_switch(ui2, newPage, pageIndex)) {
|
|
867
|
+
newPage = null;
|
|
1048
868
|
}
|
|
1049
|
-
visited.add(obj);
|
|
1050
|
-
return obj.map(
|
|
1051
|
-
(item, index) => remove_circular_dependencies(item, visited, [...path, `[${index}]`])
|
|
1052
|
-
);
|
|
1053
869
|
}
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
870
|
+
if (!newPage) {
|
|
871
|
+
newPage = ui2.insertPage(null, pageIndex);
|
|
872
|
+
if (!newPage) {
|
|
873
|
+
throw new Error("Failed to create a new page");
|
|
874
|
+
}
|
|
875
|
+
if (options.name) {
|
|
876
|
+
try {
|
|
877
|
+
assert_page_rename_supported(ui2, "create a named page", newPage);
|
|
878
|
+
newPage.setName(options.name);
|
|
879
|
+
} catch (error) {
|
|
880
|
+
rollback_created_page(ui2, newPage);
|
|
881
|
+
throw error;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
1057
884
|
}
|
|
1058
|
-
|
|
1059
|
-
|
|
885
|
+
const newPageId = get_page_id(newPage);
|
|
886
|
+
const index = Array.isArray(ui2.pages) ? ui2.pages.findIndex((page) => get_page_id(page) === newPageId) : -1;
|
|
887
|
+
if (index === -1) {
|
|
888
|
+
throw new Error("Created page is not present in the page list");
|
|
1060
889
|
}
|
|
1061
|
-
|
|
1062
|
-
|
|
890
|
+
return serialize_page_info(ui2, newPage, index);
|
|
891
|
+
}
|
|
892
|
+
function copy_page(ui2, options) {
|
|
893
|
+
const page_selector = typeof options.page === "number" ? { index: options.page } : options.page;
|
|
894
|
+
const resolved = resolve_target_page(ui2, page_selector, "page");
|
|
895
|
+
if (typeof ui2?.duplicatePage !== "function") {
|
|
896
|
+
throw new Error("Draw.io page copying is not supported in this version");
|
|
897
|
+
}
|
|
898
|
+
const currentId = ui2?.currentPage !== void 0 && ui2?.currentPage !== null ? get_page_id(ui2.currentPage) : null;
|
|
899
|
+
const requestedName = typeof options.name === "string" && options.name.length > 0 ? options.name : void 0;
|
|
900
|
+
const copiedPage = ui2.duplicatePage(resolved.page, requestedName);
|
|
901
|
+
if (!copiedPage) {
|
|
902
|
+
throw new Error("Failed to copy the target page");
|
|
903
|
+
}
|
|
904
|
+
if (requestedName && get_page_name(copiedPage, resolved.index) !== requestedName) {
|
|
905
|
+
assert_page_rename_supported(ui2, "rename the copied page", copiedPage);
|
|
906
|
+
if (!rename_page_without_switch(ui2, copiedPage, requestedName)) {
|
|
907
|
+
throw new Error("Failed to rename the copied page");
|
|
908
|
+
}
|
|
1063
909
|
}
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
stripped_value = {
|
|
1072
|
-
id: value.id
|
|
1073
|
-
};
|
|
1074
|
-
} else {
|
|
1075
|
-
stripped_value = value;
|
|
910
|
+
const index = move_page_to_end(ui2, copiedPage);
|
|
911
|
+
if (currentId !== null) {
|
|
912
|
+
const currentPage = ui2.pages.find((page) => {
|
|
913
|
+
try {
|
|
914
|
+
return get_page_id(page) === currentId;
|
|
915
|
+
} catch {
|
|
916
|
+
return false;
|
|
1076
917
|
}
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
918
|
+
});
|
|
919
|
+
const visiblePageId = ui2?.currentPage !== void 0 && ui2?.currentPage !== null ? get_page_id(ui2.currentPage) : null;
|
|
920
|
+
if (currentPage && visiblePageId !== null && visiblePageId !== currentId && typeof ui2?.selectPage === "function") {
|
|
921
|
+
ui2.selectPage(currentPage);
|
|
1081
922
|
}
|
|
1082
923
|
}
|
|
1083
|
-
return
|
|
924
|
+
return serialize_page_info(ui2, copiedPage, index);
|
|
925
|
+
}
|
|
926
|
+
function rename_page(ui2, options) {
|
|
927
|
+
const page_selector = typeof options.page === "number" ? { index: options.page } : options.page;
|
|
928
|
+
const resolved = resolve_target_page(ui2, page_selector, "page");
|
|
929
|
+
if (!options.name) {
|
|
930
|
+
throw new Error("`name` is required");
|
|
931
|
+
}
|
|
932
|
+
assert_page_rename_supported(ui2, "rename a page", resolved.page);
|
|
933
|
+
if (!rename_page_without_switch(ui2, resolved.page, options.name)) {
|
|
934
|
+
throw new Error("Failed to rename the target page");
|
|
935
|
+
}
|
|
936
|
+
return serialize_page_info(ui2, resolved.page, resolved.index);
|
|
1084
937
|
}
|
|
1085
938
|
function transform_cell_for_display(cell) {
|
|
1086
939
|
if (!cell || typeof cell !== "object") {
|
|
@@ -1384,7 +1237,7 @@ var DrawMcp = (() => {
|
|
|
1384
1237
|
`Cell '${cell_id}' is an edge; set_cell_shape expects a vertex`
|
|
1385
1238
|
);
|
|
1386
1239
|
}
|
|
1387
|
-
const style =
|
|
1240
|
+
const style = getShape(shape_name)?.style;
|
|
1388
1241
|
if (!style) {
|
|
1389
1242
|
throw new Error(
|
|
1390
1243
|
`set_cell_shape could not find a shape named '${shape_name}'`
|
|
@@ -1437,28 +1290,14 @@ var DrawMcp = (() => {
|
|
|
1437
1290
|
}
|
|
1438
1291
|
return cell;
|
|
1439
1292
|
}
|
|
1440
|
-
function get_shape_categories(
|
|
1441
|
-
|
|
1442
|
-
const categories = /* @__PURE__ */ new Set();
|
|
1443
|
-
for (const shape of Object.values(shapes)) {
|
|
1444
|
-
categories.add(shape.category || "General");
|
|
1445
|
-
}
|
|
1446
|
-
return [...categories];
|
|
1293
|
+
function get_shape_categories(_ui) {
|
|
1294
|
+
return getCategories();
|
|
1447
1295
|
}
|
|
1448
|
-
function get_shapes_in_category(
|
|
1449
|
-
|
|
1450
|
-
return Object.entries(shapes).filter(([_, shape]) => {
|
|
1451
|
-
return shape.category === options.category_id;
|
|
1452
|
-
}).map(([shape_key, shape_value]) => {
|
|
1453
|
-
return {
|
|
1454
|
-
id: shape_key,
|
|
1455
|
-
title: shape_value.title || shape_key
|
|
1456
|
-
};
|
|
1457
|
-
});
|
|
1296
|
+
function get_shapes_in_category(_ui, options) {
|
|
1297
|
+
return getShapesByCategory(options.category_id);
|
|
1458
1298
|
}
|
|
1459
|
-
function get_shape_by_name(
|
|
1460
|
-
const
|
|
1461
|
-
const shape = shapes[options.shape_name];
|
|
1299
|
+
function get_shape_by_name(_ui, options) {
|
|
1300
|
+
const shape = getShape(options.shape_name);
|
|
1462
1301
|
if (!shape) return null;
|
|
1463
1302
|
return {
|
|
1464
1303
|
id: options.shape_name,
|
|
@@ -1825,24 +1664,58 @@ var DrawMcp = (() => {
|
|
|
1825
1664
|
const bg = background !== "none" ? background : null;
|
|
1826
1665
|
if (embedXml) {
|
|
1827
1666
|
const currentPage = size === "page" || size === "selection";
|
|
1828
|
-
const
|
|
1829
|
-
false,
|
|
1667
|
+
const xml = ui2.getFileData(
|
|
1830
1668
|
true,
|
|
1831
1669
|
null,
|
|
1832
1670
|
null,
|
|
1671
|
+
null,
|
|
1833
1672
|
ignoreSelection,
|
|
1834
1673
|
currentPage
|
|
1835
1674
|
);
|
|
1836
|
-
const
|
|
1837
|
-
const
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1675
|
+
const exportGraphSession = create_page_export_graph(ui2, graph, ui2.currentPage);
|
|
1676
|
+
const renderGraph = exportGraphSession?.graph ?? graph;
|
|
1677
|
+
try {
|
|
1678
|
+
const svgString2 = typeof ui2.getEmbeddedSvg === "function" ? ui2.getEmbeddedSvg(
|
|
1679
|
+
xml,
|
|
1680
|
+
renderGraph,
|
|
1681
|
+
null,
|
|
1682
|
+
false,
|
|
1683
|
+
null,
|
|
1684
|
+
ignoreSelection,
|
|
1685
|
+
null,
|
|
1686
|
+
void 0,
|
|
1687
|
+
bg,
|
|
1688
|
+
scale,
|
|
1689
|
+
border,
|
|
1690
|
+
includeShadow
|
|
1691
|
+
) : (() => {
|
|
1692
|
+
const svgRoot2 = renderGraph.getSvg(
|
|
1693
|
+
bg,
|
|
1694
|
+
scale,
|
|
1695
|
+
border,
|
|
1696
|
+
!params.cropToDiagram,
|
|
1697
|
+
null,
|
|
1698
|
+
ignoreSelection
|
|
1699
|
+
);
|
|
1700
|
+
if (renderGraph.shadowVisible || includeShadow) {
|
|
1701
|
+
renderGraph.addSvgShadow(svgRoot2, null, null, border === 0);
|
|
1702
|
+
}
|
|
1703
|
+
svgRoot2.setAttribute("content", xml);
|
|
1704
|
+
return (Graph.xmlDeclaration || '<?xml version="1.0" encoding="UTF-8"?>') + "\n" + (Graph.svgFileComment || "") + "\n" + (Graph.svgDoctype || "") + "\n" + mxUtils.getXml(svgRoot2);
|
|
1705
|
+
})();
|
|
1706
|
+
const bounds = renderGraph.getGraphBounds();
|
|
1707
|
+
const w2 = Math.ceil(bounds.width * scale + bounds.x * scale + 2 * border);
|
|
1708
|
+
const h2 = Math.ceil(bounds.height * scale + bounds.y * scale + 2 * border);
|
|
1709
|
+
return {
|
|
1710
|
+
format: "svg",
|
|
1711
|
+
mimeType: "image/svg+xml",
|
|
1712
|
+
data: svgString2,
|
|
1713
|
+
width: w2,
|
|
1714
|
+
height: h2
|
|
1715
|
+
};
|
|
1716
|
+
} finally {
|
|
1717
|
+
exportGraphSession?.cleanup();
|
|
1718
|
+
}
|
|
1846
1719
|
}
|
|
1847
1720
|
const svgRoot = graph.getSvg(
|
|
1848
1721
|
bg,
|
|
@@ -2227,10 +2100,40 @@ var DrawMcp = (() => {
|
|
|
2227
2100
|
message: "New page creation not supported in this Draw.io version"
|
|
2228
2101
|
};
|
|
2229
2102
|
}
|
|
2103
|
+
const importedPageName = filename ? filename.replace(/\.[^/.]+$/, "") : null;
|
|
2104
|
+
if (importedPageName) {
|
|
2105
|
+
try {
|
|
2106
|
+
assert_page_rename_supported(
|
|
2107
|
+
ui2,
|
|
2108
|
+
"create a named imported page"
|
|
2109
|
+
);
|
|
2110
|
+
} catch (error) {
|
|
2111
|
+
return {
|
|
2112
|
+
success: false,
|
|
2113
|
+
message: error instanceof Error ? error.message : "Page renaming is not supported"
|
|
2114
|
+
};
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2230
2117
|
const newPage = ui2.insertPage();
|
|
2231
2118
|
if (!newPage) {
|
|
2232
2119
|
return { success: false, message: "Failed to create new page" };
|
|
2233
2120
|
}
|
|
2121
|
+
if (importedPageName) {
|
|
2122
|
+
try {
|
|
2123
|
+
assert_page_rename_supported(
|
|
2124
|
+
ui2,
|
|
2125
|
+
"create a named imported page",
|
|
2126
|
+
newPage
|
|
2127
|
+
);
|
|
2128
|
+
newPage.setName(importedPageName);
|
|
2129
|
+
} catch (error) {
|
|
2130
|
+
rollback_created_page(ui2, newPage);
|
|
2131
|
+
return {
|
|
2132
|
+
success: false,
|
|
2133
|
+
message: error instanceof Error ? error.message : "Page renaming is not supported"
|
|
2134
|
+
};
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
2234
2137
|
ui2.selectPage(newPage);
|
|
2235
2138
|
model.beginUpdate();
|
|
2236
2139
|
try {
|
|
@@ -2257,225 +2160,1398 @@ var DrawMcp = (() => {
|
|
|
2257
2160
|
} finally {
|
|
2258
2161
|
model.endUpdate();
|
|
2259
2162
|
}
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2163
|
+
return {
|
|
2164
|
+
success: true,
|
|
2165
|
+
message: `Diagram imported successfully (new page created)${filename ? `: ${filename}` : ""}`,
|
|
2166
|
+
pages: ui2.pages.length,
|
|
2167
|
+
cells: cellCount
|
|
2168
|
+
};
|
|
2169
|
+
default:
|
|
2170
|
+
return { success: false, message: `Unsupported import mode: ${mode}` };
|
|
2171
|
+
}
|
|
2172
|
+
} catch (error) {
|
|
2173
|
+
console.error("[import-diagram] Error importing diagram:", error);
|
|
2174
|
+
return {
|
|
2175
|
+
success: false,
|
|
2176
|
+
message: `Import failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
2177
|
+
};
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
|
|
2181
|
+
// src/events.ts
|
|
2182
|
+
function reply_name(event_name, request_id) {
|
|
2183
|
+
return `${event_name}.${request_id}`;
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2186
|
+
// src/shape-extractor.ts
|
|
2187
|
+
var ADDER_TO_PALETTE = {
|
|
2188
|
+
addAWS4Palette: "aws4",
|
|
2189
|
+
addGCP2Palette: "gcp2",
|
|
2190
|
+
addAzure2Palette: "azure2",
|
|
2191
|
+
addCisco19Palette: "cisco19",
|
|
2192
|
+
addCiscoSafePalette: "cisco_safe"
|
|
2193
|
+
};
|
|
2194
|
+
function extractShapesFromSidebar(ui2) {
|
|
2195
|
+
const Sidebar = window.Sidebar;
|
|
2196
|
+
if (!Sidebar?.prototype) {
|
|
2197
|
+
throw new Error("drawio Sidebar prototype not available on window");
|
|
2198
|
+
}
|
|
2199
|
+
if (!ui2?.sidebar) {
|
|
2200
|
+
throw new Error("ui.sidebar not constructed yet");
|
|
2201
|
+
}
|
|
2202
|
+
const recorded = [];
|
|
2203
|
+
let currentPalette = "unknown";
|
|
2204
|
+
let currentSection = "";
|
|
2205
|
+
const dummy = Object.assign(
|
|
2206
|
+
Object.create(Sidebar.prototype),
|
|
2207
|
+
ui2.sidebar,
|
|
2208
|
+
{
|
|
2209
|
+
taglist: {},
|
|
2210
|
+
palettes: {},
|
|
2211
|
+
entries: [],
|
|
2212
|
+
createVertexTemplateEntry(style, w, h, _value, title) {
|
|
2213
|
+
recorded.push({
|
|
2214
|
+
style,
|
|
2215
|
+
width: w,
|
|
2216
|
+
height: h,
|
|
2217
|
+
name: String(title ?? ""),
|
|
2218
|
+
paletteId: currentPalette,
|
|
2219
|
+
category: `mxgraph.${currentPalette}.${slug(currentSection || "default")}`
|
|
2220
|
+
});
|
|
2221
|
+
return () => null;
|
|
2222
|
+
},
|
|
2223
|
+
addPalette(_id, title, _expanded, onInit) {
|
|
2224
|
+
if (title) currentSection = title;
|
|
2225
|
+
try {
|
|
2226
|
+
onInit({ appendChild() {
|
|
2227
|
+
} });
|
|
2228
|
+
} catch {
|
|
2229
|
+
}
|
|
2230
|
+
},
|
|
2231
|
+
addPaletteFunctions(_id, title, _expanded, fns) {
|
|
2232
|
+
if (title) currentSection = title;
|
|
2233
|
+
const fake = { appendChild() {
|
|
2234
|
+
} };
|
|
2235
|
+
for (const fn of fns) {
|
|
2236
|
+
try {
|
|
2237
|
+
fn(fake);
|
|
2238
|
+
} catch {
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
},
|
|
2242
|
+
setCurrentSearchEntryLibrary() {
|
|
2243
|
+
},
|
|
2244
|
+
createEdgeTemplateEntry: () => () => null,
|
|
2245
|
+
addEntry: (_tags, fn) => fn,
|
|
2246
|
+
createTitle: () => typeof document !== "undefined" ? document.createElement("div") : {}
|
|
2247
|
+
}
|
|
2248
|
+
);
|
|
2249
|
+
for (const [adder, paletteId] of Object.entries(ADDER_TO_PALETTE)) {
|
|
2250
|
+
if (typeof dummy[adder] !== "function") {
|
|
2251
|
+
console.warn(
|
|
2252
|
+
`[shape-extractor] Sidebar.prototype.${adder} missing \u2014 vendor '${paletteId}' skipped`
|
|
2253
|
+
);
|
|
2254
|
+
continue;
|
|
2255
|
+
}
|
|
2256
|
+
currentPalette = paletteId;
|
|
2257
|
+
currentSection = "";
|
|
2258
|
+
try {
|
|
2259
|
+
dummy[adder]();
|
|
2260
|
+
} catch (err) {
|
|
2261
|
+
console.warn(`[shape-extractor] ${adder} threw during extraction`, err);
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
const out = /* @__PURE__ */ new Map();
|
|
2265
|
+
for (const s of recorded) {
|
|
2266
|
+
const key = deriveKey(s.style);
|
|
2267
|
+
if (key) out.set(key, s);
|
|
2268
|
+
}
|
|
2269
|
+
for (const v of Object.values(ADDER_TO_PALETTE)) {
|
|
2270
|
+
const n = [...out.keys()].filter(
|
|
2271
|
+
(k) => k.startsWith(`mxgraph.${v}.`)
|
|
2272
|
+
).length;
|
|
2273
|
+
if (n === 0) {
|
|
2274
|
+
console.warn(`[shape-extractor] captured 0 shapes for vendor '${v}'`);
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
return out;
|
|
2278
|
+
}
|
|
2279
|
+
function deriveKey(style) {
|
|
2280
|
+
if (!style) return null;
|
|
2281
|
+
const res = /resIcon=([^;]+)/.exec(style);
|
|
2282
|
+
if (res && res[1].startsWith("mxgraph.")) return res[1];
|
|
2283
|
+
const shapeMatch = /shape=mxgraph\.([a-z0-9_]+)\.([a-z0-9_]+)/i.exec(style);
|
|
2284
|
+
const prIconMatch = /prIcon=([a-z0-9_]+)/i.exec(style);
|
|
2285
|
+
if (shapeMatch && prIconMatch) {
|
|
2286
|
+
return `mxgraph.${shapeMatch[1].toLowerCase()}.${prIconMatch[1].toLowerCase()}`;
|
|
2287
|
+
}
|
|
2288
|
+
if (shapeMatch) {
|
|
2289
|
+
return `mxgraph.${shapeMatch[1].toLowerCase()}.${shapeMatch[2].toLowerCase()}`;
|
|
2290
|
+
}
|
|
2291
|
+
const imgMatch = /image=img\/lib\/([^/;]+)\/(?:(.+)\/)?([^/;]+?)\.(?:svg|png|jpe?g)/i.exec(
|
|
2292
|
+
style
|
|
2293
|
+
);
|
|
2294
|
+
if (imgMatch) {
|
|
2295
|
+
const vendor = slug(imgMatch[1]);
|
|
2296
|
+
const middle = imgMatch[2] ? slug(imgMatch[2]) : "";
|
|
2297
|
+
const file = slug(imgMatch[3]);
|
|
2298
|
+
if (!vendor || !file) return null;
|
|
2299
|
+
return middle ? `mxgraph.${vendor}.${middle}.${file}` : `mxgraph.${vendor}.${file}`;
|
|
2300
|
+
}
|
|
2301
|
+
return null;
|
|
2302
|
+
}
|
|
2303
|
+
function slug(s) {
|
|
2304
|
+
return s.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "") || "default";
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2307
|
+
// src/tool-registry.ts
|
|
2308
|
+
var VISIBLE_PAGE_EXECUTION = {
|
|
2309
|
+
mode: "visible-page"
|
|
2310
|
+
};
|
|
2311
|
+
var VISIBLE_PAGE_MUTATION_EXECUTION = {
|
|
2312
|
+
mode: "visible-page",
|
|
2313
|
+
mutates: true
|
|
2314
|
+
};
|
|
2315
|
+
var BACKGROUND_PAGE_EXECUTION = {
|
|
2316
|
+
mode: "background-page"
|
|
2317
|
+
};
|
|
2318
|
+
var BACKGROUND_PAGE_MUTATION_EXECUTION = {
|
|
2319
|
+
mode: "background-page",
|
|
2320
|
+
mutates: true
|
|
2321
|
+
};
|
|
2322
|
+
function can_export_in_background(options) {
|
|
2323
|
+
const format = options.format ?? "xml";
|
|
2324
|
+
const hasEmbeddedPng = options.embed_xml === true && format === "png";
|
|
2325
|
+
return options.selection_only !== true && options.size !== "selection" && !hasEmbeddedPng;
|
|
2326
|
+
}
|
|
2327
|
+
var EXPORT_PAGE_EXECUTION = {
|
|
2328
|
+
mode: "hybrid-page",
|
|
2329
|
+
allow_background: can_export_in_background,
|
|
2330
|
+
sync_live_current_page_state: true
|
|
2331
|
+
};
|
|
2332
|
+
function skip_page_execution_for_new_page_import(options) {
|
|
2333
|
+
return options.mode === "new-page";
|
|
2334
|
+
}
|
|
2335
|
+
function skip_page_execution_for_new_page_mermaid(options) {
|
|
2336
|
+
return options.insert_mode === "new-page";
|
|
2337
|
+
}
|
|
2338
|
+
function with_target_page(handler, options) {
|
|
2339
|
+
return (ui2, rawOptions) => {
|
|
2340
|
+
const drawioOptions = rawOptions;
|
|
2341
|
+
if (!options?.skip?.(drawioOptions)) {
|
|
2342
|
+
const pageExecution = options?.pageExecution;
|
|
2343
|
+
const preferBackground = pageExecution?.mode === "background-page" || pageExecution?.mode === "hybrid-page" && pageExecution.allow_background?.(drawioOptions) === true;
|
|
2344
|
+
const execution = prepare_target_page_execution(
|
|
2345
|
+
ui2,
|
|
2346
|
+
drawioOptions.target_page,
|
|
2347
|
+
{
|
|
2348
|
+
prefer_background: preferBackground,
|
|
2349
|
+
sync_live_current_page_state: pageExecution?.sync_live_current_page_state === true
|
|
2350
|
+
}
|
|
2351
|
+
);
|
|
2352
|
+
try {
|
|
2353
|
+
const result = handler(execution.ui, drawioOptions);
|
|
2354
|
+
if (result && typeof result === "object" && typeof result.finally === "function") {
|
|
2355
|
+
return result.finally(() => {
|
|
2356
|
+
if (pageExecution?.mutates) {
|
|
2357
|
+
mark_page_execution_modified(ui2, execution);
|
|
2358
|
+
}
|
|
2359
|
+
execution.cleanup();
|
|
2360
|
+
});
|
|
2361
|
+
}
|
|
2362
|
+
if (pageExecution?.mutates) {
|
|
2363
|
+
mark_page_execution_modified(ui2, execution);
|
|
2364
|
+
}
|
|
2365
|
+
execution.cleanup();
|
|
2366
|
+
return result;
|
|
2367
|
+
} catch (error) {
|
|
2368
|
+
if (pageExecution?.mutates) {
|
|
2369
|
+
mark_page_execution_modified(ui2, execution);
|
|
2370
|
+
}
|
|
2371
|
+
execution.cleanup();
|
|
2372
|
+
throw error;
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
return handler(ui2, drawioOptions);
|
|
2376
|
+
};
|
|
2377
|
+
}
|
|
2378
|
+
function page_tool({
|
|
2379
|
+
handler,
|
|
2380
|
+
pageExecution,
|
|
2381
|
+
skip,
|
|
2382
|
+
...definition
|
|
2383
|
+
}) {
|
|
2384
|
+
const options = { pageExecution };
|
|
2385
|
+
if (skip) {
|
|
2386
|
+
options.skip = skip;
|
|
2387
|
+
}
|
|
2388
|
+
return {
|
|
2389
|
+
...definition,
|
|
2390
|
+
handler: with_target_page(handler, options),
|
|
2391
|
+
pageExecution
|
|
2392
|
+
};
|
|
2393
|
+
}
|
|
2394
|
+
function with_target_document(handler) {
|
|
2395
|
+
return (ui2, rawOptions) => {
|
|
2396
|
+
const drawioOptions = rawOptions;
|
|
2397
|
+
assert_target_document_active(drawioOptions.target_document);
|
|
2398
|
+
return handler(ui2, rawOptions);
|
|
2399
|
+
};
|
|
2400
|
+
}
|
|
2401
|
+
var rawToolDefinitions = [
|
|
2402
|
+
page_tool({
|
|
2403
|
+
name: "get-selected-cell",
|
|
2404
|
+
params: /* @__PURE__ */ new Set(["target_page"]),
|
|
2405
|
+
handler: get_selected_cell,
|
|
2406
|
+
pageExecution: VISIBLE_PAGE_EXECUTION
|
|
2407
|
+
}),
|
|
2408
|
+
page_tool({
|
|
2409
|
+
name: "add-rectangle",
|
|
2410
|
+
params: /* @__PURE__ */ new Set([
|
|
2411
|
+
"x",
|
|
2412
|
+
"y",
|
|
2413
|
+
"width",
|
|
2414
|
+
"height",
|
|
2415
|
+
"text",
|
|
2416
|
+
"style",
|
|
2417
|
+
"parent_id",
|
|
2418
|
+
"target_page"
|
|
2419
|
+
]),
|
|
2420
|
+
handler: add_new_rectangle,
|
|
2421
|
+
pageExecution: BACKGROUND_PAGE_MUTATION_EXECUTION
|
|
2422
|
+
}),
|
|
2423
|
+
page_tool({
|
|
2424
|
+
name: "add-edge",
|
|
2425
|
+
params: /* @__PURE__ */ new Set([
|
|
2426
|
+
"source_id",
|
|
2427
|
+
"target_id",
|
|
2428
|
+
"style",
|
|
2429
|
+
"text",
|
|
2430
|
+
"parent_id",
|
|
2431
|
+
"points",
|
|
2432
|
+
"target_page"
|
|
2433
|
+
]),
|
|
2434
|
+
handler: add_edge,
|
|
2435
|
+
pageExecution: BACKGROUND_PAGE_MUTATION_EXECUTION
|
|
2436
|
+
}),
|
|
2437
|
+
page_tool({
|
|
2438
|
+
name: "delete-cell-by-id",
|
|
2439
|
+
params: /* @__PURE__ */ new Set(["cell_id", "target_page"]),
|
|
2440
|
+
handler: delete_cell_by_id,
|
|
2441
|
+
pageExecution: BACKGROUND_PAGE_MUTATION_EXECUTION
|
|
2442
|
+
}),
|
|
2443
|
+
{
|
|
2444
|
+
name: "get-shape-categories",
|
|
2445
|
+
params: /* @__PURE__ */ new Set([]),
|
|
2446
|
+
handler: get_shape_categories
|
|
2447
|
+
},
|
|
2448
|
+
{
|
|
2449
|
+
name: "get-shapes-in-category",
|
|
2450
|
+
params: /* @__PURE__ */ new Set(["category_id"]),
|
|
2451
|
+
handler: get_shapes_in_category
|
|
2452
|
+
},
|
|
2453
|
+
{
|
|
2454
|
+
name: "get-shape-by-name",
|
|
2455
|
+
params: /* @__PURE__ */ new Set(["shape_name"]),
|
|
2456
|
+
handler: get_shape_by_name
|
|
2457
|
+
},
|
|
2458
|
+
page_tool({
|
|
2459
|
+
name: "add-cell-of-shape",
|
|
2460
|
+
params: /* @__PURE__ */ new Set([
|
|
2461
|
+
"shape_name",
|
|
2462
|
+
"x",
|
|
2463
|
+
"y",
|
|
2464
|
+
"width",
|
|
2465
|
+
"height",
|
|
2466
|
+
"text",
|
|
2467
|
+
"style",
|
|
2468
|
+
"parent_id",
|
|
2469
|
+
"target_page"
|
|
2470
|
+
]),
|
|
2471
|
+
handler: add_cell_of_shape,
|
|
2472
|
+
pageExecution: BACKGROUND_PAGE_MUTATION_EXECUTION
|
|
2473
|
+
}),
|
|
2474
|
+
page_tool({
|
|
2475
|
+
name: "set-cell-shape",
|
|
2476
|
+
params: /* @__PURE__ */ new Set(["cell_id", "shape_name", "target_page"]),
|
|
2477
|
+
handler: set_cell_shape,
|
|
2478
|
+
pageExecution: BACKGROUND_PAGE_MUTATION_EXECUTION
|
|
2479
|
+
}),
|
|
2480
|
+
page_tool({
|
|
2481
|
+
name: "set-cell-data",
|
|
2482
|
+
params: /* @__PURE__ */ new Set(["cell_id", "key", "value", "target_page"]),
|
|
2483
|
+
handler: set_cell_data,
|
|
2484
|
+
pageExecution: BACKGROUND_PAGE_MUTATION_EXECUTION
|
|
2485
|
+
}),
|
|
2486
|
+
page_tool({
|
|
2487
|
+
name: "list-paged-model",
|
|
2488
|
+
params: /* @__PURE__ */ new Set(["page", "page_size", "filter", "target_page"]),
|
|
2489
|
+
handler: list_paged_model,
|
|
2490
|
+
pageExecution: BACKGROUND_PAGE_EXECUTION
|
|
2491
|
+
}),
|
|
2492
|
+
page_tool({
|
|
2493
|
+
name: "edit-cell",
|
|
2494
|
+
params: /* @__PURE__ */ new Set([
|
|
2495
|
+
"cell_id",
|
|
2496
|
+
"text",
|
|
2497
|
+
"x",
|
|
2498
|
+
"y",
|
|
2499
|
+
"width",
|
|
2500
|
+
"height",
|
|
2501
|
+
"style",
|
|
2502
|
+
"target_page"
|
|
2503
|
+
]),
|
|
2504
|
+
handler: edit_cell,
|
|
2505
|
+
pageExecution: BACKGROUND_PAGE_MUTATION_EXECUTION
|
|
2506
|
+
}),
|
|
2507
|
+
page_tool({
|
|
2508
|
+
name: "edit-edge",
|
|
2509
|
+
params: /* @__PURE__ */ new Set([
|
|
2510
|
+
"cell_id",
|
|
2511
|
+
"text",
|
|
2512
|
+
"source_id",
|
|
2513
|
+
"target_id",
|
|
2514
|
+
"style",
|
|
2515
|
+
"points",
|
|
2516
|
+
"target_page"
|
|
2517
|
+
]),
|
|
2518
|
+
handler: edit_edge,
|
|
2519
|
+
pageExecution: BACKGROUND_PAGE_MUTATION_EXECUTION
|
|
2520
|
+
}),
|
|
2521
|
+
page_tool({
|
|
2522
|
+
name: "list-layers",
|
|
2523
|
+
params: /* @__PURE__ */ new Set(["target_page"]),
|
|
2524
|
+
handler: list_layers,
|
|
2525
|
+
pageExecution: BACKGROUND_PAGE_EXECUTION
|
|
2526
|
+
}),
|
|
2527
|
+
page_tool({
|
|
2528
|
+
name: "set-active-layer",
|
|
2529
|
+
params: /* @__PURE__ */ new Set(["layer_id", "target_page"]),
|
|
2530
|
+
handler: set_active_layer,
|
|
2531
|
+
pageExecution: VISIBLE_PAGE_MUTATION_EXECUTION
|
|
2532
|
+
}),
|
|
2533
|
+
page_tool({
|
|
2534
|
+
name: "move-cell-to-layer",
|
|
2535
|
+
params: /* @__PURE__ */ new Set(["cell_id", "target_layer_id", "target_page"]),
|
|
2536
|
+
handler: move_cell_to_layer,
|
|
2537
|
+
pageExecution: BACKGROUND_PAGE_MUTATION_EXECUTION
|
|
2538
|
+
}),
|
|
2539
|
+
page_tool({
|
|
2540
|
+
name: "set-cell-parent",
|
|
2541
|
+
params: /* @__PURE__ */ new Set(["cell_id", "parent_id", "target_page"]),
|
|
2542
|
+
handler: set_cell_parent,
|
|
2543
|
+
pageExecution: BACKGROUND_PAGE_MUTATION_EXECUTION
|
|
2544
|
+
}),
|
|
2545
|
+
page_tool({
|
|
2546
|
+
name: "get-active-layer",
|
|
2547
|
+
params: /* @__PURE__ */ new Set(["target_page"]),
|
|
2548
|
+
handler: get_active_layer,
|
|
2549
|
+
pageExecution: VISIBLE_PAGE_EXECUTION
|
|
2550
|
+
}),
|
|
2551
|
+
page_tool({
|
|
2552
|
+
name: "create-layer",
|
|
2553
|
+
params: /* @__PURE__ */ new Set(["name", "target_page"]),
|
|
2554
|
+
handler: create_layer,
|
|
2555
|
+
pageExecution: BACKGROUND_PAGE_MUTATION_EXECUTION
|
|
2556
|
+
}),
|
|
2557
|
+
page_tool({
|
|
2558
|
+
name: "export-diagram",
|
|
2559
|
+
params: /* @__PURE__ */ new Set([
|
|
2560
|
+
"format",
|
|
2561
|
+
"scale",
|
|
2562
|
+
"border",
|
|
2563
|
+
"background",
|
|
2564
|
+
"shadow",
|
|
2565
|
+
"crop",
|
|
2566
|
+
"selection_only",
|
|
2567
|
+
"transparent",
|
|
2568
|
+
"dpi",
|
|
2569
|
+
"embed_xml",
|
|
2570
|
+
"size",
|
|
2571
|
+
"target_page"
|
|
2572
|
+
]),
|
|
2573
|
+
handler: export_diagram,
|
|
2574
|
+
pageExecution: EXPORT_PAGE_EXECUTION
|
|
2575
|
+
}),
|
|
2576
|
+
page_tool({
|
|
2577
|
+
name: "import-diagram",
|
|
2578
|
+
params: /* @__PURE__ */ new Set(["data", "format", "mode", "filename", "target_page"]),
|
|
2579
|
+
handler: import_diagram,
|
|
2580
|
+
pageExecution: VISIBLE_PAGE_MUTATION_EXECUTION,
|
|
2581
|
+
skip: skip_page_execution_for_new_page_import
|
|
2582
|
+
}),
|
|
2583
|
+
page_tool({
|
|
2584
|
+
name: "import-mermaid",
|
|
2585
|
+
params: /* @__PURE__ */ new Set(["mermaid_source", "mode", "insert_mode", "target_page"]),
|
|
2586
|
+
handler: import_mermaid,
|
|
2587
|
+
pageExecution: VISIBLE_PAGE_MUTATION_EXECUTION,
|
|
2588
|
+
skip: skip_page_execution_for_new_page_mermaid
|
|
2589
|
+
}),
|
|
2590
|
+
{
|
|
2591
|
+
name: "list-pages",
|
|
2592
|
+
params: /* @__PURE__ */ new Set([]),
|
|
2593
|
+
handler: list_pages
|
|
2594
|
+
},
|
|
2595
|
+
{
|
|
2596
|
+
name: "get-current-page",
|
|
2597
|
+
params: /* @__PURE__ */ new Set([]),
|
|
2598
|
+
handler: get_current_page
|
|
2599
|
+
},
|
|
2600
|
+
{
|
|
2601
|
+
name: "create-page",
|
|
2602
|
+
params: /* @__PURE__ */ new Set(["name"]),
|
|
2603
|
+
handler: create_page
|
|
2604
|
+
},
|
|
2605
|
+
{
|
|
2606
|
+
name: "copy-page",
|
|
2607
|
+
params: /* @__PURE__ */ new Set(["page", "name"]),
|
|
2608
|
+
handler: copy_page
|
|
2609
|
+
},
|
|
2610
|
+
{
|
|
2611
|
+
name: "rename-page",
|
|
2612
|
+
params: /* @__PURE__ */ new Set(["page", "name"]),
|
|
2613
|
+
handler: rename_page
|
|
2614
|
+
}
|
|
2615
|
+
];
|
|
2616
|
+
var toolDefinitions = rawToolDefinitions.map(
|
|
2617
|
+
(definition) => ({
|
|
2618
|
+
...definition,
|
|
2619
|
+
params: /* @__PURE__ */ new Set(["target_document", ...definition.params]),
|
|
2620
|
+
handler: with_target_document(definition.handler)
|
|
2621
|
+
})
|
|
2622
|
+
);
|
|
2623
|
+
|
|
2624
|
+
// src/bootstrap.ts
|
|
2625
|
+
var SHAPE_EXTRACTION_MAX_ATTEMPTS = 10;
|
|
2626
|
+
var SHAPE_EXTRACTION_INTERVAL_MS = 1e3;
|
|
2627
|
+
function generateDocumentId() {
|
|
2628
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
2629
|
+
return crypto.randomUUID();
|
|
2630
|
+
}
|
|
2631
|
+
return `document-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
2632
|
+
}
|
|
2633
|
+
function bootstrapPlugin(opts) {
|
|
2634
|
+
const {
|
|
2635
|
+
ui: ui2,
|
|
2636
|
+
transport: transport2,
|
|
2637
|
+
enableDocumentState = true,
|
|
2638
|
+
enableShapeExtraction = true
|
|
2639
|
+
} = opts;
|
|
2640
|
+
let currentDocumentId = null;
|
|
2641
|
+
let currentFileRef = null;
|
|
2642
|
+
let detachFileListener = null;
|
|
2643
|
+
const cleanups = [];
|
|
2644
|
+
const syncDocumentState = () => {
|
|
2645
|
+
if (!enableDocumentState) return;
|
|
2646
|
+
if (!ui2?.getCurrentFile?.() || !currentDocumentId) return;
|
|
2647
|
+
transport2.send({
|
|
2648
|
+
__control: "document-state",
|
|
2649
|
+
document: serialize_document_info(ui2, currentDocumentId)
|
|
2650
|
+
});
|
|
2651
|
+
};
|
|
2652
|
+
const detachCurrentFileListener = () => {
|
|
2653
|
+
if (detachFileListener) {
|
|
2654
|
+
detachFileListener();
|
|
2655
|
+
detachFileListener = null;
|
|
2656
|
+
}
|
|
2657
|
+
currentFileRef = null;
|
|
2658
|
+
};
|
|
2659
|
+
const bindCurrentFileListener = (file) => {
|
|
2660
|
+
detachCurrentFileListener();
|
|
2661
|
+
currentFileRef = file;
|
|
2662
|
+
if (!file?.addListener || !file?.removeListener) return;
|
|
2663
|
+
const onDescriptorChanged = () => syncDocumentState();
|
|
2664
|
+
file.addListener("descriptorChanged", onDescriptorChanged);
|
|
2665
|
+
detachFileListener = () => {
|
|
2666
|
+
try {
|
|
2667
|
+
file.removeListener?.("descriptorChanged", onDescriptorChanged);
|
|
2668
|
+
} catch (error) {
|
|
2669
|
+
console.warn(
|
|
2670
|
+
"[plugin] Failed to remove file descriptor listener:",
|
|
2671
|
+
error
|
|
2672
|
+
);
|
|
2673
|
+
}
|
|
2674
|
+
};
|
|
2675
|
+
};
|
|
2676
|
+
const refreshActiveDocument = (forceNewId) => {
|
|
2677
|
+
const file = ui2?.getCurrentFile?.() ?? null;
|
|
2678
|
+
if (!file) {
|
|
2679
|
+
currentDocumentId = null;
|
|
2680
|
+
set_active_document_id(null);
|
|
2681
|
+
detachCurrentFileListener();
|
|
2682
|
+
return;
|
|
2683
|
+
}
|
|
2684
|
+
if (forceNewId || !currentDocumentId || file !== currentFileRef) {
|
|
2685
|
+
currentDocumentId = generateDocumentId();
|
|
2686
|
+
set_active_document_id(currentDocumentId);
|
|
2687
|
+
bindCurrentFileListener(file);
|
|
2688
|
+
return;
|
|
2689
|
+
}
|
|
2690
|
+
if (file !== currentFileRef) {
|
|
2691
|
+
bindCurrentFileListener(file);
|
|
2692
|
+
}
|
|
2693
|
+
};
|
|
2694
|
+
const handleDocumentStateChange = (forceNewId) => {
|
|
2695
|
+
refreshActiveDocument(forceNewId);
|
|
2696
|
+
syncDocumentState();
|
|
2697
|
+
};
|
|
2698
|
+
const registerDocumentStateListeners = () => {
|
|
2699
|
+
const listen = (eventName, forceNewId) => {
|
|
2700
|
+
ui2.editor?.addListener?.(eventName, () => {
|
|
2701
|
+
handleDocumentStateChange(forceNewId);
|
|
2702
|
+
});
|
|
2703
|
+
};
|
|
2704
|
+
listen("fileLoaded", true);
|
|
2705
|
+
listen("pageSelected", false);
|
|
2706
|
+
listen("pageRenamed", false);
|
|
2707
|
+
listen("pageMoved", false);
|
|
2708
|
+
listen("pagesPatched", false);
|
|
2709
|
+
refreshActiveDocument(false);
|
|
2710
|
+
};
|
|
2711
|
+
const buildToolHandler = (toolName, parameterKeys, executeFunction) => {
|
|
2712
|
+
return (request) => {
|
|
2713
|
+
const options = Object.entries(request).reduce(
|
|
2714
|
+
(acc, [key, value]) => {
|
|
2715
|
+
if (parameterKeys.has(key)) {
|
|
2716
|
+
acc[key] = value;
|
|
2717
|
+
}
|
|
2718
|
+
return acc;
|
|
2719
|
+
},
|
|
2720
|
+
{}
|
|
2721
|
+
);
|
|
2722
|
+
const sendReply = (success, payload) => {
|
|
2723
|
+
const reply = {
|
|
2724
|
+
__event: reply_name(toolName, request.__request_id),
|
|
2725
|
+
__request_id: request.__request_id,
|
|
2726
|
+
success
|
|
2727
|
+
};
|
|
2728
|
+
if (success) {
|
|
2729
|
+
reply.result = remove_circular_dependencies(payload);
|
|
2730
|
+
} else {
|
|
2731
|
+
reply.error = remove_circular_dependencies(payload);
|
|
2732
|
+
}
|
|
2733
|
+
transport2.send(reply);
|
|
2734
|
+
if (success) {
|
|
2735
|
+
syncDocumentState();
|
|
2736
|
+
}
|
|
2737
|
+
};
|
|
2738
|
+
try {
|
|
2739
|
+
const result = executeFunction(ui2, options);
|
|
2740
|
+
if (result instanceof Promise) {
|
|
2741
|
+
result.then(
|
|
2742
|
+
(resolved) => sendReply(true, resolved),
|
|
2743
|
+
(error) => {
|
|
2744
|
+
console.error(
|
|
2745
|
+
`[plugin] Async tool ${toolName} failed for request ID ${request.__request_id}:`,
|
|
2746
|
+
error
|
|
2747
|
+
);
|
|
2748
|
+
sendReply(false, error);
|
|
2749
|
+
}
|
|
2750
|
+
);
|
|
2751
|
+
return;
|
|
2752
|
+
}
|
|
2753
|
+
sendReply(true, result);
|
|
2754
|
+
} catch (error) {
|
|
2755
|
+
console.error(
|
|
2756
|
+
`[plugin] Tool ${toolName} failed for request ID ${request.__request_id}:`,
|
|
2757
|
+
error
|
|
2758
|
+
);
|
|
2759
|
+
sendReply(false, error);
|
|
2760
|
+
}
|
|
2761
|
+
};
|
|
2762
|
+
};
|
|
2763
|
+
const toolHandlers = /* @__PURE__ */ new Map();
|
|
2764
|
+
toolDefinitions.forEach((def) => {
|
|
2765
|
+
toolHandlers.set(
|
|
2766
|
+
def.name,
|
|
2767
|
+
buildToolHandler(def.name, def.params, def.handler)
|
|
2768
|
+
);
|
|
2769
|
+
console.debug(`[plugin] registered tool ${def.name}`);
|
|
2770
|
+
});
|
|
2771
|
+
transport2.onMessage((message) => {
|
|
2772
|
+
if (!message) return;
|
|
2773
|
+
if (message.__control === "sync-document-state") {
|
|
2774
|
+
handleDocumentStateChange(false);
|
|
2775
|
+
return;
|
|
2776
|
+
}
|
|
2777
|
+
const handler = typeof message.__event === "string" ? toolHandlers.get(message.__event) : void 0;
|
|
2778
|
+
if (handler) {
|
|
2779
|
+
handler(message);
|
|
2780
|
+
}
|
|
2781
|
+
});
|
|
2782
|
+
if (enableDocumentState) {
|
|
2783
|
+
registerDocumentStateListeners();
|
|
2784
|
+
}
|
|
2785
|
+
if (enableShapeExtraction) {
|
|
2786
|
+
const tryExtractShapes = () => {
|
|
2787
|
+
try {
|
|
2788
|
+
if (!ui2?.sidebar) return false;
|
|
2789
|
+
const map = extractShapesFromSidebar(ui2);
|
|
2790
|
+
if (map.size === 0) return false;
|
|
2791
|
+
const runtime = new Map(
|
|
2792
|
+
[...map].map(
|
|
2793
|
+
([k, v]) => [
|
|
2794
|
+
k,
|
|
2795
|
+
{ style: v.style, category: v.category, name: v.name }
|
|
2796
|
+
]
|
|
2797
|
+
)
|
|
2798
|
+
);
|
|
2799
|
+
setRuntimeCatalog(runtime);
|
|
2800
|
+
console.info(
|
|
2801
|
+
`[plugin] extracted ${map.size} vendor shapes from drawio sidebar`
|
|
2802
|
+
);
|
|
2803
|
+
return true;
|
|
2804
|
+
} catch (err) {
|
|
2805
|
+
console.warn("[plugin] shape extraction attempt failed", err);
|
|
2806
|
+
return false;
|
|
2807
|
+
}
|
|
2808
|
+
};
|
|
2809
|
+
if (!tryExtractShapes()) {
|
|
2810
|
+
let attempts = 0;
|
|
2811
|
+
const intervalId = setInterval(() => {
|
|
2812
|
+
attempts += 1;
|
|
2813
|
+
if (tryExtractShapes() || attempts >= SHAPE_EXTRACTION_MAX_ATTEMPTS) {
|
|
2814
|
+
clearInterval(intervalId);
|
|
2815
|
+
if (attempts >= SHAPE_EXTRACTION_MAX_ATTEMPTS) {
|
|
2816
|
+
console.error(
|
|
2817
|
+
"[plugin] shape extraction gave up after retries; vendor shapes unavailable"
|
|
2818
|
+
);
|
|
2819
|
+
}
|
|
2820
|
+
}
|
|
2821
|
+
}, SHAPE_EXTRACTION_INTERVAL_MS);
|
|
2822
|
+
cleanups.push(() => clearInterval(intervalId));
|
|
2823
|
+
}
|
|
2824
|
+
}
|
|
2825
|
+
return {
|
|
2826
|
+
syncDocumentState,
|
|
2827
|
+
dispose: () => {
|
|
2828
|
+
detachCurrentFileListener();
|
|
2829
|
+
cleanups.forEach((fn) => fn());
|
|
2830
|
+
cleanups.length = 0;
|
|
2831
|
+
}
|
|
2832
|
+
};
|
|
2833
|
+
}
|
|
2834
|
+
|
|
2835
|
+
// src/websocketManager.ts
|
|
2836
|
+
function createWebSocketManager(options) {
|
|
2837
|
+
let socket = null;
|
|
2838
|
+
let reconnectAttempts = 0;
|
|
2839
|
+
let currentState = "disconnected";
|
|
2840
|
+
let messageHandler = null;
|
|
2841
|
+
let pingIntervalId = null;
|
|
2842
|
+
let reconnectTimeoutId = null;
|
|
2843
|
+
const {
|
|
2844
|
+
url,
|
|
2845
|
+
maxReconnectAttempts = 5,
|
|
2846
|
+
reconnectDelay = 3e3,
|
|
2847
|
+
pingInterval = 3e4
|
|
2848
|
+
} = options;
|
|
2849
|
+
const updateState = (newState) => {
|
|
2850
|
+
if (currentState !== newState) {
|
|
2851
|
+
console.debug(
|
|
2852
|
+
`[websocketManager] State change: ${currentState} \u2192 ${newState}`
|
|
2853
|
+
);
|
|
2854
|
+
currentState = newState;
|
|
2855
|
+
}
|
|
2856
|
+
};
|
|
2857
|
+
const connect = () => {
|
|
2858
|
+
if (socket && socket.readyState === WebSocket.OPEN) {
|
|
2859
|
+
console.debug("[websocketManager] Already connected");
|
|
2860
|
+
return;
|
|
2861
|
+
}
|
|
2862
|
+
updateState("connecting");
|
|
2863
|
+
try {
|
|
2864
|
+
socket = new WebSocket(url);
|
|
2865
|
+
socket.addEventListener("open", () => {
|
|
2866
|
+
console.debug("[websocketManager] WebSocket connection established");
|
|
2867
|
+
reconnectAttempts = 0;
|
|
2868
|
+
updateState("connected");
|
|
2869
|
+
startPing();
|
|
2870
|
+
});
|
|
2871
|
+
socket.addEventListener("message", (event) => {
|
|
2872
|
+
try {
|
|
2873
|
+
const parsedMessage = JSON.parse(event.data);
|
|
2874
|
+
console.debug("[websocketManager] Received message:", parsedMessage);
|
|
2875
|
+
if (messageHandler) {
|
|
2876
|
+
messageHandler(parsedMessage);
|
|
2877
|
+
}
|
|
2878
|
+
} catch (error) {
|
|
2879
|
+
console.error(
|
|
2880
|
+
"[websocketManager] Failed to parse WebSocket message:",
|
|
2881
|
+
error
|
|
2882
|
+
);
|
|
2883
|
+
}
|
|
2884
|
+
});
|
|
2885
|
+
socket.addEventListener("close", () => {
|
|
2886
|
+
console.debug("[websocketManager] WebSocket connection closed");
|
|
2887
|
+
updateState("disconnected");
|
|
2888
|
+
stopPing();
|
|
2889
|
+
attemptReconnect();
|
|
2890
|
+
});
|
|
2891
|
+
socket.addEventListener("error", (event) => {
|
|
2892
|
+
console.error("[websocketManager] WebSocket error:", event);
|
|
2893
|
+
updateState("disconnected");
|
|
2894
|
+
});
|
|
2895
|
+
} catch (error) {
|
|
2896
|
+
console.error(
|
|
2897
|
+
"[websocketManager] Failed to create WebSocket connection:",
|
|
2898
|
+
error
|
|
2899
|
+
);
|
|
2900
|
+
updateState("disconnected");
|
|
2901
|
+
}
|
|
2902
|
+
};
|
|
2903
|
+
const disconnect = () => {
|
|
2904
|
+
if (reconnectTimeoutId) {
|
|
2905
|
+
clearTimeout(reconnectTimeoutId);
|
|
2906
|
+
reconnectTimeoutId = null;
|
|
2907
|
+
}
|
|
2908
|
+
stopPing();
|
|
2909
|
+
reconnectAttempts = 0;
|
|
2910
|
+
if (socket) {
|
|
2911
|
+
console.debug("[websocketManager] Closing WebSocket connection");
|
|
2912
|
+
socket.close();
|
|
2913
|
+
socket = null;
|
|
2914
|
+
}
|
|
2915
|
+
updateState("disconnected");
|
|
2916
|
+
};
|
|
2917
|
+
const send = (message) => {
|
|
2918
|
+
if (!socket || socket.readyState !== WebSocket.OPEN) {
|
|
2919
|
+
console.warn(
|
|
2920
|
+
"[websocketManager] Cannot send message: WebSocket not connected"
|
|
2921
|
+
);
|
|
2922
|
+
return;
|
|
2923
|
+
}
|
|
2924
|
+
try {
|
|
2925
|
+
const serialized = JSON.stringify(message);
|
|
2926
|
+
console.debug("[websocketManager] Sending message:", message);
|
|
2927
|
+
socket.send(serialized);
|
|
2928
|
+
} catch (error) {
|
|
2929
|
+
console.error("[websocketManager] Failed to send message:", error);
|
|
2930
|
+
}
|
|
2931
|
+
};
|
|
2932
|
+
const getState = () => currentState;
|
|
2933
|
+
const onMessage = (handler) => {
|
|
2934
|
+
messageHandler = handler;
|
|
2935
|
+
};
|
|
2936
|
+
const attemptReconnect = () => {
|
|
2937
|
+
if (reconnectAttempts >= maxReconnectAttempts) {
|
|
2938
|
+
console.error(
|
|
2939
|
+
"[websocketManager] Max reconnection attempts reached. Giving up."
|
|
2940
|
+
);
|
|
2941
|
+
return;
|
|
2942
|
+
}
|
|
2943
|
+
reconnectAttempts++;
|
|
2944
|
+
const delay = reconnectDelay * Math.pow(1.5, reconnectAttempts - 1);
|
|
2945
|
+
console.log(
|
|
2946
|
+
`[websocketManager] Attempting to reconnect in ${Math.round(delay / 1e3)} seconds... (attempt ${reconnectAttempts}/${maxReconnectAttempts})`
|
|
2947
|
+
);
|
|
2948
|
+
reconnectTimeoutId = window.setTimeout(() => {
|
|
2949
|
+
reconnectTimeoutId = null;
|
|
2950
|
+
connect();
|
|
2951
|
+
}, delay);
|
|
2952
|
+
};
|
|
2953
|
+
const startPing = () => {
|
|
2954
|
+
stopPing();
|
|
2955
|
+
pingIntervalId = window.setInterval(() => {
|
|
2956
|
+
if (getState() === "connected") {
|
|
2957
|
+
send({ type: "PING" });
|
|
2958
|
+
}
|
|
2959
|
+
}, pingInterval);
|
|
2960
|
+
};
|
|
2961
|
+
const stopPing = () => {
|
|
2962
|
+
if (pingIntervalId !== null) {
|
|
2963
|
+
clearInterval(pingIntervalId);
|
|
2964
|
+
pingIntervalId = null;
|
|
2965
|
+
}
|
|
2966
|
+
};
|
|
2967
|
+
const ping = () => {
|
|
2968
|
+
return new Promise((resolve) => {
|
|
2969
|
+
if (getState() !== "connected") {
|
|
2970
|
+
resolve(false);
|
|
2971
|
+
return;
|
|
2972
|
+
}
|
|
2973
|
+
const timeoutId = setTimeout(() => {
|
|
2974
|
+
resolve(false);
|
|
2975
|
+
}, 5e3);
|
|
2976
|
+
send({ type: "PING", message: "Ping from plugin" });
|
|
2977
|
+
setTimeout(() => {
|
|
2978
|
+
clearTimeout(timeoutId);
|
|
2979
|
+
resolve(getState() === "connected");
|
|
2980
|
+
}, 1e3);
|
|
2981
|
+
});
|
|
2982
|
+
};
|
|
2983
|
+
return {
|
|
2984
|
+
connect,
|
|
2985
|
+
disconnect,
|
|
2986
|
+
send,
|
|
2987
|
+
getState,
|
|
2988
|
+
onMessage,
|
|
2989
|
+
ping
|
|
2990
|
+
};
|
|
2991
|
+
}
|
|
2992
|
+
|
|
2993
|
+
// src/pluginConfig.ts
|
|
2994
|
+
var DEFAULT_PLUGIN_CONFIG = {
|
|
2995
|
+
websocketPort: 3333,
|
|
2996
|
+
serverUrl: ""
|
|
2997
|
+
};
|
|
2998
|
+
function isValidWebSocketUrl(value) {
|
|
2999
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
3000
|
+
return false;
|
|
3001
|
+
}
|
|
3002
|
+
try {
|
|
3003
|
+
const parsed = new URL(value);
|
|
3004
|
+
return parsed.protocol === "ws:" || parsed.protocol === "wss:";
|
|
3005
|
+
} catch {
|
|
3006
|
+
return false;
|
|
3007
|
+
}
|
|
3008
|
+
}
|
|
3009
|
+
var PLUGIN_CONFIG_KEY = "drawio-mcp-plugin-config";
|
|
3010
|
+
var cachedConfig = null;
|
|
3011
|
+
function isFileOrigin() {
|
|
3012
|
+
return typeof window !== "undefined" && window.location.protocol === "file:";
|
|
3013
|
+
}
|
|
3014
|
+
async function fetchPluginConfig() {
|
|
3015
|
+
if (cachedConfig) {
|
|
3016
|
+
return cachedConfig;
|
|
3017
|
+
}
|
|
3018
|
+
if (isFileOrigin()) {
|
|
3019
|
+
const stored = readPluginConfig();
|
|
3020
|
+
cachedConfig = stored;
|
|
3021
|
+
return stored;
|
|
3022
|
+
}
|
|
3023
|
+
try {
|
|
3024
|
+
const response = await fetch("/api/config");
|
|
3025
|
+
if (response.ok) {
|
|
3026
|
+
const serverConfig = await response.json();
|
|
3027
|
+
cachedConfig = {
|
|
3028
|
+
websocketPort: serverConfig.websocketPort || DEFAULT_PLUGIN_CONFIG.websocketPort,
|
|
3029
|
+
serverUrl: serverConfig.serverUrl || window.location.origin,
|
|
3030
|
+
websocketUrl: isValidWebSocketUrl(serverConfig.websocketUrl) ? serverConfig.websocketUrl : void 0
|
|
3031
|
+
};
|
|
3032
|
+
writePluginConfig(cachedConfig);
|
|
3033
|
+
return cachedConfig;
|
|
3034
|
+
}
|
|
3035
|
+
} catch (error) {
|
|
3036
|
+
console.warn("[pluginConfig] Failed to fetch config from server:", error);
|
|
3037
|
+
}
|
|
3038
|
+
return readPluginConfig();
|
|
3039
|
+
}
|
|
3040
|
+
function readPluginConfig() {
|
|
3041
|
+
try {
|
|
3042
|
+
const stored = localStorage.getItem(PLUGIN_CONFIG_KEY);
|
|
3043
|
+
if (stored) {
|
|
3044
|
+
const parsed = JSON.parse(stored);
|
|
3045
|
+
const validated = validatePluginConfig(parsed);
|
|
3046
|
+
if (validated.isValid && validated.config) {
|
|
3047
|
+
return validated.config;
|
|
3048
|
+
}
|
|
3049
|
+
}
|
|
3050
|
+
} catch (error) {
|
|
3051
|
+
console.warn("[pluginConfig] Failed to read from localStorage:", error);
|
|
3052
|
+
}
|
|
3053
|
+
return { ...DEFAULT_PLUGIN_CONFIG };
|
|
3054
|
+
}
|
|
3055
|
+
function writePluginConfig(config) {
|
|
3056
|
+
try {
|
|
3057
|
+
localStorage.setItem(PLUGIN_CONFIG_KEY, JSON.stringify(config));
|
|
3058
|
+
cachedConfig = config;
|
|
3059
|
+
} catch (error) {
|
|
3060
|
+
console.error("[pluginConfig] Failed to write to localStorage:", error);
|
|
3061
|
+
throw error;
|
|
3062
|
+
}
|
|
3063
|
+
}
|
|
3064
|
+
function validatePluginConfig(config) {
|
|
3065
|
+
if (!config || typeof config !== "object") {
|
|
3066
|
+
return { isValid: false, error: "Configuration must be an object" };
|
|
3067
|
+
}
|
|
3068
|
+
const cfg = config;
|
|
3069
|
+
if (typeof cfg.websocketPort !== "number") {
|
|
3070
|
+
return { isValid: false, error: "websocketPort must be a number" };
|
|
3071
|
+
}
|
|
3072
|
+
if (cfg.websocketPort < 1024 || cfg.websocketPort > 65535) {
|
|
3073
|
+
return {
|
|
3074
|
+
isValid: false,
|
|
3075
|
+
error: "websocketPort must be between 1024 and 65535"
|
|
3076
|
+
};
|
|
3077
|
+
}
|
|
3078
|
+
const websocketUrl = isValidWebSocketUrl(cfg.websocketUrl) ? cfg.websocketUrl : void 0;
|
|
3079
|
+
return {
|
|
3080
|
+
isValid: true,
|
|
3081
|
+
config: {
|
|
3082
|
+
websocketPort: cfg.websocketPort,
|
|
3083
|
+
serverUrl: cfg.serverUrl || "",
|
|
3084
|
+
websocketUrl
|
|
3085
|
+
}
|
|
3086
|
+
};
|
|
3087
|
+
}
|
|
3088
|
+
function buildWebSocketUrl(config) {
|
|
3089
|
+
if (config.websocketUrl) {
|
|
3090
|
+
return config.websocketUrl;
|
|
3091
|
+
}
|
|
3092
|
+
const isFile = isFileOrigin();
|
|
3093
|
+
const scheme = !isFile && window.location.protocol === "https:" ? "wss:" : "ws:";
|
|
3094
|
+
const hostname = window.location.hostname;
|
|
3095
|
+
const host = isFile || hostname.length === 0 ? "localhost" : hostname;
|
|
3096
|
+
return `${scheme}//${host}:${config.websocketPort}`;
|
|
3097
|
+
}
|
|
3098
|
+
|
|
3099
|
+
// src/settingsDialog.ts
|
|
3100
|
+
function defaultUrlFor(config) {
|
|
3101
|
+
return buildWebSocketUrl({ ...config, websocketUrl: void 0 });
|
|
3102
|
+
}
|
|
3103
|
+
function effectiveUrlFor(config) {
|
|
3104
|
+
return buildWebSocketUrl(config);
|
|
3105
|
+
}
|
|
3106
|
+
function createDialogContainer() {
|
|
3107
|
+
const container = document.createElement("div");
|
|
3108
|
+
container.id = "mcp-settings-dialog";
|
|
3109
|
+
container.style.cssText = `
|
|
3110
|
+
position: fixed;
|
|
3111
|
+
top: 0;
|
|
3112
|
+
left: 0;
|
|
3113
|
+
width: 100%;
|
|
3114
|
+
height: 100%;
|
|
3115
|
+
background-color: rgba(0, 0, 0, 0.5);
|
|
3116
|
+
display: flex;
|
|
3117
|
+
justify-content: center;
|
|
3118
|
+
align-items: center;
|
|
3119
|
+
z-index: 10000;
|
|
3120
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
3121
|
+
`;
|
|
3122
|
+
container.addEventListener("click", (e) => {
|
|
3123
|
+
if (e.target === container) {
|
|
3124
|
+
e.stopPropagation();
|
|
3125
|
+
}
|
|
3126
|
+
});
|
|
3127
|
+
return container;
|
|
3128
|
+
}
|
|
3129
|
+
function createDialogContent() {
|
|
3130
|
+
const content = document.createElement("div");
|
|
3131
|
+
content.className = "dialog-content";
|
|
3132
|
+
content.style.cssText = `
|
|
3133
|
+
background: white;
|
|
3134
|
+
border-radius: 8px;
|
|
3135
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
|
3136
|
+
max-width: 500px;
|
|
3137
|
+
width: 90%;
|
|
3138
|
+
max-height: 90vh;
|
|
3139
|
+
overflow-y: auto;
|
|
3140
|
+
position: relative;
|
|
3141
|
+
`;
|
|
3142
|
+
return content;
|
|
3143
|
+
}
|
|
3144
|
+
function createDialogHeader(title, onClose) {
|
|
3145
|
+
const header = document.createElement("div");
|
|
3146
|
+
header.className = "dialog-header";
|
|
3147
|
+
header.style.cssText = `
|
|
3148
|
+
padding: 16px 20px;
|
|
3149
|
+
border-bottom: 1px solid #e0e0e0;
|
|
3150
|
+
display: flex;
|
|
3151
|
+
justify-content: space-between;
|
|
3152
|
+
align-items: center;
|
|
3153
|
+
`;
|
|
3154
|
+
const titleEl = document.createElement("h2");
|
|
3155
|
+
titleEl.textContent = title;
|
|
3156
|
+
titleEl.style.cssText = `
|
|
3157
|
+
margin: 0;
|
|
3158
|
+
font-size: 18px;
|
|
3159
|
+
font-weight: 600;
|
|
3160
|
+
color: #333;
|
|
3161
|
+
`;
|
|
3162
|
+
const closeBtn = document.createElement("button");
|
|
3163
|
+
closeBtn.textContent = "\xD7";
|
|
3164
|
+
closeBtn.style.cssText = `
|
|
3165
|
+
background: none;
|
|
3166
|
+
border: none;
|
|
3167
|
+
font-size: 24px;
|
|
3168
|
+
cursor: pointer;
|
|
3169
|
+
padding: 0;
|
|
3170
|
+
width: 24px;
|
|
3171
|
+
height: 24px;
|
|
3172
|
+
display: flex;
|
|
3173
|
+
align-items: center;
|
|
3174
|
+
justify-content: center;
|
|
3175
|
+
color: #666;
|
|
3176
|
+
border-radius: 4px;
|
|
3177
|
+
`;
|
|
3178
|
+
closeBtn.title = "Close";
|
|
3179
|
+
closeBtn.addEventListener("mouseenter", () => {
|
|
3180
|
+
closeBtn.style.backgroundColor = "#f5f5f5";
|
|
3181
|
+
});
|
|
3182
|
+
closeBtn.addEventListener("mouseleave", () => {
|
|
3183
|
+
closeBtn.style.backgroundColor = "transparent";
|
|
3184
|
+
});
|
|
3185
|
+
closeBtn.addEventListener("click", onClose);
|
|
3186
|
+
header.appendChild(titleEl);
|
|
3187
|
+
header.appendChild(closeBtn);
|
|
3188
|
+
return header;
|
|
3189
|
+
}
|
|
3190
|
+
function createDialogBody(state) {
|
|
3191
|
+
const body = document.createElement("div");
|
|
3192
|
+
body.className = "dialog-body";
|
|
3193
|
+
body.style.cssText = `
|
|
3194
|
+
padding: 20px;
|
|
3195
|
+
`;
|
|
3196
|
+
const statusSection = createStatusSection(state);
|
|
3197
|
+
body.appendChild(statusSection);
|
|
3198
|
+
const formSection = createFormSection(state);
|
|
3199
|
+
body.appendChild(formSection);
|
|
3200
|
+
return body;
|
|
3201
|
+
}
|
|
3202
|
+
function createStatusSection(state) {
|
|
3203
|
+
const section = document.createElement("div");
|
|
3204
|
+
section.className = "status-section";
|
|
3205
|
+
section.style.cssText = `
|
|
3206
|
+
margin-bottom: 24px;
|
|
3207
|
+
padding: 16px;
|
|
3208
|
+
background: #f8f9fa;
|
|
3209
|
+
border-radius: 6px;
|
|
3210
|
+
border: 1px solid #e9ecef;
|
|
3211
|
+
`;
|
|
3212
|
+
const title = document.createElement("div");
|
|
3213
|
+
title.style.cssText = `
|
|
3214
|
+
font-weight: 600;
|
|
3215
|
+
margin-bottom: 8px;
|
|
3216
|
+
color: #333;
|
|
3217
|
+
`;
|
|
3218
|
+
title.textContent = "Connection Status";
|
|
3219
|
+
const statusIndicator = document.createElement("div");
|
|
3220
|
+
statusIndicator.className = "status-indicator";
|
|
3221
|
+
statusIndicator.style.cssText = `
|
|
3222
|
+
display: flex;
|
|
3223
|
+
align-items: center;
|
|
3224
|
+
gap: 8px;
|
|
3225
|
+
margin-bottom: 4px;
|
|
3226
|
+
`;
|
|
3227
|
+
const indicator = document.createElement("div");
|
|
3228
|
+
indicator.style.cssText = `
|
|
3229
|
+
width: 12px;
|
|
3230
|
+
height: 12px;
|
|
3231
|
+
border-radius: 50%;
|
|
3232
|
+
flex-shrink: 0;
|
|
3233
|
+
`;
|
|
3234
|
+
switch (state.connectionState) {
|
|
3235
|
+
case "connected":
|
|
3236
|
+
indicator.style.backgroundColor = "#28a745";
|
|
3237
|
+
break;
|
|
3238
|
+
case "connecting":
|
|
3239
|
+
indicator.style.backgroundColor = "#ffc107";
|
|
3240
|
+
break;
|
|
3241
|
+
case "disconnected":
|
|
3242
|
+
indicator.style.backgroundColor = "#dc3545";
|
|
3243
|
+
break;
|
|
3244
|
+
}
|
|
3245
|
+
const statusText = document.createElement("span");
|
|
3246
|
+
statusText.textContent = state.connectionState.charAt(0).toUpperCase() + state.connectionState.slice(1);
|
|
3247
|
+
statusText.style.fontWeight = "500";
|
|
3248
|
+
statusIndicator.appendChild(indicator);
|
|
3249
|
+
statusIndicator.appendChild(statusText);
|
|
3250
|
+
const urlDisplay = document.createElement("div");
|
|
3251
|
+
urlDisplay.style.cssText = `
|
|
3252
|
+
font-size: 14px;
|
|
3253
|
+
color: #666;
|
|
3254
|
+
word-break: break-all;
|
|
3255
|
+
`;
|
|
3256
|
+
urlDisplay.textContent = `URL: ${effectiveUrlFor(state.config)}`;
|
|
3257
|
+
section.appendChild(title);
|
|
3258
|
+
section.appendChild(statusIndicator);
|
|
3259
|
+
section.appendChild(urlDisplay);
|
|
3260
|
+
return section;
|
|
3261
|
+
}
|
|
3262
|
+
function createFormSection(state) {
|
|
3263
|
+
const section = document.createElement("div");
|
|
3264
|
+
section.className = "form-section";
|
|
3265
|
+
const urlGroup = document.createElement("div");
|
|
3266
|
+
urlGroup.className = "form-group";
|
|
3267
|
+
urlGroup.style.cssText = `
|
|
3268
|
+
margin-bottom: 16px;
|
|
3269
|
+
`;
|
|
3270
|
+
const label = document.createElement("label");
|
|
3271
|
+
label.textContent = "WebSocket URL";
|
|
3272
|
+
label.htmlFor = "mcp-url-input";
|
|
3273
|
+
label.style.cssText = `
|
|
3274
|
+
display: block;
|
|
3275
|
+
margin-bottom: 6px;
|
|
3276
|
+
font-weight: 500;
|
|
3277
|
+
color: #333;
|
|
3278
|
+
`;
|
|
3279
|
+
const input = document.createElement("input");
|
|
3280
|
+
input.id = "mcp-url-input";
|
|
3281
|
+
input.type = "text";
|
|
3282
|
+
input.spellcheck = false;
|
|
3283
|
+
input.autocomplete = "off";
|
|
3284
|
+
input.value = state.formData.url;
|
|
3285
|
+
input.placeholder = defaultUrlFor(state.config);
|
|
3286
|
+
input.style.cssText = `
|
|
3287
|
+
width: 100%;
|
|
3288
|
+
padding: 8px 12px;
|
|
3289
|
+
border: 1px solid #ddd;
|
|
3290
|
+
border-radius: 4px;
|
|
3291
|
+
font-size: 14px;
|
|
3292
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
3293
|
+
box-sizing: border-box;
|
|
3294
|
+
`;
|
|
3295
|
+
if (state.errors.url) {
|
|
3296
|
+
input.style.borderColor = "#dc3545";
|
|
3297
|
+
}
|
|
3298
|
+
input.addEventListener("input", (e) => {
|
|
3299
|
+
const value = e.target.value;
|
|
3300
|
+
window.dispatchEvent(
|
|
3301
|
+
new CustomEvent("mcp-settings-message", {
|
|
3302
|
+
detail: { type: "UPDATE_URL", url: value }
|
|
3303
|
+
})
|
|
3304
|
+
);
|
|
3305
|
+
});
|
|
3306
|
+
const hint = document.createElement("div");
|
|
3307
|
+
hint.textContent = `Leave blank to use the default (${defaultUrlFor(state.config)}). Must start with ws:// or wss://`;
|
|
3308
|
+
hint.style.cssText = `
|
|
3309
|
+
font-size: 12px;
|
|
3310
|
+
color: #666;
|
|
3311
|
+
margin-top: 4px;
|
|
3312
|
+
word-break: break-all;
|
|
3313
|
+
`;
|
|
3314
|
+
urlGroup.appendChild(label);
|
|
3315
|
+
urlGroup.appendChild(input);
|
|
3316
|
+
urlGroup.appendChild(hint);
|
|
3317
|
+
if (state.errors.url) {
|
|
3318
|
+
const error = document.createElement("div");
|
|
3319
|
+
error.textContent = state.errors.url;
|
|
3320
|
+
error.style.cssText = `
|
|
3321
|
+
font-size: 12px;
|
|
3322
|
+
color: #dc3545;
|
|
3323
|
+
margin-top: 4px;
|
|
3324
|
+
`;
|
|
3325
|
+
urlGroup.appendChild(error);
|
|
3326
|
+
}
|
|
3327
|
+
section.appendChild(urlGroup);
|
|
3328
|
+
return section;
|
|
3329
|
+
}
|
|
3330
|
+
function createDialogFooter(state) {
|
|
3331
|
+
const footer = document.createElement("div");
|
|
3332
|
+
footer.className = "dialog-footer";
|
|
3333
|
+
footer.style.cssText = `
|
|
3334
|
+
padding: 16px 20px;
|
|
3335
|
+
border-top: 1px solid #e0e0e0;
|
|
3336
|
+
display: flex;
|
|
3337
|
+
justify-content: space-between;
|
|
3338
|
+
gap: 12px;
|
|
3339
|
+
flex-wrap: wrap;
|
|
3340
|
+
`;
|
|
3341
|
+
const leftActions = document.createElement("div");
|
|
3342
|
+
leftActions.style.cssText = `
|
|
3343
|
+
display: flex;
|
|
3344
|
+
gap: 8px;
|
|
3345
|
+
flex-wrap: wrap;
|
|
3346
|
+
`;
|
|
3347
|
+
const rightActions = document.createElement("div");
|
|
3348
|
+
rightActions.style.cssText = `
|
|
3349
|
+
display: flex;
|
|
3350
|
+
gap: 8px;
|
|
3351
|
+
`;
|
|
3352
|
+
const cancelBtn = createButton("Cancel", "ghost", () => {
|
|
3353
|
+
window.dispatchEvent(
|
|
3354
|
+
new CustomEvent("mcp-settings-message", {
|
|
3355
|
+
detail: { type: "CLOSE" }
|
|
3356
|
+
})
|
|
3357
|
+
);
|
|
3358
|
+
});
|
|
3359
|
+
const saveBtn = createButton(
|
|
3360
|
+
state.isSaving ? "Saving..." : "Save",
|
|
3361
|
+
"primary",
|
|
3362
|
+
() => {
|
|
3363
|
+
window.dispatchEvent(
|
|
3364
|
+
new CustomEvent("mcp-settings-message", {
|
|
3365
|
+
detail: { type: "SAVE" }
|
|
3366
|
+
})
|
|
3367
|
+
);
|
|
3368
|
+
},
|
|
3369
|
+
state.isSaving
|
|
3370
|
+
);
|
|
3371
|
+
rightActions.appendChild(cancelBtn);
|
|
3372
|
+
rightActions.appendChild(saveBtn);
|
|
3373
|
+
footer.appendChild(leftActions);
|
|
3374
|
+
footer.appendChild(rightActions);
|
|
3375
|
+
return footer;
|
|
3376
|
+
}
|
|
3377
|
+
function createButton(text, variant, onClick, disabled = false) {
|
|
3378
|
+
const btn = document.createElement("button");
|
|
3379
|
+
btn.textContent = text;
|
|
3380
|
+
btn.disabled = disabled;
|
|
3381
|
+
btn.style.cssText = `
|
|
3382
|
+
padding: 8px 16px;
|
|
3383
|
+
border-radius: 4px;
|
|
3384
|
+
font-size: 14px;
|
|
3385
|
+
cursor: pointer;
|
|
3386
|
+
border: 1px solid transparent;
|
|
3387
|
+
transition: all 0.2s;
|
|
3388
|
+
`;
|
|
3389
|
+
switch (variant) {
|
|
3390
|
+
case "primary":
|
|
3391
|
+
btn.style.cssText += `
|
|
3392
|
+
background-color: #007bff;
|
|
3393
|
+
color: white;
|
|
3394
|
+
border-color: #007bff;
|
|
3395
|
+
`;
|
|
3396
|
+
btn.addEventListener("mouseenter", () => {
|
|
3397
|
+
if (!disabled) btn.style.backgroundColor = "#0056b3";
|
|
3398
|
+
});
|
|
3399
|
+
btn.addEventListener("mouseleave", () => {
|
|
3400
|
+
if (!disabled) btn.style.backgroundColor = "#007bff";
|
|
3401
|
+
});
|
|
3402
|
+
break;
|
|
3403
|
+
case "secondary":
|
|
3404
|
+
btn.style.cssText += `
|
|
3405
|
+
background-color: #6c757d;
|
|
3406
|
+
color: white;
|
|
3407
|
+
border-color: #6c757d;
|
|
3408
|
+
`;
|
|
3409
|
+
btn.addEventListener("mouseenter", () => {
|
|
3410
|
+
if (!disabled) btn.style.backgroundColor = "#545b62";
|
|
3411
|
+
});
|
|
3412
|
+
btn.addEventListener("mouseleave", () => {
|
|
3413
|
+
if (!disabled) btn.style.backgroundColor = "#6c757d";
|
|
3414
|
+
});
|
|
3415
|
+
break;
|
|
3416
|
+
case "ghost":
|
|
3417
|
+
btn.style.cssText += `
|
|
3418
|
+
background-color: transparent;
|
|
3419
|
+
color: #6c757d;
|
|
3420
|
+
border-color: #6c757d;
|
|
3421
|
+
`;
|
|
3422
|
+
btn.addEventListener("mouseenter", () => {
|
|
3423
|
+
if (!disabled) {
|
|
3424
|
+
btn.style.backgroundColor = "#f8f9fa";
|
|
2263
3425
|
}
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
};
|
|
2270
|
-
default:
|
|
2271
|
-
return { success: false, message: `Unsupported import mode: ${mode}` };
|
|
2272
|
-
}
|
|
2273
|
-
} catch (error) {
|
|
2274
|
-
console.error("[import-diagram] Error importing diagram:", error);
|
|
2275
|
-
return {
|
|
2276
|
-
success: false,
|
|
2277
|
-
message: `Import failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
2278
|
-
};
|
|
3426
|
+
});
|
|
3427
|
+
btn.addEventListener("mouseleave", () => {
|
|
3428
|
+
if (!disabled) btn.style.backgroundColor = "transparent";
|
|
3429
|
+
});
|
|
3430
|
+
break;
|
|
2279
3431
|
}
|
|
3432
|
+
if (disabled) {
|
|
3433
|
+
btn.style.cssText += `
|
|
3434
|
+
opacity: 0.6;
|
|
3435
|
+
cursor: not-allowed;
|
|
3436
|
+
`;
|
|
3437
|
+
}
|
|
3438
|
+
btn.addEventListener("click", onClick);
|
|
3439
|
+
return btn;
|
|
2280
3440
|
}
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
);
|
|
2298
|
-
const
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
3441
|
+
function createSettingsDialog(initialState, actions) {
|
|
3442
|
+
let currentState = { ...initialState };
|
|
3443
|
+
let dialogElement = null;
|
|
3444
|
+
let isVisible = false;
|
|
3445
|
+
const update = (newState) => {
|
|
3446
|
+
currentState = { ...newState };
|
|
3447
|
+
if (dialogElement && isVisible) {
|
|
3448
|
+
render();
|
|
3449
|
+
}
|
|
3450
|
+
};
|
|
3451
|
+
const render = () => {
|
|
3452
|
+
if (dialogElement && dialogElement.parentNode) {
|
|
3453
|
+
dialogElement.parentNode.removeChild(dialogElement);
|
|
3454
|
+
}
|
|
3455
|
+
const container = createDialogContainer();
|
|
3456
|
+
const content = createDialogContent();
|
|
3457
|
+
const header = createDialogHeader("MCP Settings", () => actions.onClose());
|
|
3458
|
+
const body = createDialogBody(currentState);
|
|
3459
|
+
const footer = createDialogFooter(currentState);
|
|
3460
|
+
content.appendChild(header);
|
|
3461
|
+
content.appendChild(body);
|
|
3462
|
+
content.appendChild(footer);
|
|
3463
|
+
container.appendChild(content);
|
|
3464
|
+
dialogElement = container;
|
|
3465
|
+
isVisible = true;
|
|
3466
|
+
setupMessageListeners(container, actions);
|
|
3467
|
+
return container;
|
|
3468
|
+
};
|
|
3469
|
+
const setupMessageListeners = (container, actions2) => {
|
|
3470
|
+
const handleMessage = (event) => {
|
|
3471
|
+
const message = event.detail;
|
|
3472
|
+
switch (message.type) {
|
|
3473
|
+
case "UPDATE_URL":
|
|
3474
|
+
currentState.formData.url = message.url;
|
|
3475
|
+
delete currentState.errors.url;
|
|
3476
|
+
break;
|
|
3477
|
+
case "SAVE":
|
|
3478
|
+
if (!validateAndSave()) {
|
|
3479
|
+
update(currentState);
|
|
3480
|
+
}
|
|
3481
|
+
break;
|
|
3482
|
+
case "CLOSE":
|
|
3483
|
+
actions2.onClose();
|
|
3484
|
+
break;
|
|
2308
3485
|
}
|
|
2309
|
-
return reply;
|
|
2310
3486
|
};
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
3487
|
+
window.addEventListener(
|
|
3488
|
+
"mcp-settings-message",
|
|
3489
|
+
handleMessage
|
|
3490
|
+
);
|
|
3491
|
+
const observer = new MutationObserver((mutations) => {
|
|
3492
|
+
mutations.forEach((mutation) => {
|
|
3493
|
+
mutation.removedNodes.forEach((node) => {
|
|
3494
|
+
if (node === container) {
|
|
3495
|
+
window.removeEventListener(
|
|
3496
|
+
"mcp-settings-message",
|
|
3497
|
+
handleMessage
|
|
2320
3498
|
);
|
|
2321
|
-
|
|
3499
|
+
observer.disconnect();
|
|
2322
3500
|
}
|
|
2323
|
-
);
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
console.error(
|
|
2329
|
-
`[plugin] Tool ${toolName} failed for request ID ${request.__request_id}:`,
|
|
2330
|
-
error
|
|
2331
|
-
);
|
|
2332
|
-
return sendReply(void 0, false, error);
|
|
3501
|
+
});
|
|
3502
|
+
});
|
|
3503
|
+
});
|
|
3504
|
+
if (container.parentNode) {
|
|
3505
|
+
observer.observe(container.parentNode, { childList: true });
|
|
2333
3506
|
}
|
|
2334
3507
|
};
|
|
2335
|
-
|
|
3508
|
+
const validateAndSave = () => {
|
|
3509
|
+
const trimmed = currentState.formData.url.trim();
|
|
3510
|
+
if (trimmed.length > 0 && !isValidWebSocketUrl(trimmed)) {
|
|
3511
|
+
currentState.errors.url = "URL must start with ws:// or wss://";
|
|
3512
|
+
return false;
|
|
3513
|
+
}
|
|
3514
|
+
currentState.errors = {};
|
|
3515
|
+
currentState.isSaving = true;
|
|
3516
|
+
const newConfig = {
|
|
3517
|
+
...currentState.config,
|
|
3518
|
+
websocketUrl: trimmed.length > 0 ? trimmed : void 0
|
|
3519
|
+
};
|
|
3520
|
+
actions.onSave(newConfig);
|
|
3521
|
+
return true;
|
|
3522
|
+
};
|
|
3523
|
+
const dialogProxy = {
|
|
3524
|
+
get element() {
|
|
3525
|
+
if (!dialogElement) {
|
|
3526
|
+
render();
|
|
3527
|
+
}
|
|
3528
|
+
return dialogElement;
|
|
3529
|
+
},
|
|
3530
|
+
update
|
|
3531
|
+
};
|
|
3532
|
+
return dialogProxy;
|
|
3533
|
+
}
|
|
3534
|
+
function showSettingsDialog(dialog) {
|
|
3535
|
+
if (!dialog.element.parentNode) {
|
|
3536
|
+
document.body.appendChild(dialog.element);
|
|
3537
|
+
}
|
|
3538
|
+
}
|
|
3539
|
+
function hideSettingsDialog(dialog) {
|
|
3540
|
+
if (dialog.element.parentNode) {
|
|
3541
|
+
dialog.element.parentNode.removeChild(dialog.element);
|
|
3542
|
+
}
|
|
3543
|
+
}
|
|
3544
|
+
|
|
3545
|
+
// src/plugin.ts
|
|
2336
3546
|
var ui;
|
|
2337
3547
|
var wsManager = null;
|
|
3548
|
+
var bootstrapListener = null;
|
|
2338
3549
|
var settingsDialog = null;
|
|
2339
|
-
var
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
return ui2.editor.graph.getSelectionCell() || "no cell selected";
|
|
2345
|
-
}
|
|
2346
|
-
},
|
|
2347
|
-
{
|
|
2348
|
-
name: "add-rectangle",
|
|
2349
|
-
params: /* @__PURE__ */ new Set(["x", "y", "width", "height", "text", "style", "parent_id"]),
|
|
2350
|
-
handler: add_new_rectangle
|
|
2351
|
-
},
|
|
2352
|
-
{
|
|
2353
|
-
name: "delete-cell-by-id",
|
|
2354
|
-
params: /* @__PURE__ */ new Set(["cell_id"]),
|
|
2355
|
-
handler: delete_cell_by_id
|
|
2356
|
-
},
|
|
2357
|
-
{
|
|
2358
|
-
name: "add-edge",
|
|
2359
|
-
params: /* @__PURE__ */ new Set(["source_id", "target_id", "style", "text", "parent_id", "points"]),
|
|
2360
|
-
handler: add_edge
|
|
2361
|
-
},
|
|
2362
|
-
{
|
|
2363
|
-
name: "get-shape-categories",
|
|
2364
|
-
params: /* @__PURE__ */ new Set([]),
|
|
2365
|
-
handler: get_shape_categories
|
|
2366
|
-
},
|
|
2367
|
-
{
|
|
2368
|
-
name: "get-shapes-in-category",
|
|
2369
|
-
params: /* @__PURE__ */ new Set(["category_id"]),
|
|
2370
|
-
handler: get_shapes_in_category
|
|
2371
|
-
},
|
|
2372
|
-
{
|
|
2373
|
-
name: "get-shape-by-name",
|
|
2374
|
-
params: /* @__PURE__ */ new Set(["shape_name"]),
|
|
2375
|
-
handler: get_shape_by_name
|
|
2376
|
-
},
|
|
2377
|
-
{
|
|
2378
|
-
name: "add-cell-of-shape",
|
|
2379
|
-
params: /* @__PURE__ */ new Set([
|
|
2380
|
-
"shape_name",
|
|
2381
|
-
"x",
|
|
2382
|
-
"y",
|
|
2383
|
-
"width",
|
|
2384
|
-
"height",
|
|
2385
|
-
"text",
|
|
2386
|
-
"style",
|
|
2387
|
-
"parent_id"
|
|
2388
|
-
]),
|
|
2389
|
-
handler: add_cell_of_shape
|
|
2390
|
-
},
|
|
2391
|
-
{
|
|
2392
|
-
name: "set-cell-shape",
|
|
2393
|
-
params: /* @__PURE__ */ new Set(["cell_id", "shape_name"]),
|
|
2394
|
-
handler: set_cell_shape
|
|
2395
|
-
},
|
|
2396
|
-
{
|
|
2397
|
-
name: "set-cell-data",
|
|
2398
|
-
params: /* @__PURE__ */ new Set(["cell_id", "key", "value"]),
|
|
2399
|
-
handler: (ui2, options) => {
|
|
2400
|
-
return set_cell_data(ui2, options);
|
|
2401
|
-
}
|
|
2402
|
-
},
|
|
2403
|
-
{
|
|
2404
|
-
name: "list-paged-model",
|
|
2405
|
-
params: /* @__PURE__ */ new Set(["page", "page_size", "filter"]),
|
|
2406
|
-
handler: list_paged_model
|
|
2407
|
-
},
|
|
2408
|
-
{
|
|
2409
|
-
name: "edit-cell",
|
|
2410
|
-
params: /* @__PURE__ */ new Set(["cell_id", "text", "x", "y", "width", "height", "style"]),
|
|
2411
|
-
handler: edit_cell
|
|
2412
|
-
},
|
|
2413
|
-
{
|
|
2414
|
-
name: "edit-edge",
|
|
2415
|
-
params: /* @__PURE__ */ new Set(["cell_id", "text", "source_id", "target_id", "style", "points"]),
|
|
2416
|
-
handler: edit_edge
|
|
2417
|
-
},
|
|
2418
|
-
{
|
|
2419
|
-
name: "list-layers",
|
|
2420
|
-
params: /* @__PURE__ */ new Set([]),
|
|
2421
|
-
handler: list_layers
|
|
2422
|
-
},
|
|
2423
|
-
{
|
|
2424
|
-
name: "set-active-layer",
|
|
2425
|
-
params: /* @__PURE__ */ new Set(["layer_id"]),
|
|
2426
|
-
handler: set_active_layer
|
|
2427
|
-
},
|
|
2428
|
-
{
|
|
2429
|
-
name: "move-cell-to-layer",
|
|
2430
|
-
params: /* @__PURE__ */ new Set(["cell_id", "target_layer_id"]),
|
|
2431
|
-
handler: move_cell_to_layer
|
|
2432
|
-
},
|
|
2433
|
-
{
|
|
2434
|
-
name: "set-cell-parent",
|
|
2435
|
-
params: /* @__PURE__ */ new Set(["cell_id", "parent_id"]),
|
|
2436
|
-
handler: set_cell_parent
|
|
2437
|
-
},
|
|
2438
|
-
{
|
|
2439
|
-
name: "get-active-layer",
|
|
2440
|
-
params: /* @__PURE__ */ new Set([]),
|
|
2441
|
-
handler: get_active_layer
|
|
2442
|
-
},
|
|
2443
|
-
{
|
|
2444
|
-
name: "create-layer",
|
|
2445
|
-
params: /* @__PURE__ */ new Set(["name"]),
|
|
2446
|
-
handler: create_layer
|
|
2447
|
-
},
|
|
2448
|
-
{
|
|
2449
|
-
name: "export-diagram",
|
|
2450
|
-
params: /* @__PURE__ */ new Set([
|
|
2451
|
-
"format",
|
|
2452
|
-
"scale",
|
|
2453
|
-
"border",
|
|
2454
|
-
"background",
|
|
2455
|
-
"shadow",
|
|
2456
|
-
"crop",
|
|
2457
|
-
"selection_only",
|
|
2458
|
-
"transparent",
|
|
2459
|
-
"dpi",
|
|
2460
|
-
"embed_xml",
|
|
2461
|
-
"size"
|
|
2462
|
-
]),
|
|
2463
|
-
handler: export_diagram
|
|
2464
|
-
},
|
|
2465
|
-
{
|
|
2466
|
-
name: "import-diagram",
|
|
2467
|
-
params: /* @__PURE__ */ new Set(["data", "format", "mode", "filename"]),
|
|
2468
|
-
handler: import_diagram
|
|
2469
|
-
}
|
|
2470
|
-
];
|
|
2471
|
-
var toolHandlers = /* @__PURE__ */ new Map();
|
|
2472
|
-
var handleWebSocketMessage = (message) => {
|
|
2473
|
-
console.debug("[plugin] Received WebSocket message:", message);
|
|
2474
|
-
if (message.__event && toolHandlers.has(message.__event)) {
|
|
2475
|
-
const handler = toolHandlers.get(message.__event);
|
|
2476
|
-
if (handler) {
|
|
2477
|
-
handler(message);
|
|
2478
|
-
}
|
|
3550
|
+
var transport = {
|
|
3551
|
+
send: (message) => wsManager?.send(message),
|
|
3552
|
+
onMessage: (listener) => {
|
|
3553
|
+
bootstrapListener = listener;
|
|
3554
|
+
wsManager?.onMessage(listener);
|
|
2479
3555
|
}
|
|
2480
3556
|
};
|
|
2481
3557
|
var initializeWebSocket = async () => {
|
|
@@ -2487,7 +3563,9 @@ var DrawMcp = (() => {
|
|
|
2487
3563
|
reconnectDelay: 3e3,
|
|
2488
3564
|
pingInterval: 3e4
|
|
2489
3565
|
});
|
|
2490
|
-
|
|
3566
|
+
if (bootstrapListener) {
|
|
3567
|
+
wsManager.onMessage(bootstrapListener);
|
|
3568
|
+
}
|
|
2491
3569
|
wsManager.connect();
|
|
2492
3570
|
console.log(`[plugin] WebSocket initialized with URL: ${wsUrl}`);
|
|
2493
3571
|
};
|
|
@@ -2499,7 +3577,7 @@ var DrawMcp = (() => {
|
|
|
2499
3577
|
connectionState,
|
|
2500
3578
|
isSaving: false,
|
|
2501
3579
|
formData: {
|
|
2502
|
-
|
|
3580
|
+
url: config.websocketUrl ?? ""
|
|
2503
3581
|
},
|
|
2504
3582
|
errors: {}
|
|
2505
3583
|
};
|
|
@@ -2509,7 +3587,7 @@ var DrawMcp = (() => {
|
|
|
2509
3587
|
if (wsManager) {
|
|
2510
3588
|
wsManager.disconnect();
|
|
2511
3589
|
}
|
|
2512
|
-
initializeWebSocket();
|
|
3590
|
+
void initializeWebSocket();
|
|
2513
3591
|
if (settingsDialog) {
|
|
2514
3592
|
settingsDialog.update({
|
|
2515
3593
|
...initialState,
|
|
@@ -2552,7 +3630,7 @@ var DrawMcp = (() => {
|
|
|
2552
3630
|
connectionState,
|
|
2553
3631
|
isSaving: false,
|
|
2554
3632
|
formData: {
|
|
2555
|
-
|
|
3633
|
+
url: config.websocketUrl ?? ""
|
|
2556
3634
|
},
|
|
2557
3635
|
errors: {}
|
|
2558
3636
|
});
|
|
@@ -2596,11 +3674,8 @@ var DrawMcp = (() => {
|
|
|
2596
3674
|
if (window.__DRAWIO_MCP_TEST_HOOKS__ === true) {
|
|
2597
3675
|
window.ui = drawioUI;
|
|
2598
3676
|
}
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
toolHandlers.set(def.name, handler);
|
|
2602
|
-
});
|
|
2603
|
-
initializeWebSocket();
|
|
3677
|
+
bootstrapPlugin({ ui, transport });
|
|
3678
|
+
void initializeWebSocket();
|
|
2604
3679
|
initializeSettingsDialog();
|
|
2605
3680
|
addMenuItem(ui);
|
|
2606
3681
|
console.info("[plugin] MCP Plugin fully initialized");
|