@agent-canvas/cli 0.8.0 → 0.9.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/dist/commands/__tests__/add-arrow.test.d.ts +1 -0
- package/dist/commands/__tests__/add-arrow.test.js +186 -0
- package/dist/commands/__tests__/add-image.test.d.ts +1 -0
- package/dist/commands/__tests__/add-image.test.js +170 -0
- package/dist/commands/__tests__/add-line.test.d.ts +1 -0
- package/dist/commands/__tests__/add-line.test.js +138 -0
- package/dist/commands/__tests__/add-polygon.test.d.ts +1 -0
- package/dist/commands/__tests__/add-polygon.test.js +147 -0
- package/dist/commands/__tests__/add-shape.test.d.ts +1 -0
- package/dist/commands/__tests__/add-shape.test.js +193 -0
- package/dist/commands/__tests__/add-text.test.d.ts +1 -0
- package/dist/commands/__tests__/add-text.test.js +144 -0
- package/dist/commands/__tests__/clear.test.d.ts +1 -0
- package/dist/commands/__tests__/clear.test.js +65 -0
- package/dist/commands/__tests__/delete-elements.test.d.ts +1 -0
- package/dist/commands/__tests__/delete-elements.test.js +103 -0
- package/dist/commands/__tests__/export.test.d.ts +1 -0
- package/dist/commands/__tests__/export.test.js +187 -0
- package/dist/commands/__tests__/group-elements.test.d.ts +1 -0
- package/dist/commands/__tests__/group-elements.test.js +93 -0
- package/dist/commands/__tests__/list.test.d.ts +1 -0
- package/dist/commands/__tests__/list.test.js +134 -0
- package/dist/commands/__tests__/load.test.d.ts +1 -0
- package/dist/commands/__tests__/load.test.js +158 -0
- package/dist/commands/__tests__/move-elements.test.d.ts +1 -0
- package/dist/commands/__tests__/move-elements.test.js +117 -0
- package/dist/commands/__tests__/new-canvas.test.d.ts +1 -0
- package/dist/commands/__tests__/new-canvas.test.js +113 -0
- package/dist/commands/__tests__/read.test.d.ts +1 -0
- package/dist/commands/__tests__/read.test.js +247 -0
- package/dist/commands/__tests__/rename-canvas.test.d.ts +1 -0
- package/dist/commands/__tests__/rename-canvas.test.js +86 -0
- package/dist/commands/__tests__/resize-elements.test.d.ts +1 -0
- package/dist/commands/__tests__/resize-elements.test.js +150 -0
- package/dist/commands/__tests__/rotate-elements.test.d.ts +1 -0
- package/dist/commands/__tests__/rotate-elements.test.js +114 -0
- package/dist/commands/__tests__/save.test.d.ts +1 -0
- package/dist/commands/__tests__/save.test.js +105 -0
- package/dist/commands/__tests__/ungroup-element.test.d.ts +1 -0
- package/dist/commands/__tests__/ungroup-element.test.js +93 -0
- package/dist/commands/__tests__/use-canvas.test.d.ts +1 -0
- package/dist/commands/__tests__/use-canvas.test.js +86 -0
- package/dist/commands/add-arrow.d.ts +40 -0
- package/dist/commands/add-arrow.js +52 -0
- package/dist/commands/add-image.d.ts +26 -0
- package/dist/commands/add-image.js +66 -0
- package/dist/commands/add-line.d.ts +27 -0
- package/dist/commands/add-line.js +35 -0
- package/dist/commands/add-polygon.d.ts +26 -0
- package/dist/commands/add-polygon.js +44 -0
- package/dist/commands/add-shape.d.ts +32 -0
- package/dist/commands/add-shape.js +41 -0
- package/dist/commands/add-text.d.ts +28 -0
- package/dist/commands/add-text.js +35 -0
- package/dist/commands/clear.d.ts +17 -0
- package/dist/commands/clear.js +23 -0
- package/dist/commands/delete-elements.d.ts +20 -0
- package/dist/commands/delete-elements.js +26 -0
- package/dist/commands/export.d.ts +26 -0
- package/dist/commands/export.js +45 -0
- package/dist/commands/group-elements.d.ts +20 -0
- package/dist/commands/group-elements.js +28 -0
- package/dist/commands/list.d.ts +23 -0
- package/dist/commands/list.js +50 -0
- package/dist/commands/load.d.ts +20 -0
- package/dist/commands/load.js +67 -0
- package/dist/commands/move-elements.d.ts +22 -0
- package/dist/commands/move-elements.js +26 -0
- package/dist/commands/new-canvas.d.ts +21 -0
- package/dist/commands/new-canvas.js +29 -0
- package/dist/commands/read.d.ts +23 -0
- package/dist/commands/read.js +49 -0
- package/dist/commands/rename-canvas.d.ts +20 -0
- package/dist/commands/rename-canvas.js +27 -0
- package/dist/commands/resize-elements.d.ts +24 -0
- package/dist/commands/resize-elements.js +41 -0
- package/dist/commands/rotate-elements.d.ts +21 -0
- package/dist/commands/rotate-elements.js +26 -0
- package/dist/commands/save.d.ts +18 -0
- package/dist/commands/save.js +27 -0
- package/dist/commands/start.d.ts +0 -1
- package/dist/commands/start.js +0 -41
- package/dist/commands/ungroup-element.d.ts +20 -0
- package/dist/commands/ungroup-element.js +28 -0
- package/dist/commands/use-canvas.d.ts +20 -0
- package/dist/commands/use-canvas.js +27 -0
- package/dist/index.js +124 -518
- package/dist/lib/__tests__/image-utils.test.d.ts +1 -0
- package/dist/lib/__tests__/image-utils.test.js +123 -0
- package/dist/lib/__tests__/toon-converter.test.d.ts +1 -0
- package/dist/lib/__tests__/toon-converter.test.js +586 -0
- package/dist/lib/__tests__/ws-client.test.d.ts +1 -0
- package/dist/lib/__tests__/ws-client.test.js +22 -0
- package/dist/lib/image-utils.d.ts +3 -0
- package/dist/lib/image-utils.js +21 -0
- package/dist/lib/protocol.d.ts +24 -0
- package/dist/lib/toon-converter.d.ts +104 -0
- package/dist/lib/toon-converter.js +221 -0
- package/dist/static/assets/{ar-SA-G6X2FPQ2-DrFZc17I.js → ar-SA-G6X2FPQ2-DBOnFzSe.js} +1 -1
- package/dist/static/assets/{arc-BE4RRWho.js → arc-bbUtBUEI.js} +1 -1
- package/dist/static/assets/{az-AZ-76LH7QW2-DgHo0c8x.js → az-AZ-76LH7QW2-Cc10aZ9u.js} +1 -1
- package/dist/static/assets/{bg-BG-XCXSNQG7-D6Qfq7sN.js → bg-BG-XCXSNQG7-Ccf7m1dz.js} +1 -1
- package/dist/static/assets/{blockDiagram-38ab4fdb-j4QCKNBJ.js → blockDiagram-38ab4fdb-fpHXuuqC.js} +1 -1
- package/dist/static/assets/{bn-BD-2XOGV67Q-DtD_GeTA.js → bn-BD-2XOGV67Q-DUsn1OkS.js} +1 -1
- package/dist/static/assets/{c4Diagram-3d4e48cf-BmQ9mE4L.js → c4Diagram-3d4e48cf-R8YUsP4D.js} +1 -1
- package/dist/static/assets/{ca-ES-6MX7JW3Y-pqblEVH2.js → ca-ES-6MX7JW3Y-hu4EsJg6.js} +1 -1
- package/dist/static/assets/channel-DOejQ6Zr.js +1 -0
- package/dist/static/assets/{classDiagram-70f12bd4-CUF5vm_X.js → classDiagram-70f12bd4-Bd-nCoOe.js} +1 -1
- package/dist/static/assets/{classDiagram-v2-f2320105-Cpj_A_lB.js → classDiagram-v2-f2320105-BSqlF2Ya.js} +1 -1
- package/dist/static/assets/clone-BACvnIVb.js +1 -0
- package/dist/static/assets/{createText-2e5e7dd3-pnM7Sebc.js → createText-2e5e7dd3-DDxcRLmM.js} +1 -1
- package/dist/static/assets/{cs-CZ-2BRQDIVT-CybzkHZt.js → cs-CZ-2BRQDIVT-CvZtKTE7.js} +1 -1
- package/dist/static/assets/{da-DK-5WZEPLOC-pqELhXiQ.js → da-DK-5WZEPLOC-Bo6-ltfA.js} +1 -1
- package/dist/static/assets/{de-DE-XR44H4JA-ZL76WiIL.js → de-DE-XR44H4JA-Rki2qM_x.js} +1 -1
- package/dist/static/assets/{edges-e0da2a9e-B9extNmC.js → edges-e0da2a9e-DWJxCouB.js} +1 -1
- package/dist/static/assets/{el-GR-BZB4AONW-rKEdKItN.js → el-GR-BZB4AONW-BRy2rrt9.js} +1 -1
- package/dist/static/assets/{erDiagram-9861fffd-Bf-1lr9-.js → erDiagram-9861fffd-DXldiM4J.js} +1 -1
- package/dist/static/assets/{es-ES-U4NZUMDT-BB6riLIk.js → es-ES-U4NZUMDT-hCKbxwHs.js} +1 -1
- package/dist/static/assets/{eu-ES-A7QVB2H4-ChqJNrpA.js → eu-ES-A7QVB2H4-CmZGwoa5.js} +1 -1
- package/dist/static/assets/{fa-IR-HGAKTJCU--KEd62Xu.js → fa-IR-HGAKTJCU-C6DRPcaF.js} +1 -1
- package/dist/static/assets/{fi-FI-Z5N7JZ37-CdB0adCJ.js → fi-FI-Z5N7JZ37-DBaspnIB.js} +1 -1
- package/dist/static/assets/{flowDb-956e92f1-Dbca38tY.js → flowDb-956e92f1-C48Cmgvd.js} +1 -1
- package/dist/static/assets/{flowDiagram-66a62f08-DpQc0ZQB.js → flowDiagram-66a62f08-DV7f8TtG.js} +1 -1
- package/dist/static/assets/flowDiagram-v2-96b9c2cf-MnAxlKb6.js +1 -0
- package/dist/static/assets/{flowchart-elk-definition-4a651766-CAxl2EAj.js → flowchart-elk-definition-4a651766-C2muEpzy.js} +1 -1
- package/dist/static/assets/{fr-FR-RHASNOE6-LEJbMD3b.js → fr-FR-RHASNOE6-D1dEEEfS.js} +1 -1
- package/dist/static/assets/{ganttDiagram-c361ad54-BsKueDb1.js → ganttDiagram-c361ad54-CrooqCzc.js} +1 -1
- package/dist/static/assets/{gitGraphDiagram-72cf32ee-BySoTKcT.js → gitGraphDiagram-72cf32ee-x7BVIo_3.js} +1 -1
- package/dist/static/assets/{gl-ES-HMX3MZ6V-Bi3P3M7W.js → gl-ES-HMX3MZ6V-Czkw2ahx.js} +1 -1
- package/dist/static/assets/{graph-B_0qOa-k.js → graph-Bv0C_szp.js} +1 -1
- package/dist/static/assets/{he-IL-6SHJWFNN-DE7_aRwg.js → he-IL-6SHJWFNN-BLwbN3CV.js} +1 -1
- package/dist/static/assets/{hi-IN-IWLTKZ5I-CjARmJ8i.js → hi-IN-IWLTKZ5I-BJh3HrXc.js} +1 -1
- package/dist/static/assets/{hu-HU-A5ZG7DT2-d79urL5L.js → hu-HU-A5ZG7DT2-D00s-8EN.js} +1 -1
- package/dist/static/assets/{id-ID-SAP4L64H-bxo8Q0Jv.js → id-ID-SAP4L64H-BmyuzwXV.js} +1 -1
- package/dist/static/assets/{index-3862675e-BLm8h60G.js → index-3862675e-mZlepZqF.js} +1 -1
- package/dist/static/assets/{index-BkW4NM9R.js → index-Bnmyv9TE.js} +4 -4
- package/dist/static/assets/index-jjzEa4oB.js +316 -0
- package/dist/static/assets/{infoDiagram-f8f76790-CZ4J5sjk.js → infoDiagram-f8f76790-w7FUTsVV.js} +1 -1
- package/dist/static/assets/{it-IT-JPQ66NNP-D41R3uEK.js → it-IT-JPQ66NNP-CeVq0l8v.js} +1 -1
- package/dist/static/assets/{ja-JP-DBVTYXUO-zK8NUJnS.js → ja-JP-DBVTYXUO-BUNKxxGA.js} +1 -1
- package/dist/static/assets/{journeyDiagram-49397b02-DtFcZaIk.js → journeyDiagram-49397b02-DYjDqkQG.js} +1 -1
- package/dist/static/assets/{kaa-6HZHGXH3-CbGIc6V6.js → kaa-6HZHGXH3-BIKwULqb.js} +1 -1
- package/dist/static/assets/{kab-KAB-ZGHBKWFO-BweHPuX1.js → kab-KAB-ZGHBKWFO-BDpRo7IX.js} +1 -1
- package/dist/static/assets/{kk-KZ-P5N5QNE5-DSokMm7h.js → kk-KZ-P5N5QNE5-bI2LN3W0.js} +1 -1
- package/dist/static/assets/{km-KH-HSX4SM5Z-LYiEs3ge.js → km-KH-HSX4SM5Z-gtwrLJn5.js} +1 -1
- package/dist/static/assets/{ko-KR-MTYHY66A-BzgMEtcU.js → ko-KR-MTYHY66A-BVcwVELq.js} +1 -1
- package/dist/static/assets/{ku-TR-6OUDTVRD-D1FtjbSs.js → ku-TR-6OUDTVRD-COvDJH7d.js} +1 -1
- package/dist/static/assets/{layout-CQWIZrii.js → layout-HBWJ9_zM.js} +1 -1
- package/dist/static/assets/{line-BryEd-Ku.js → line-DxrK6d-_.js} +1 -1
- package/dist/static/assets/{linear-SXhM57Mz.js → linear-TwnxNDQ0.js} +1 -1
- package/dist/static/assets/{lt-LT-XHIRWOB4-BPrhIUrC.js → lt-LT-XHIRWOB4-BxYB7tM6.js} +1 -1
- package/dist/static/assets/{lv-LV-5QDEKY6T-CXJse_rs.js → lv-LV-5QDEKY6T-CGURbwyW.js} +1 -1
- package/dist/static/assets/{mindmap-definition-fc14e90a-C8giDsiX.js → mindmap-definition-fc14e90a-CWJfWF5a.js} +1 -1
- package/dist/static/assets/{mr-IN-CRQNXWMA-Clab-bAO.js → mr-IN-CRQNXWMA-65brZPyQ.js} +1 -1
- package/dist/static/assets/{my-MM-5M5IBNSE-Dp08JzEw.js → my-MM-5M5IBNSE-DaCAmQNv.js} +1 -1
- package/dist/static/assets/{nb-NO-T6EIAALU-CiaXJA-W.js → nb-NO-T6EIAALU-BiSJhu0W.js} +1 -1
- package/dist/static/assets/{nl-NL-IS3SIHDZ-D-9KUTnx.js → nl-NL-IS3SIHDZ-D3rj4Vme.js} +1 -1
- package/dist/static/assets/{nn-NO-6E72VCQL-Bg5gsQ4h.js → nn-NO-6E72VCQL-rxxP7Cwf.js} +1 -1
- package/dist/static/assets/{oc-FR-POXYY2M6-G4iqllhL.js → oc-FR-POXYY2M6-6emd2NQX.js} +1 -1
- package/dist/static/assets/{pa-IN-N4M65BXN-l6Lk41uX.js → pa-IN-N4M65BXN-CXwT_z_m.js} +1 -1
- package/dist/static/assets/{pica-CtkejCRD.js → pica-CtyIOuSv.js} +1 -1
- package/dist/static/assets/{pieDiagram-8a3498a8-CG6gQ14H.js → pieDiagram-8a3498a8-Ccff4vHz.js} +1 -1
- package/dist/static/assets/{pl-PL-T2D74RX3-BZPbB8S3.js → pl-PL-T2D74RX3-DMx_ZmIC.js} +1 -1
- package/dist/static/assets/{pt-BR-5N22H2LF-CIC4vRyd.js → pt-BR-5N22H2LF-D9nz7afr.js} +1 -1
- package/dist/static/assets/{pt-PT-UZXXM6DQ-rkGTBEI0.js → pt-PT-UZXXM6DQ-DeFH3geX.js} +1 -1
- package/dist/static/assets/{quadrantDiagram-120e2f19-BL9eFu4M.js → quadrantDiagram-120e2f19-RF2ZGF1U.js} +1 -1
- package/dist/static/assets/{requirementDiagram-deff3bca-crxdUpVK.js → requirementDiagram-deff3bca-CvnD9QLg.js} +1 -1
- package/dist/static/assets/{ro-RO-JPDTUUEW-GDhpTKBO.js → ro-RO-JPDTUUEW-Cy22QAjW.js} +1 -1
- package/dist/static/assets/{ru-RU-B4JR7IUQ-BzHvMwjC.js → ru-RU-B4JR7IUQ-Cw2rH2nW.js} +1 -1
- package/dist/static/assets/{sankeyDiagram-04a897e0-bM05WQw3.js → sankeyDiagram-04a897e0-CWfRjMv0.js} +1 -1
- package/dist/static/assets/{sequenceDiagram-704730f1-DjknV0Qp.js → sequenceDiagram-704730f1-pAE8N_Ym.js} +1 -1
- package/dist/static/assets/{si-LK-N5RQ5JYF-D3P3TNDH.js → si-LK-N5RQ5JYF-DmXIZ3i0.js} +1 -1
- package/dist/static/assets/{sk-SK-C5VTKIMK-CM8yTXlZ.js → sk-SK-C5VTKIMK-CboHDpHd.js} +1 -1
- package/dist/static/assets/{sl-SI-NN7IZMDC-CxoGm3aM.js → sl-SI-NN7IZMDC-8XnCHmN4.js} +1 -1
- package/dist/static/assets/{stateDiagram-587899a1-CmWqIdF5.js → stateDiagram-587899a1-B4nuLay6.js} +1 -1
- package/dist/static/assets/{stateDiagram-v2-d93cdb3a-CgzNTiHW.js → stateDiagram-v2-d93cdb3a-9cMNxr_8.js} +1 -1
- package/dist/static/assets/{styles-6aaf32cf-CI4s6NIA.js → styles-6aaf32cf-CynMMkPq.js} +1 -1
- package/dist/static/assets/{styles-9a916d00-ZcdN6rtW.js → styles-9a916d00-BTmAnC2j.js} +1 -1
- package/dist/static/assets/{styles-c10674c1-ZFkD6ta7.js → styles-c10674c1-DQ_pTuGr.js} +1 -1
- package/dist/static/assets/{subset-shared.chunk-B4F4dEPr.js → subset-shared.chunk-DPGuz0R6.js} +1 -1
- package/dist/static/assets/{subset-worker.chunk-CmgaOgn3.js → subset-worker.chunk-CMiOYLER.js} +1 -1
- package/dist/static/assets/{sv-SE-XGPEYMSR-CnVZlafq.js → sv-SE-XGPEYMSR-ATPKfqXs.js} +1 -1
- package/dist/static/assets/{svgDrawCommon-08f97a94-DbN3OiBf.js → svgDrawCommon-08f97a94-qY4BnSWc.js} +1 -1
- package/dist/static/assets/{ta-IN-2NMHFXQM-Bl-eCjzL.js → ta-IN-2NMHFXQM-Ct5-Fher.js} +1 -1
- package/dist/static/assets/{th-TH-HPSO5L25-CNIGPjSR.js → th-TH-HPSO5L25-5a6bUzcv.js} +1 -1
- package/dist/static/assets/{timeline-definition-85554ec2-Cmr82Iq1.js → timeline-definition-85554ec2-Bgexbl3C.js} +1 -1
- package/dist/static/assets/{tr-TR-DEFEU3FU-Cx7HbGIA.js → tr-TR-DEFEU3FU-WsK7dnwA.js} +1 -1
- package/dist/static/assets/{uk-UA-QMV73CPH-BxcA50Ze.js → uk-UA-QMV73CPH-B_P61mnc.js} +1 -1
- package/dist/static/assets/{vi-VN-M7AON7JQ-BvGuRh0c.js → vi-VN-M7AON7JQ-qdiQcney.js} +1 -1
- package/dist/static/assets/{xychartDiagram-e933f94c-BcWLDEHu.js → xychartDiagram-e933f94c-vkQjFADD.js} +1 -1
- package/dist/static/assets/{zh-CN-LNUGB5OW-SQH8i3l5.js → zh-CN-LNUGB5OW-DQ3BQjPe.js} +1 -1
- package/dist/static/assets/{zh-HK-E62DVLB3-COWoLNur.js → zh-HK-E62DVLB3-Ynj07W9J.js} +1 -1
- package/dist/static/assets/{zh-TW-RAJ6MFWO-Cm5B69ig.js → zh-TW-RAJ6MFWO-DNkcasuo.js} +1 -1
- package/dist/static/index.html +1 -1
- package/package.json +5 -2
- package/dist/static/assets/channel-DjiT9qJ0.js +0 -1
- package/dist/static/assets/clone-nkJpLn4s.js +0 -1
- package/dist/static/assets/flowDiagram-v2-96b9c2cf-Dlfh8z7R.js +0 -1
- package/dist/static/assets/index-B6CTdFKu.js +0 -311
package/dist/index.js
CHANGED
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
import { writeFileSync } from 'node:fs';
|
|
3
|
-
import { encode as toToon } from '@toon-format/toon';
|
|
4
2
|
import { start } from './commands/start.js';
|
|
5
|
-
import {
|
|
3
|
+
import { load, defaultDeps as loadDeps } from './commands/load.js';
|
|
4
|
+
import { addImage, defaultDeps as addImageDeps } from './commands/add-image.js';
|
|
5
|
+
import { addShape, defaultDeps as addShapeDeps } from './commands/add-shape.js';
|
|
6
|
+
import { addText, defaultDeps as addTextDeps } from './commands/add-text.js';
|
|
7
|
+
import { addLine, defaultDeps as addLineDeps } from './commands/add-line.js';
|
|
8
|
+
import { addArrow, defaultDeps as addArrowDeps } from './commands/add-arrow.js';
|
|
9
|
+
import { addPolygon, defaultDeps as addPolygonDeps } from './commands/add-polygon.js';
|
|
10
|
+
import { resizeElements, defaultDeps as resizeElementsDeps } from './commands/resize-elements.js';
|
|
11
|
+
import { groupElements, defaultDeps as groupElementsDeps } from './commands/group-elements.js';
|
|
12
|
+
import { ungroupElement, defaultDeps as ungroupElementDeps } from './commands/ungroup-element.js';
|
|
13
|
+
import { deleteElements, defaultDeps as deleteElementsDeps } from './commands/delete-elements.js';
|
|
14
|
+
import { rotateElements, defaultDeps as rotateElementsDeps } from './commands/rotate-elements.js';
|
|
15
|
+
import { moveElements, defaultDeps as moveElementsDeps } from './commands/move-elements.js';
|
|
16
|
+
import { read, defaultDeps as readDeps } from './commands/read.js';
|
|
17
|
+
import { save, defaultDeps as saveDeps } from './commands/save.js';
|
|
18
|
+
import { exportImage, defaultDeps as exportDeps } from './commands/export.js';
|
|
19
|
+
import { clear, defaultDeps as clearDeps } from './commands/clear.js';
|
|
20
|
+
import { list, defaultDeps as listDeps } from './commands/list.js';
|
|
21
|
+
import { newCanvas, defaultDeps as newCanvasDeps } from './commands/new-canvas.js';
|
|
22
|
+
import { useCanvas, defaultDeps as useCanvasDeps } from './commands/use-canvas.js';
|
|
23
|
+
import { renameCanvas, defaultDeps as renameCanvasDeps } from './commands/rename-canvas.js';
|
|
6
24
|
const program = new Command();
|
|
7
25
|
program
|
|
8
26
|
.name('agent-canvas')
|
|
9
27
|
.description('CLI for Agent Canvas - Excalidraw interface for AI agents')
|
|
10
|
-
.version('0.
|
|
28
|
+
.version('0.9.0');
|
|
11
29
|
program
|
|
12
30
|
.command('start')
|
|
13
31
|
.description('Start the canvas server and open in browser')
|
|
@@ -18,8 +36,7 @@ program
|
|
|
18
36
|
.command('load [filepath]')
|
|
19
37
|
.description('Load an .excalidraw file into the current canvas')
|
|
20
38
|
.action(async (filepath) => {
|
|
21
|
-
|
|
22
|
-
await loadFile(filepath);
|
|
39
|
+
await load(filepath, loadDeps);
|
|
23
40
|
});
|
|
24
41
|
// ============================================================================
|
|
25
42
|
// Add Shape
|
|
@@ -41,8 +58,7 @@ program
|
|
|
41
58
|
.option('--label-font-size <number>', 'Label font size', parseFloat)
|
|
42
59
|
.option('-n, --note <text>', 'Note for this element (stored in customData)')
|
|
43
60
|
.action(async (options) => {
|
|
44
|
-
|
|
45
|
-
const params = {
|
|
61
|
+
await addShape({
|
|
46
62
|
type: options.type,
|
|
47
63
|
x: options.x,
|
|
48
64
|
y: options.y,
|
|
@@ -53,23 +69,10 @@ program
|
|
|
53
69
|
strokeWidth: options.strokeWidth,
|
|
54
70
|
strokeStyle: options.strokeStyle,
|
|
55
71
|
fillStyle: options.fillStyle,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
const result = await client.send({ type: 'addShape', id: generateId(), params });
|
|
62
|
-
if (result.success) {
|
|
63
|
-
const dims = result.width !== undefined && result.height !== undefined
|
|
64
|
-
? ` x=${result.x} y=${result.y} w=${result.width} h=${result.height}`
|
|
65
|
-
: '';
|
|
66
|
-
console.log(`Shape created (id: ${result.elementId}${dims})`);
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
console.error(`Failed: ${result.error}`);
|
|
70
|
-
process.exit(1);
|
|
71
|
-
}
|
|
72
|
-
client.close();
|
|
72
|
+
label: options.label,
|
|
73
|
+
labelFontSize: options.labelFontSize,
|
|
74
|
+
note: options.note,
|
|
75
|
+
}, addShapeDeps);
|
|
73
76
|
});
|
|
74
77
|
// ============================================================================
|
|
75
78
|
// Add Text
|
|
@@ -86,29 +89,16 @@ program
|
|
|
86
89
|
.option('--stroke-color <color>', 'Text color (hex)')
|
|
87
90
|
.option('-n, --note <text>', 'Note for this element (stored in customData)')
|
|
88
91
|
.action(async (options) => {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
anchor: options.anchor,
|
|
100
|
-
strokeColor: options.strokeColor,
|
|
101
|
-
customData: options.note ? { note: options.note } : undefined,
|
|
102
|
-
},
|
|
103
|
-
});
|
|
104
|
-
if (result.success) {
|
|
105
|
-
console.log(`Text created (id: ${result.elementId}, x: ${result.x}, y: ${result.y}, ${result.width}x${result.height})`);
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
console.error(`Failed: ${result.error}`);
|
|
109
|
-
process.exit(1);
|
|
110
|
-
}
|
|
111
|
-
client.close();
|
|
92
|
+
await addText({
|
|
93
|
+
text: options.text,
|
|
94
|
+
x: options.ax,
|
|
95
|
+
y: options.ay,
|
|
96
|
+
fontSize: options.fontSize,
|
|
97
|
+
textAlign: options.textAlign,
|
|
98
|
+
anchor: options.anchor,
|
|
99
|
+
strokeColor: options.strokeColor,
|
|
100
|
+
note: options.note,
|
|
101
|
+
}, addTextDeps);
|
|
112
102
|
});
|
|
113
103
|
// ============================================================================
|
|
114
104
|
// Add Line
|
|
@@ -125,29 +115,16 @@ program
|
|
|
125
115
|
.option('--stroke-style <style>', 'Line style: solid, dashed, or dotted')
|
|
126
116
|
.option('-n, --note <text>', 'Note for this element (stored in customData)')
|
|
127
117
|
.action(async (options) => {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
strokeWidth: options.strokeWidth,
|
|
139
|
-
strokeStyle: options.strokeStyle,
|
|
140
|
-
customData: options.note ? { note: options.note } : undefined,
|
|
141
|
-
},
|
|
142
|
-
});
|
|
143
|
-
if (result.success) {
|
|
144
|
-
console.log(`Line created (id: ${result.elementId})`);
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
console.error(`Failed: ${result.error}`);
|
|
148
|
-
process.exit(1);
|
|
149
|
-
}
|
|
150
|
-
client.close();
|
|
118
|
+
await addLine({
|
|
119
|
+
x: options.x,
|
|
120
|
+
y: options.y,
|
|
121
|
+
endX: options.endX,
|
|
122
|
+
endY: options.endY,
|
|
123
|
+
strokeColor: options.strokeColor,
|
|
124
|
+
strokeWidth: options.strokeWidth,
|
|
125
|
+
strokeStyle: options.strokeStyle,
|
|
126
|
+
note: options.note,
|
|
127
|
+
}, addLineDeps);
|
|
151
128
|
});
|
|
152
129
|
// ============================================================================
|
|
153
130
|
// Add Arrow
|
|
@@ -168,41 +145,20 @@ program
|
|
|
168
145
|
.option('--via <points>', 'Intermediate points as "x1,y1;x2,y2;..." (absolute coordinates). For round: 1 control point. For elbow: multiple turn points.')
|
|
169
146
|
.option('-n, --note <text>', 'Note for this element (stored in customData)')
|
|
170
147
|
.action(async (options) => {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
y: options.y,
|
|
186
|
-
endX: options.endX,
|
|
187
|
-
endY: options.endY,
|
|
188
|
-
strokeColor: options.strokeColor,
|
|
189
|
-
strokeWidth: options.strokeWidth,
|
|
190
|
-
strokeStyle: options.strokeStyle,
|
|
191
|
-
startArrowhead: options.startArrowhead,
|
|
192
|
-
endArrowhead: options.endArrowhead,
|
|
193
|
-
arrowType: options.arrowType,
|
|
194
|
-
midpoints,
|
|
195
|
-
customData: options.note ? { note: options.note } : undefined,
|
|
196
|
-
},
|
|
197
|
-
});
|
|
198
|
-
if (result.success) {
|
|
199
|
-
console.log(`Arrow created (id: ${result.elementId})`);
|
|
200
|
-
}
|
|
201
|
-
else {
|
|
202
|
-
console.error(`Failed: ${result.error}`);
|
|
203
|
-
process.exit(1);
|
|
204
|
-
}
|
|
205
|
-
client.close();
|
|
148
|
+
await addArrow({
|
|
149
|
+
x: options.x,
|
|
150
|
+
y: options.y,
|
|
151
|
+
endX: options.endX,
|
|
152
|
+
endY: options.endY,
|
|
153
|
+
strokeColor: options.strokeColor,
|
|
154
|
+
strokeWidth: options.strokeWidth,
|
|
155
|
+
strokeStyle: options.strokeStyle,
|
|
156
|
+
startArrowhead: options.startArrowhead,
|
|
157
|
+
endArrowhead: options.endArrowhead,
|
|
158
|
+
arrowType: options.arrowType,
|
|
159
|
+
via: options.via,
|
|
160
|
+
note: options.note,
|
|
161
|
+
}, addArrowDeps);
|
|
206
162
|
});
|
|
207
163
|
// ============================================================================
|
|
208
164
|
// Add Polygon
|
|
@@ -218,36 +174,37 @@ program
|
|
|
218
174
|
.option('--fill-style <style>', 'Fill style: hachure, cross-hatch, solid, or zigzag')
|
|
219
175
|
.option('-n, --note <text>', 'Note for this element (stored in customData)')
|
|
220
176
|
.action(async (options) => {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
177
|
+
await addPolygon({
|
|
178
|
+
points: options.points,
|
|
179
|
+
strokeColor: options.strokeColor,
|
|
180
|
+
backgroundColor: options.backgroundColor,
|
|
181
|
+
strokeWidth: options.strokeWidth,
|
|
182
|
+
strokeStyle: options.strokeStyle,
|
|
183
|
+
fillStyle: options.fillStyle,
|
|
184
|
+
note: options.note,
|
|
185
|
+
}, addPolygonDeps);
|
|
186
|
+
});
|
|
187
|
+
// ============================================================================
|
|
188
|
+
// Add Image
|
|
189
|
+
// ============================================================================
|
|
190
|
+
program
|
|
191
|
+
.command('add-image')
|
|
192
|
+
.description('Add an image to the canvas')
|
|
193
|
+
.requiredOption('-f, --file <path>', 'Path to image file (PNG, JPEG, GIF, SVG, WebP)')
|
|
194
|
+
.requiredOption('-x, --x <number>', 'X coordinate', parseFloat)
|
|
195
|
+
.requiredOption('-y, --y <number>', 'Y coordinate', parseFloat)
|
|
196
|
+
.option('-w, --width <number>', 'Width (default: original image width)', parseFloat)
|
|
197
|
+
.option('-h, --height <number>', 'Height (default: original image height)', parseFloat)
|
|
198
|
+
.option('-n, --note <text>', 'Note for this element (stored in customData)')
|
|
199
|
+
.action(async (options) => {
|
|
200
|
+
await addImage({
|
|
201
|
+
file: options.file,
|
|
202
|
+
x: options.x,
|
|
203
|
+
y: options.y,
|
|
204
|
+
width: options.width,
|
|
205
|
+
height: options.height,
|
|
206
|
+
note: options.note,
|
|
207
|
+
}, addImageDeps);
|
|
251
208
|
});
|
|
252
209
|
// ============================================================================
|
|
253
210
|
// Delete Elements
|
|
@@ -257,21 +214,7 @@ program
|
|
|
257
214
|
.description('Delete elements from the canvas')
|
|
258
215
|
.requiredOption('-i, --element-ids <ids>', 'Comma-separated element IDs to delete')
|
|
259
216
|
.action(async (options) => {
|
|
260
|
-
|
|
261
|
-
const client = await connectToCanvas();
|
|
262
|
-
const result = await client.send({
|
|
263
|
-
type: 'deleteElements',
|
|
264
|
-
id: generateId(),
|
|
265
|
-
params: { elementIds },
|
|
266
|
-
});
|
|
267
|
-
if (result.success) {
|
|
268
|
-
console.log(`Deleted ${result.deletedCount} element(s)`);
|
|
269
|
-
}
|
|
270
|
-
else {
|
|
271
|
-
console.error(`Failed: ${result.error}`);
|
|
272
|
-
process.exit(1);
|
|
273
|
-
}
|
|
274
|
-
client.close();
|
|
217
|
+
await deleteElements({ elementIds: options.elementIds }, deleteElementsDeps);
|
|
275
218
|
});
|
|
276
219
|
// ============================================================================
|
|
277
220
|
// Rotate Elements
|
|
@@ -282,21 +225,7 @@ program
|
|
|
282
225
|
.requiredOption('-i, --element-ids <ids>', 'Comma-separated element IDs to rotate')
|
|
283
226
|
.requiredOption('-a, --angle <degrees>', 'Rotation angle in degrees', parseFloat)
|
|
284
227
|
.action(async (options) => {
|
|
285
|
-
|
|
286
|
-
const client = await connectToCanvas();
|
|
287
|
-
const result = await client.send({
|
|
288
|
-
type: 'rotateElements',
|
|
289
|
-
id: generateId(),
|
|
290
|
-
params: { elementIds, angle: options.angle },
|
|
291
|
-
});
|
|
292
|
-
if (result.success) {
|
|
293
|
-
console.log(`Rotated ${result.rotatedCount} element(s)`);
|
|
294
|
-
}
|
|
295
|
-
else {
|
|
296
|
-
console.error(`Failed: ${result.error}`);
|
|
297
|
-
process.exit(1);
|
|
298
|
-
}
|
|
299
|
-
client.close();
|
|
228
|
+
await rotateElements({ elementIds: options.elementIds, angle: options.angle }, rotateElementsDeps);
|
|
300
229
|
});
|
|
301
230
|
// ============================================================================
|
|
302
231
|
// Group Elements
|
|
@@ -307,20 +236,7 @@ program
|
|
|
307
236
|
.requiredOption('-i, --element-ids <ids>', 'Comma-separated element IDs')
|
|
308
237
|
.action(async (options) => {
|
|
309
238
|
const elementIds = options.elementIds.split(',').map((s) => s.trim());
|
|
310
|
-
|
|
311
|
-
const result = await client.send({
|
|
312
|
-
type: 'groupElements',
|
|
313
|
-
id: generateId(),
|
|
314
|
-
params: { elementIds },
|
|
315
|
-
});
|
|
316
|
-
if (result.success) {
|
|
317
|
-
console.log(`Group created (id: ${result.groupId})`);
|
|
318
|
-
}
|
|
319
|
-
else {
|
|
320
|
-
console.error(`Failed: ${result.error}`);
|
|
321
|
-
process.exit(1);
|
|
322
|
-
}
|
|
323
|
-
client.close();
|
|
239
|
+
await groupElements({ elementIds }, groupElementsDeps);
|
|
324
240
|
});
|
|
325
241
|
// ============================================================================
|
|
326
242
|
// Ungroup Element
|
|
@@ -330,20 +246,7 @@ program
|
|
|
330
246
|
.description('Remove an element from its group')
|
|
331
247
|
.requiredOption('-i, --element-id <id>', 'Element ID to ungroup')
|
|
332
248
|
.action(async (options) => {
|
|
333
|
-
|
|
334
|
-
const result = await client.send({
|
|
335
|
-
type: 'ungroupElement',
|
|
336
|
-
id: generateId(),
|
|
337
|
-
params: { elementId: options.elementId },
|
|
338
|
-
});
|
|
339
|
-
if (result.success) {
|
|
340
|
-
console.log('Element ungrouped');
|
|
341
|
-
}
|
|
342
|
-
else {
|
|
343
|
-
console.error(`Failed: ${result.error}`);
|
|
344
|
-
process.exit(1);
|
|
345
|
-
}
|
|
346
|
-
client.close();
|
|
249
|
+
await ungroupElement({ elementId: options.elementId }, ungroupElementDeps);
|
|
347
250
|
});
|
|
348
251
|
// ============================================================================
|
|
349
252
|
// Move Elements
|
|
@@ -355,28 +258,18 @@ program
|
|
|
355
258
|
.requiredOption('--delta-x <number>', 'Horizontal offset (positive = right)', parseFloat)
|
|
356
259
|
.requiredOption('--delta-y <number>', 'Vertical offset (positive = down)', parseFloat)
|
|
357
260
|
.action(async (options) => {
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
params: { elementIds, deltaX: options.deltaX, deltaY: options.deltaY },
|
|
364
|
-
});
|
|
365
|
-
if (result.success) {
|
|
366
|
-
console.log(`Moved ${result.movedCount} element(s)`);
|
|
367
|
-
}
|
|
368
|
-
else {
|
|
369
|
-
console.error(`Failed: ${result.error}`);
|
|
370
|
-
process.exit(1);
|
|
371
|
-
}
|
|
372
|
-
client.close();
|
|
261
|
+
await moveElements({
|
|
262
|
+
elementIds: options.elementIds,
|
|
263
|
+
deltaX: options.deltaX,
|
|
264
|
+
deltaY: options.deltaY,
|
|
265
|
+
}, moveElementsDeps);
|
|
373
266
|
});
|
|
374
267
|
// ============================================================================
|
|
375
268
|
// Resize Elements
|
|
376
269
|
// ============================================================================
|
|
377
270
|
program
|
|
378
271
|
.command('resize-elements')
|
|
379
|
-
.description('Resize
|
|
272
|
+
.description('Resize elements (shapes and images) by expanding/contracting edges')
|
|
380
273
|
.requiredOption('-i, --element-ids <ids>', 'Comma-separated element IDs')
|
|
381
274
|
.option('--top <number>', 'Expand top edge (positive = upward, negative = contract)', parseFloat)
|
|
382
275
|
.option('--bottom <number>', 'Expand bottom edge (positive = downward, negative = contract)', parseFloat)
|
|
@@ -384,28 +277,13 @@ program
|
|
|
384
277
|
.option('--right <number>', 'Expand right edge (positive = rightward, negative = contract)', parseFloat)
|
|
385
278
|
.action(async (options) => {
|
|
386
279
|
const elementIds = options.elementIds.split(',').map((s) => s.trim());
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
}
|
|
395
|
-
const client = await connectToCanvas();
|
|
396
|
-
const result = await client.send({
|
|
397
|
-
type: 'resizeElements',
|
|
398
|
-
id: generateId(),
|
|
399
|
-
params: { elementIds, top, bottom, left, right },
|
|
400
|
-
});
|
|
401
|
-
if (result.success) {
|
|
402
|
-
console.log(`Resized ${result.resizedCount} element(s)`);
|
|
403
|
-
}
|
|
404
|
-
else {
|
|
405
|
-
console.error(`Failed: ${result.error}`);
|
|
406
|
-
process.exit(1);
|
|
407
|
-
}
|
|
408
|
-
client.close();
|
|
280
|
+
await resizeElements({
|
|
281
|
+
elementIds,
|
|
282
|
+
top: options.top,
|
|
283
|
+
bottom: options.bottom,
|
|
284
|
+
left: options.left,
|
|
285
|
+
right: options.right,
|
|
286
|
+
}, resizeElementsDeps);
|
|
409
287
|
});
|
|
410
288
|
// ============================================================================
|
|
411
289
|
// Read Scene
|
|
@@ -416,173 +294,7 @@ program
|
|
|
416
294
|
.option('--json', 'Output raw Excalidraw scene JSON')
|
|
417
295
|
.option('--with-style', 'Include style info (stroke, bg) in TOON output')
|
|
418
296
|
.action(async (options) => {
|
|
419
|
-
|
|
420
|
-
if (options.json) {
|
|
421
|
-
// Return raw Excalidraw scene data
|
|
422
|
-
const result = await client.send({
|
|
423
|
-
type: 'saveScene',
|
|
424
|
-
id: generateId(),
|
|
425
|
-
});
|
|
426
|
-
if (result.success && result.data) {
|
|
427
|
-
console.log(JSON.stringify(result.data, null, 2));
|
|
428
|
-
}
|
|
429
|
-
else {
|
|
430
|
-
console.error(`Failed: ${result.error}`);
|
|
431
|
-
process.exit(1);
|
|
432
|
-
}
|
|
433
|
-
client.close();
|
|
434
|
-
return;
|
|
435
|
-
}
|
|
436
|
-
const result = await client.send({
|
|
437
|
-
type: 'readScene',
|
|
438
|
-
id: generateId(),
|
|
439
|
-
});
|
|
440
|
-
if (result.success && result.elements) {
|
|
441
|
-
const withStyle = options.withStyle;
|
|
442
|
-
// Separate elements into shapes, lines, labels (bound text), texts (standalone text), and groups
|
|
443
|
-
const shapes = [];
|
|
444
|
-
const lines = [];
|
|
445
|
-
const labels = [];
|
|
446
|
-
const texts = [];
|
|
447
|
-
const groupsMap = new Map(); // groupId -> elementIds
|
|
448
|
-
for (const el of result.elements) {
|
|
449
|
-
const angle = el.angle ? Math.round(el.angle * 180 / Math.PI) : 0; // Convert radians to degrees
|
|
450
|
-
// Collect group memberships
|
|
451
|
-
if (el.groupIds?.length) {
|
|
452
|
-
for (const groupId of el.groupIds) {
|
|
453
|
-
if (!groupsMap.has(groupId)) {
|
|
454
|
-
groupsMap.set(groupId, []);
|
|
455
|
-
}
|
|
456
|
-
groupsMap.get(groupId).push(el.id);
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
if (el.type === 'text') {
|
|
460
|
-
if (el.containerId) {
|
|
461
|
-
// Bound text (label)
|
|
462
|
-
labels.push({
|
|
463
|
-
id: el.id,
|
|
464
|
-
containerId: el.containerId,
|
|
465
|
-
content: el.text ?? '',
|
|
466
|
-
x: Math.round(el.x),
|
|
467
|
-
y: Math.round(el.y),
|
|
468
|
-
w: el.width !== undefined ? Math.round(el.width) : null,
|
|
469
|
-
h: el.height !== undefined ? Math.round(el.height) : null,
|
|
470
|
-
});
|
|
471
|
-
}
|
|
472
|
-
else {
|
|
473
|
-
// Standalone text
|
|
474
|
-
const text = {
|
|
475
|
-
id: el.id,
|
|
476
|
-
content: el.text ?? '',
|
|
477
|
-
x: Math.round(el.x),
|
|
478
|
-
y: Math.round(el.y),
|
|
479
|
-
w: el.width !== undefined ? Math.round(el.width) : null,
|
|
480
|
-
h: el.height !== undefined ? Math.round(el.height) : null,
|
|
481
|
-
angle,
|
|
482
|
-
note: el.customData?.note ?? null,
|
|
483
|
-
};
|
|
484
|
-
if (withStyle) {
|
|
485
|
-
text.stroke = el.strokeColor ?? null;
|
|
486
|
-
}
|
|
487
|
-
texts.push(text);
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
else if (el.type === 'line' || el.type === 'arrow') {
|
|
491
|
-
const pts = el.points ?? [];
|
|
492
|
-
// Check if it's a closed polygon (first and last point within 8px threshold)
|
|
493
|
-
const isPolygon = el.type === 'line' && pts.length >= 3 && (() => {
|
|
494
|
-
const first = pts[0];
|
|
495
|
-
const last = pts[pts.length - 1];
|
|
496
|
-
const distance = Math.sqrt((last[0] - first[0]) ** 2 + (last[1] - first[1]) ** 2);
|
|
497
|
-
return distance <= 8;
|
|
498
|
-
})();
|
|
499
|
-
if (isPolygon) {
|
|
500
|
-
// Polygon - treat as shape
|
|
501
|
-
// Calculate bounding box from points
|
|
502
|
-
const xs = pts.map(p => p[0]);
|
|
503
|
-
const ys = pts.map(p => p[1]);
|
|
504
|
-
const minX = Math.min(...xs);
|
|
505
|
-
const maxX = Math.max(...xs);
|
|
506
|
-
const minY = Math.min(...ys);
|
|
507
|
-
const maxY = Math.max(...ys);
|
|
508
|
-
const shape = {
|
|
509
|
-
id: el.id,
|
|
510
|
-
type: 'polygon',
|
|
511
|
-
x: Math.round(el.x + minX),
|
|
512
|
-
y: Math.round(el.y + minY),
|
|
513
|
-
w: Math.round(maxX - minX),
|
|
514
|
-
h: Math.round(maxY - minY),
|
|
515
|
-
angle,
|
|
516
|
-
labelId: null,
|
|
517
|
-
note: el.customData?.note ?? null,
|
|
518
|
-
};
|
|
519
|
-
if (withStyle) {
|
|
520
|
-
shape.stroke = el.strokeColor ?? null;
|
|
521
|
-
shape.bg = el.backgroundColor ?? null;
|
|
522
|
-
}
|
|
523
|
-
shapes.push(shape);
|
|
524
|
-
}
|
|
525
|
-
else {
|
|
526
|
-
// Line/Arrow element
|
|
527
|
-
const lastPt = pts.length > 0 ? pts[pts.length - 1] : [0, 0];
|
|
528
|
-
const line = {
|
|
529
|
-
id: el.id,
|
|
530
|
-
type: el.type,
|
|
531
|
-
x: Math.round(el.x),
|
|
532
|
-
y: Math.round(el.y),
|
|
533
|
-
endX: Math.round(el.x + lastPt[0]),
|
|
534
|
-
endY: Math.round(el.y + lastPt[1]),
|
|
535
|
-
// Show intermediate points (via) in the same format as --via input
|
|
536
|
-
via: pts.length > 2
|
|
537
|
-
? pts.slice(1, -1).map(pt => `${Math.round(el.x + pt[0])},${Math.round(el.y + pt[1])}`).join(';')
|
|
538
|
-
: null,
|
|
539
|
-
angle,
|
|
540
|
-
note: el.customData?.note ?? null,
|
|
541
|
-
};
|
|
542
|
-
if (withStyle) {
|
|
543
|
-
line.stroke = el.strokeColor ?? null;
|
|
544
|
-
}
|
|
545
|
-
lines.push(line);
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
else {
|
|
549
|
-
// Shape element (rectangle, ellipse, diamond, etc.)
|
|
550
|
-
const boundText = el.boundElements?.find(b => b.type === 'text');
|
|
551
|
-
const shape = {
|
|
552
|
-
id: el.id,
|
|
553
|
-
type: el.type,
|
|
554
|
-
x: Math.round(el.x),
|
|
555
|
-
y: Math.round(el.y),
|
|
556
|
-
w: el.width !== undefined ? Math.round(el.width) : null,
|
|
557
|
-
h: el.height !== undefined ? Math.round(el.height) : null,
|
|
558
|
-
angle,
|
|
559
|
-
labelId: boundText?.id ?? null,
|
|
560
|
-
note: el.customData?.note ?? null,
|
|
561
|
-
};
|
|
562
|
-
if (withStyle) {
|
|
563
|
-
shape.stroke = el.strokeColor ?? null;
|
|
564
|
-
shape.bg = el.backgroundColor ?? null;
|
|
565
|
-
}
|
|
566
|
-
shapes.push(shape);
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
// Build groups array
|
|
570
|
-
const groups = Array.from(groupsMap.entries()).map(([id, elementIds]) => ({
|
|
571
|
-
id,
|
|
572
|
-
elementIds: elementIds.join(','),
|
|
573
|
-
}));
|
|
574
|
-
console.log(toToon({ shapes, lines, labels, texts, groups }));
|
|
575
|
-
// Output selected elements
|
|
576
|
-
const selectedIds = result.selectedElementIds ?? [];
|
|
577
|
-
if (selectedIds.length > 0) {
|
|
578
|
-
console.log(`\nSelected: ${selectedIds.join(', ')}`);
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
else {
|
|
582
|
-
console.error(`Failed: ${result.error}`);
|
|
583
|
-
process.exit(1);
|
|
584
|
-
}
|
|
585
|
-
client.close();
|
|
297
|
+
await read({ json: options.json, withStyle: options.withStyle }, readDeps);
|
|
586
298
|
});
|
|
587
299
|
// ============================================================================
|
|
588
300
|
// Export Image
|
|
@@ -596,36 +308,13 @@ program
|
|
|
596
308
|
.option('--embed-scene', 'Embed scene data in PNG')
|
|
597
309
|
.option('--scale <scale>', 'Export scale (1, 2, or 3)', '1')
|
|
598
310
|
.action(async (options) => {
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
type: 'exportImage',
|
|
607
|
-
id: generateId(),
|
|
608
|
-
params: {
|
|
609
|
-
background: options.background,
|
|
610
|
-
dark: options.dark ?? false,
|
|
611
|
-
embedScene: options.embedScene ?? false,
|
|
612
|
-
scale: scale,
|
|
613
|
-
},
|
|
614
|
-
});
|
|
615
|
-
if (result.success && result.dataUrl) {
|
|
616
|
-
// Extract base64 data from data URL
|
|
617
|
-
const base64Data = result.dataUrl.replace(/^data:image\/png;base64,/, '');
|
|
618
|
-
const buffer = Buffer.from(base64Data, 'base64');
|
|
619
|
-
// Generate output path if not specified
|
|
620
|
-
const outputPath = options.output || `canvas-${Date.now()}.png`;
|
|
621
|
-
writeFileSync(outputPath, buffer);
|
|
622
|
-
console.log(`Exported to ${outputPath}`);
|
|
623
|
-
}
|
|
624
|
-
else {
|
|
625
|
-
console.error(`Failed: ${result.error}`);
|
|
626
|
-
process.exit(1);
|
|
627
|
-
}
|
|
628
|
-
client.close();
|
|
311
|
+
await exportImage({
|
|
312
|
+
output: options.output,
|
|
313
|
+
background: options.background,
|
|
314
|
+
dark: options.dark,
|
|
315
|
+
embedScene: options.embedScene,
|
|
316
|
+
scale: parseInt(options.scale, 10),
|
|
317
|
+
}, exportDeps);
|
|
629
318
|
});
|
|
630
319
|
// ============================================================================
|
|
631
320
|
// Save Scene
|
|
@@ -635,21 +324,7 @@ program
|
|
|
635
324
|
.description('Save canvas to an .excalidraw file')
|
|
636
325
|
.argument('<filepath>', 'Output file path (.excalidraw)')
|
|
637
326
|
.action(async (filepath) => {
|
|
638
|
-
|
|
639
|
-
const result = await client.send({
|
|
640
|
-
type: 'saveScene',
|
|
641
|
-
id: generateId(),
|
|
642
|
-
});
|
|
643
|
-
if (result.success && result.data) {
|
|
644
|
-
const outputPath = filepath.endsWith('.excalidraw') ? filepath : `${filepath}.excalidraw`;
|
|
645
|
-
writeFileSync(outputPath, JSON.stringify(result.data, null, 2));
|
|
646
|
-
console.log(`Saved to ${outputPath}`);
|
|
647
|
-
}
|
|
648
|
-
else {
|
|
649
|
-
console.error(`Failed: ${result.error}`);
|
|
650
|
-
process.exit(1);
|
|
651
|
-
}
|
|
652
|
-
client.close();
|
|
327
|
+
await save(filepath, saveDeps);
|
|
653
328
|
});
|
|
654
329
|
// ============================================================================
|
|
655
330
|
// Clear Canvas
|
|
@@ -658,19 +333,7 @@ program
|
|
|
658
333
|
.command('clear')
|
|
659
334
|
.description('Clear all elements from the canvas')
|
|
660
335
|
.action(async () => {
|
|
661
|
-
|
|
662
|
-
const result = await client.send({
|
|
663
|
-
type: 'clearCanvas',
|
|
664
|
-
id: generateId(),
|
|
665
|
-
});
|
|
666
|
-
if (result.success) {
|
|
667
|
-
console.log('Canvas cleared');
|
|
668
|
-
}
|
|
669
|
-
else {
|
|
670
|
-
console.error(`Failed: ${result.error}`);
|
|
671
|
-
process.exit(1);
|
|
672
|
-
}
|
|
673
|
-
client.close();
|
|
336
|
+
await clear(clearDeps);
|
|
674
337
|
});
|
|
675
338
|
// ============================================================================
|
|
676
339
|
// List Canvases
|
|
@@ -679,24 +342,7 @@ program
|
|
|
679
342
|
.command('list')
|
|
680
343
|
.description('List all canvases')
|
|
681
344
|
.action(async () => {
|
|
682
|
-
|
|
683
|
-
const result = await client.send({
|
|
684
|
-
type: 'listCanvases',
|
|
685
|
-
id: generateId(),
|
|
686
|
-
});
|
|
687
|
-
if (result.success && result.canvases) {
|
|
688
|
-
console.log('Canvases:');
|
|
689
|
-
for (const canvas of result.canvases) {
|
|
690
|
-
const marker = canvas.id === result.activeCanvasId ? ' *' : ' ';
|
|
691
|
-
const date = new Date(canvas.updatedAt).toLocaleString();
|
|
692
|
-
console.log(`${marker} ${canvas.name} (updated: ${date})`);
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
else {
|
|
696
|
-
console.error(`Failed: ${result.error}`);
|
|
697
|
-
process.exit(1);
|
|
698
|
-
}
|
|
699
|
-
client.close();
|
|
345
|
+
await list(listDeps);
|
|
700
346
|
});
|
|
701
347
|
// ============================================================================
|
|
702
348
|
// Create Canvas
|
|
@@ -707,21 +353,7 @@ program
|
|
|
707
353
|
.requiredOption('-n, --name <name>', 'Name for the new canvas')
|
|
708
354
|
.option('--use', 'Switch to the new canvas after creation')
|
|
709
355
|
.action(async (options) => {
|
|
710
|
-
|
|
711
|
-
const result = await client.send({
|
|
712
|
-
type: 'createCanvas',
|
|
713
|
-
id: generateId(),
|
|
714
|
-
params: { name: options.name, switchTo: options.use ?? false },
|
|
715
|
-
});
|
|
716
|
-
if (result.success && result.canvas) {
|
|
717
|
-
const switched = options.use ? ' and switched to it' : '';
|
|
718
|
-
console.log(`Canvas "${result.canvas.name}" created${switched}`);
|
|
719
|
-
}
|
|
720
|
-
else {
|
|
721
|
-
console.error(`Failed: ${result.error}`);
|
|
722
|
-
process.exit(1);
|
|
723
|
-
}
|
|
724
|
-
client.close();
|
|
356
|
+
await newCanvas({ name: options.name, use: options.use }, newCanvasDeps);
|
|
725
357
|
});
|
|
726
358
|
// ============================================================================
|
|
727
359
|
// Switch Canvas
|
|
@@ -731,20 +363,7 @@ program
|
|
|
731
363
|
.description('Switch to a canvas by name')
|
|
732
364
|
.argument('<name>', 'Canvas name to switch to')
|
|
733
365
|
.action(async (name) => {
|
|
734
|
-
|
|
735
|
-
const result = await client.send({
|
|
736
|
-
type: 'switchCanvas',
|
|
737
|
-
id: generateId(),
|
|
738
|
-
params: { name },
|
|
739
|
-
});
|
|
740
|
-
if (result.success && result.canvas) {
|
|
741
|
-
console.log(`Switched to canvas "${result.canvas.name}"`);
|
|
742
|
-
}
|
|
743
|
-
else {
|
|
744
|
-
console.error(`Failed: ${result.error}`);
|
|
745
|
-
process.exit(1);
|
|
746
|
-
}
|
|
747
|
-
client.close();
|
|
366
|
+
await useCanvas({ name }, useCanvasDeps);
|
|
748
367
|
});
|
|
749
368
|
// ============================================================================
|
|
750
369
|
// Rename Canvas
|
|
@@ -754,19 +373,6 @@ program
|
|
|
754
373
|
.description('Rename the current canvas')
|
|
755
374
|
.argument('<name>', 'New name for the canvas')
|
|
756
375
|
.action(async (name) => {
|
|
757
|
-
|
|
758
|
-
const result = await client.send({
|
|
759
|
-
type: 'renameCanvas',
|
|
760
|
-
id: generateId(),
|
|
761
|
-
params: { newName: name },
|
|
762
|
-
});
|
|
763
|
-
if (result.success && result.canvas) {
|
|
764
|
-
console.log(`Canvas renamed to "${result.canvas.name}"`);
|
|
765
|
-
}
|
|
766
|
-
else {
|
|
767
|
-
console.error(`Failed: ${result.error}`);
|
|
768
|
-
process.exit(1);
|
|
769
|
-
}
|
|
770
|
-
client.close();
|
|
376
|
+
await renameCanvas({ newName: name }, renameCanvasDeps);
|
|
771
377
|
});
|
|
772
378
|
program.parse();
|