agent-whiteboard 1.0.4 → 1.2.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/CHANGELOG.md +76 -0
- package/README.md +61 -5
- package/dist/client/assets/abnfDiagram-VCTEODGH-Dj8sd_5g.js +1 -0
- package/dist/client/assets/{arc-4691b008.js → arc-Aq92EeUK.js} +1 -1
- package/dist/client/assets/architectureDiagram-5GKGNRK7-B1QyVL0F.js +36 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-CmU2SSFe.js +129 -0
- package/dist/client/assets/{bootstrap.min-21652813.js → bootstrap.min-UtnB-TxT.js} +1 -2
- package/dist/client/assets/c4Diagram-7LVT6UL2-DWmhp77c.js +38 -0
- package/dist/client/assets/channel-C9ni1Via.js +1 -0
- package/dist/client/assets/{chunk-QZHKN3VN-0f554985.js → chunk-2Q5K7J3B-CQLo8Sbv.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-23d48b24.js → chunk-5VM5RSS4-fJTWmTTt.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-1104c326.js → chunk-F27PBJKO-DqzEf5gi.js} +1 -1
- package/dist/client/assets/chunk-IMKFNOWR-CMamLTz3.js +231 -0
- package/dist/client/assets/{chunk-4BX2VUAB-3c93511d.js → chunk-JWPE2WC7-tyYPyD43.js} +1 -1
- package/dist/client/assets/chunk-POPQ4Y6H-XdY4rO_V.js +1 -0
- package/dist/client/assets/chunk-SVP7TREG-COvqzqaO.js +88 -0
- package/dist/client/assets/chunk-TICWLB2K-BsJSFuPC.js +206 -0
- package/dist/client/assets/{chunk-55IACEB6-0243aefd.js → chunk-XXDRQBXY-HfVrYBJb.js} +1 -1
- package/dist/client/assets/classDiagram-ZZMXUADV-DktNEiGC.js +1 -0
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-DktNEiGC.js +1 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-UXGdwSjS.js +1 -0
- package/dist/client/assets/cynefin-OW5HDTMX-PWlPYnpn.js +178 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CYE5H1wR.js +62 -0
- package/dist/client/assets/cytoscape.esm-C5JX3QLV.js +331 -0
- package/dist/client/assets/dagre-GXQ25YYZ-DaknBOKq.js +4 -0
- package/dist/client/assets/diagram-S7CK7UJ4-Dz7rZHxF.js +30 -0
- package/dist/client/assets/diagram-UQ7AKVKN-DzCi6tiS.js +41 -0
- package/dist/client/assets/{diagram-KO2AKTUF-81f42eeb.js → diagram-VSXAHHWV-TlUzhXgv.js} +3 -3
- package/dist/client/assets/diagram-VX7I27RA-Ds7jdzK7.js +24 -0
- package/dist/client/assets/diagram-Z3DM3KII-C--JD7cf.js +24 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-Dw5OM-dL.js +1 -0
- package/dist/client/assets/embed-DcNeILcO.js +211 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-DXalBHjA.js +99 -0
- package/dist/client/assets/flowDiagram-HODETNUW-DcI3UqyE.js +168 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-DyrkIo6c.js +292 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-fJKfGRcg.js +106 -0
- package/dist/client/assets/index-CIhkXT_z.js +19 -0
- package/dist/client/assets/index-DEiH2AE7.css +1 -0
- package/dist/client/assets/infoDiagram-27XIBGKW-Cijiqswb.js +2 -0
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-50b43d03.js → ishikawaDiagram-5VMMS53U-C1WqWU2l.js} +2 -2
- package/dist/client/assets/{journeyDiagram-JHISSGLW-dce41bdf.js → journeyDiagram-3NMN7TZE-7j05mbLR.js} +4 -4
- package/dist/client/assets/{kanban-definition-UN3LZRKU-92401a86.js → kanban-definition-UXKFOSKX-D5mGDfs_.js} +1 -1
- package/dist/client/assets/{katex-4c9ea27f.js → katex-BTI-AXqd.js} +3 -3
- package/dist/client/assets/{katex-0cba7652.js → katex-C5jXJg4s.js} +3 -3
- package/dist/client/assets/layout-KEin06-H.js +1 -0
- package/dist/client/assets/linear-D1EL1Azg.js +1 -0
- package/dist/client/assets/mermaid.core-CLvSDmrA.js +310 -0
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-66fe4544.js → mindmap-definition-YA3MSWOX-BsCqKd_d.js} +12 -12
- package/dist/client/assets/{ordinal-db88ae6f.js → ordinal-BeghXfj9.js} +1 -1
- package/dist/client/assets/pegDiagram-XKGWAZYB-Du5lDU3W.js +1 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-hjv5Ao6B.js +39 -0
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-f64a7ed7.js → quadrantDiagram-AXDQQJYC-DNon8LWK.js} +4 -4
- package/dist/client/assets/railroadDiagram-O6MQD6OU-yNZz2zxo.js +1 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-CZiiEUHW.js +84 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-D-u8ZQUV.js +40 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-BxjTf3q9.js +162 -0
- package/dist/client/assets/sizeCapture-INFHLROL-Dt4Wg8C5.js +1 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-B8BM6dln.js +1 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-MJauX84T.js +1 -0
- package/dist/client/assets/step-BEQzeS8V.js +1 -0
- package/dist/client/assets/swimlanes-42K2YHIH-eGWrsWAA.js +1 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-BYFu8tyL.js +8 -0
- package/dist/client/assets/{time-043b3464.js → time-BaoZouO5.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-b0c81243.js → timeline-definition-24CTP7MA-CAM-3Qj9.js} +10 -10
- package/dist/client/assets/vennDiagram-4TSXK5OY-CuFEwwD0.js +34 -0
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-8d4d7626.js → wardleyDiagram-VM6X3IG4-DI5yCVh0.js} +3 -3
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-BI0Bn-OQ.js +7 -0
- package/dist/client/index.html +2 -3
- package/dist/server/app.js +28 -396
- package/dist/server/channel.js +5 -3
- package/dist/server/export-html.js +30 -60
- package/dist/server/export-zip.js +83 -0
- package/dist/server/import-zip.js +196 -0
- package/dist/server/index.js +2 -1
- package/dist/server/mcp.js +28 -13
- package/dist/server/port.js +18 -0
- package/dist/server/quiz-submission.js +116 -0
- package/dist/server/quiz.js +110 -0
- package/dist/server/render-core.js +8 -7
- package/dist/server/routes/export.js +95 -0
- package/dist/server/routes/import.js +24 -0
- package/dist/server/routes/quiz.js +12 -0
- package/dist/server/routes/render.js +184 -0
- package/dist/server/routes/slideshow.js +52 -0
- package/dist/server/routes/snapshots.js +119 -0
- package/dist/server/snapshot-reader.js +58 -20
- package/dist/server/snapshot-writer.js +18 -16
- package/dist/server/validate.js +14 -0
- package/dist/server/viewport-cache.js +97 -25
- package/package.json +13 -7
- package/dist/client/assets/architecture-7EHR7CIX-1221aa61.js +0 -1
- package/dist/client/assets/architectureDiagram-3BPJPVTR-1eef4d3c.js +0 -36
- package/dist/client/assets/blockDiagram-GPEHLZMM-313fb06c.js +0 -132
- package/dist/client/assets/c4Diagram-AAUBKEIU-92b023ad.js +0 -10
- package/dist/client/assets/channel-5ee4a8a7.js +0 -1
- package/dist/client/assets/chunk-2J33WTMH-fb021fdc.js +0 -1
- package/dist/client/assets/chunk-727SXJPM-8e0e0228.js +0 -206
- package/dist/client/assets/chunk-AQP2D5EJ-2ccc13c2.js +0 -231
- package/dist/client/assets/classDiagram-4FO5ZUOK-42ffecb6.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-42ffecb6.js +0 -1
- package/dist/client/assets/cose-bilkent-S5V4N54A-45ec2e52.js +0 -1
- package/dist/client/assets/cytoscape.esm-1491e259.js +0 -331
- package/dist/client/assets/dagre-BM42HDAG-ed748885.js +0 -4
- package/dist/client/assets/diagram-2AECGRRQ-ccc0ddec.js +0 -43
- package/dist/client/assets/diagram-5GNKFQAL-342efdea.js +0 -10
- package/dist/client/assets/diagram-LMA3HP47-39e66739.js +0 -24
- package/dist/client/assets/diagram-OG6HWLK6-b3e61903.js +0 -24
- package/dist/client/assets/embed-2b4adf34.js +0 -201
- package/dist/client/assets/erDiagram-TEJ5UH35-281f5cc7.js +0 -85
- package/dist/client/assets/eventmodeling-FCH6USID-6508120e.js +0 -1
- package/dist/client/assets/flowDiagram-I6XJVG4X-c3a4269e.js +0 -162
- package/dist/client/assets/ganttDiagram-6RSMTGT7-013b07ec.js +0 -292
- package/dist/client/assets/gitGraph-WXDBUCRP-02827359.js +0 -1
- package/dist/client/assets/gitGraphDiagram-PVQCEYII-de184acb.js +0 -106
- package/dist/client/assets/graph-f3dfaf53.js +0 -1
- package/dist/client/assets/index-d674a6a4.css +0 -1
- package/dist/client/assets/index-ffc5af4b.js +0 -5
- package/dist/client/assets/info-J43DQDTF-81e32294.js +0 -1
- package/dist/client/assets/infoDiagram-5YYISTIA-196101ee.js +0 -2
- package/dist/client/assets/layout-3a4eff80.js +0 -1
- package/dist/client/assets/linear-fed00341.js +0 -1
- package/dist/client/assets/mermaid-parser.core-52f9cd92.js +0 -173
- package/dist/client/assets/mermaid.core-7dfc221a.js +0 -306
- package/dist/client/assets/packet-YPE3B663-278a272a.js +0 -1
- package/dist/client/assets/pie-LRSECV5Y-2e55d9ae.js +0 -1
- package/dist/client/assets/pieDiagram-4H26LBE5-65b1bcbd.js +0 -30
- package/dist/client/assets/radar-GUYGQ44K-608e459f.js +0 -1
- package/dist/client/assets/requirementDiagram-4Y6WPE33-90ebf889.js +0 -84
- package/dist/client/assets/sankeyDiagram-5OEKKPKP-2d1a83b3.js +0 -40
- package/dist/client/assets/sequenceDiagram-3UESZ5HK-aece3633.js +0 -162
- package/dist/client/assets/stateDiagram-AJRCARHV-9bd5b5f4.js +0 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-7c16c251.js +0 -1
- package/dist/client/assets/step-171ad54a.js +0 -1
- package/dist/client/assets/treeView-BLDUP644-e54b9ddb.js +0 -1
- package/dist/client/assets/treemap-LRROVOQU-6a81775b.js +0 -1
- package/dist/client/assets/vennDiagram-CIIHVFJN-8eaf0464.js +0 -34
- package/dist/client/assets/wardley-L42UT6IY-7abd921f.js +0 -1
- package/dist/client/assets/xychartDiagram-2RQKCTM6-450f333c.js +0 -7
- /package/dist/client/assets/{KaTeX_AMS-Regular-0cdd387c.woff2 → KaTeX_AMS-Regular-BQhdFMY1.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_AMS-Regular-30da91e8.woff → KaTeX_AMS-Regular-DMm9YOAa.woff} +0 -0
- /package/dist/client/assets/{KaTeX_AMS-Regular-68534840.ttf → KaTeX_AMS-Regular-DRggAlZN.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Caligraphic-Bold-07d8e303.ttf → KaTeX_Caligraphic-Bold-ATXxdsX0.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Caligraphic-Bold-1ae6bd74.woff → KaTeX_Caligraphic-Bold-BEiXGLvX.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Caligraphic-Bold-de7701e4.woff2 → KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Caligraphic-Regular-3398dd02.woff → KaTeX_Caligraphic-Regular-CTRA-rTL.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Caligraphic-Regular-5d53e70a.woff2 → KaTeX_Caligraphic-Regular-Di6jR-x-.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Caligraphic-Regular-ed0b7437.ttf → KaTeX_Caligraphic-Regular-wX97UBjC.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Fraktur-Bold-9163df9c.ttf → KaTeX_Fraktur-Bold-BdnERNNW.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Fraktur-Bold-9be7ceb8.woff → KaTeX_Fraktur-Bold-BsDP51OF.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Fraktur-Bold-74444efd.woff2 → KaTeX_Fraktur-Bold-CL6g_b3V.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Fraktur-Regular-1e6f9579.ttf → KaTeX_Fraktur-Regular-CB_wures.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Fraktur-Regular-51814d27.woff2 → KaTeX_Fraktur-Regular-CTYiF6lA.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Fraktur-Regular-5e28753b.woff → KaTeX_Fraktur-Regular-Dxdc4cR9.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Main-Bold-0f60d1b8.woff2 → KaTeX_Main-Bold-Cx986IdX.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Main-Bold-c76c5d69.woff → KaTeX_Main-Bold-Jm3AIy58.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Main-Bold-138ac28d.ttf → KaTeX_Main-Bold-waoOVXN0.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Main-BoldItalic-99cd42a3.woff2 → KaTeX_Main-BoldItalic-DxDJ3AOS.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Main-BoldItalic-70ee1f64.ttf → KaTeX_Main-BoldItalic-DzxPMmG6.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Main-BoldItalic-a6f7ec0d.woff → KaTeX_Main-BoldItalic-SpSLRI95.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Main-Italic-0d85ae7c.ttf → KaTeX_Main-Italic-3WenGoN9.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Main-Italic-f1d6ef86.woff → KaTeX_Main-Italic-BMLOBm91.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Main-Italic-97479ca6.woff2 → KaTeX_Main-Italic-NWA7e6Wa.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Main-Regular-c2342cd8.woff2 → KaTeX_Main-Regular-B22Nviop.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Main-Regular-c6368d87.woff → KaTeX_Main-Regular-Dr94JaBh.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Main-Regular-d0332f52.ttf → KaTeX_Main-Regular-ypZvNtVU.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Math-BoldItalic-f9377ab0.ttf → KaTeX_Math-BoldItalic-B3XSjfu4.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Math-BoldItalic-dc47344d.woff2 → KaTeX_Math-BoldItalic-CZnvNsCZ.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Math-BoldItalic-850c0af5.woff → KaTeX_Math-BoldItalic-iY-2wyZ7.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Math-Italic-8a8d2445.woff → KaTeX_Math-Italic-DA0__PXp.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Math-Italic-08ce98e5.ttf → KaTeX_Math-Italic-flOr_0UB.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Math-Italic-7af58c5e.woff2 → KaTeX_Math-Italic-t53AETM-.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_SansSerif-Bold-1ece03f7.ttf → KaTeX_SansSerif-Bold-CFMepnvq.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_SansSerif-Bold-e99ae511.woff2 → KaTeX_SansSerif-Bold-D1sUS0GD.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_SansSerif-Bold-ece03cfd.woff → KaTeX_SansSerif-Bold-DbIhKOiC.woff} +0 -0
- /package/dist/client/assets/{KaTeX_SansSerif-Italic-00b26ac8.woff2 → KaTeX_SansSerif-Italic-C3H0VqGB.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_SansSerif-Italic-91ee6750.woff → KaTeX_SansSerif-Italic-DN2j7dab.woff} +0 -0
- /package/dist/client/assets/{KaTeX_SansSerif-Italic-3931dd81.ttf → KaTeX_SansSerif-Italic-YYjJ1zSn.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_SansSerif-Regular-f36ea897.ttf → KaTeX_SansSerif-Regular-BNo7hRIc.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_SansSerif-Regular-11e4dc8a.woff → KaTeX_SansSerif-Regular-CS6fqUqJ.woff} +0 -0
- /package/dist/client/assets/{KaTeX_SansSerif-Regular-68e8c73e.woff2 → KaTeX_SansSerif-Regular-DDBCnlJ7.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Script-Regular-1c67f068.ttf → KaTeX_Script-Regular-C5JkGWo-.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Script-Regular-036d4e95.woff2 → KaTeX_Script-Regular-D3wIWfF6.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Script-Regular-d96cdf2b.woff → KaTeX_Script-Regular-D5yQViql.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Size1-Regular-c943cc98.woff → KaTeX_Size1-Regular-C195tn64.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Size1-Regular-95b6d2f1.ttf → KaTeX_Size1-Regular-Dbsnue_I.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Size1-Regular-6b47c401.woff2 → KaTeX_Size1-Regular-mCD8mA8B.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Size2-Regular-a6b2099f.ttf → KaTeX_Size2-Regular-B7gKUWhC.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Size2-Regular-d04c5421.woff2 → KaTeX_Size2-Regular-Dy4dx90m.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Size2-Regular-2014c523.woff → KaTeX_Size2-Regular-oD1tc_U0.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Size3-Regular-6ab6b62e.woff → KaTeX_Size3-Regular-CTq5MqoE.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Size3-Regular-500e04d5.ttf → KaTeX_Size3-Regular-DgpXs0kz.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Size4-Regular-99f9c675.woff → KaTeX_Size4-Regular-BF-4gkZK.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Size4-Regular-c647367d.ttf → KaTeX_Size4-Regular-DWFBv043.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Size4-Regular-a4af7d41.woff2 → KaTeX_Size4-Regular-Dl5lxZxV.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Typewriter-Regular-e14fed02.woff → KaTeX_Typewriter-Regular-C0xS9mPB.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Typewriter-Regular-71d517d6.woff2 → KaTeX_Typewriter-Regular-CO6r4hn1.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Typewriter-Regular-f01f3e87.ttf → KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf} +0 -0
- /package/dist/client/assets/{colors-98f238a0.js → colors-Cc3OSVma.js} +0 -0
- /package/dist/client/assets/{defaultLocale-a8476f12.js → defaultLocale-CzDG__Ur.js} +0 -0
- /package/dist/client/assets/{index-a1656aec.js → index-Bi7T_FA4.js} +0 -0
- /package/dist/client/assets/{init-a5b10ee5.js → init-Dmth1JHB.js} +0 -0
- /package/dist/client/assets/{range-6bc2a9a0.js → range-OtVwhkKS.js} +0 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import{s as pi,g as mi,o as $t,n as yi,a as bi,b as wi,_ as a,l as Ut,D as Ai,d as Ci,p as Si,y as Dt,i as Ri,A as Gt,B as _i,E as ki,am as Ti}from"./mermaid.core-CLvSDmrA.js";import{i as Di}from"./init-Dmth1JHB.js";import{o as Pi}from"./ordinal-BeghXfj9.js";import{r as vi}from"./range-OtVwhkKS.js";import{l as Xt}from"./linear-D1EL1Azg.js";import{l as Nt}from"./step-BEQzeS8V.js";import"./index-CIhkXT_z.js";import"./defaultLocale-CzDG__Ur.js";function St(){var e=Pi().unknown(void 0),t=e.domain,i=e.range,s=0,n=1,o,h,p=!1,u=0,f=0,R=.5;delete e.unknown;function C(){var y=t().length,E=n<s,v=E?n:s,L=E?s:n;o=(L-v)/Math.max(1,y-u+f*2),p&&(o=Math.floor(o)),v+=(L-v-o*(y-u))*R,h=o*(1-u),p&&(v=Math.round(v),h=Math.round(h));var M=vi(y).map(function(b){return v+o*b});return i(E?M.reverse():M)}return e.domain=function(y){return arguments.length?(t(y),C()):t()},e.range=function(y){return arguments.length?([s,n]=y,s=+s,n=+n,C()):[s,n]},e.rangeRound=function(y){return[s,n]=y,s=+s,n=+n,p=!0,C()},e.bandwidth=function(){return h},e.step=function(){return o},e.round=function(y){return arguments.length?(p=!!y,C()):p},e.padding=function(y){return arguments.length?(u=Math.min(1,f=+y),C()):u},e.paddingInner=function(y){return arguments.length?(u=Math.min(1,y),C()):u},e.paddingOuter=function(y){return arguments.length?(f=+y,C()):f},e.align=function(y){return arguments.length?(R=Math.max(0,Math.min(1,y)),C()):R},e.copy=function(){return St(t(),[s,n]).round(p).paddingInner(u).paddingOuter(f).align(R)},Di.apply(C(),arguments)}var Rt=function(){var e=a(function(W,l,g,d){for(g=g||{},d=W.length;d--;g[W[d]]=l);return g},"o"),t=[1,10,12,14,16,18,19,21,23],i=[2,6],s=[1,3],n=[1,5],o=[1,6],h=[1,7],p=[1,5,10,12,14,16,18,19,21,23,36,37,38],u=[1,25],f=[1,26],R=[1,28],C=[1,29],y=[1,30],E=[1,31],v=[1,32],L=[1,33],M=[1,34],b=[1,35],D=[1,36],c=[1,37],z=[1,43],F=[1,42],X=[1,47],N=[1,50],k=[1,10,12,14,16,18,19,21,23,36,37,38],H=[1,10,12,14,16,18,19,21,23,24,26,28,29,36,37,38],A=[1,10,12,14,16,18,19,21,23,24,26,28,29,36,37,38,42,43,44,45,46,47,48,49,50,51],S=[1,65],O=[26,28],T={trace:a(function(){},"trace"),yy:{},symbols_:{error:2,start:3,eol:4,XYCHART:5,chartConfig:6,document:7,CHART_ORIENTATION:8,statement:9,title:10,text:11,X_AXIS:12,parseXAxis:13,Y_AXIS:14,parseYAxis:15,LINE:16,plotData:17,BAR:18,acc_title:19,acc_title_value:20,acc_descr:21,acc_descr_value:22,acc_descr_multiline_value:23,SQUARE_BRACES_START:24,dataPoints:25,SQUARE_BRACES_END:26,dataPoint:27,COMMA:28,NUMBER_WITH_DECIMAL:29,STR:30,xAxisData:31,bandData:32,ARROW_DELIMITER:33,commaSeparatedTexts:34,yAxisData:35,NEWLINE:36,SEMI:37,EOF:38,alphaNum:39,MD_STR:40,alphaNumToken:41,AMP:42,NUM:43,ALPHA:44,PLUS:45,EQUALS:46,MULT:47,DOT:48,BRKT:49,MINUS:50,UNDERSCORE:51,$accept:0,$end:1},terminals_:{2:"error",5:"XYCHART",8:"CHART_ORIENTATION",10:"title",12:"X_AXIS",14:"Y_AXIS",16:"LINE",18:"BAR",19:"acc_title",20:"acc_title_value",21:"acc_descr",22:"acc_descr_value",23:"acc_descr_multiline_value",24:"SQUARE_BRACES_START",26:"SQUARE_BRACES_END",28:"COMMA",29:"NUMBER_WITH_DECIMAL",30:"STR",33:"ARROW_DELIMITER",36:"NEWLINE",37:"SEMI",38:"EOF",40:"MD_STR",42:"AMP",43:"NUM",44:"ALPHA",45:"PLUS",46:"EQUALS",47:"MULT",48:"DOT",49:"BRKT",50:"MINUS",51:"UNDERSCORE"},productions_:[0,[3,2],[3,3],[3,2],[3,1],[6,1],[7,0],[7,2],[9,2],[9,2],[9,2],[9,2],[9,2],[9,3],[9,2],[9,3],[9,2],[9,2],[9,1],[17,3],[25,3],[25,1],[27,2],[27,1],[13,1],[13,2],[13,1],[31,1],[31,3],[32,3],[34,3],[34,1],[15,1],[15,2],[15,1],[35,3],[4,1],[4,1],[4,1],[11,1],[11,1],[11,1],[39,1],[39,2],[41,1],[41,1],[41,1],[41,1],[41,1],[41,1],[41,1],[41,1],[41,1],[41,1]],performAction:a(function(l,g,d,x,_,r,lt){var m=r.length-1;switch(_){case 5:x.setOrientation(r[m]);break;case 9:x.setDiagramTitle(r[m].text.trim());break;case 12:x.setLineData({text:"",type:"text"},r[m]);break;case 13:x.setLineData(r[m-1],r[m]);break;case 14:x.setBarData({text:"",type:"text"},r[m]);break;case 15:x.setBarData(r[m-1],r[m]);break;case 16:this.$=r[m].trim(),x.setAccTitle(this.$);break;case 17:case 18:this.$=r[m].trim(),x.setAccDescription(this.$);break;case 19:this.$=r[m-1];break;case 20:case 30:this.$=[r[m-2],...r[m]];break;case 21:case 31:this.$=[r[m]];break;case 22:this.$={value:Number(r[m-1]),label:r[m]};break;case 23:this.$={value:Number(r[m]),label:""};break;case 24:x.setXAxisTitle(r[m]);break;case 25:x.setXAxisTitle(r[m-1]);break;case 26:x.setXAxisTitle({type:"text",text:""});break;case 27:x.setXAxisBand(r[m]);break;case 28:x.setXAxisRangeData(Number(r[m-2]),Number(r[m]));break;case 29:this.$=r[m-1];break;case 32:x.setYAxisTitle(r[m]);break;case 33:x.setYAxisTitle(r[m-1]);break;case 34:x.setYAxisTitle({type:"text",text:""});break;case 35:x.setYAxisRangeData(Number(r[m-2]),Number(r[m]));break;case 39:this.$={text:r[m],type:"text"};break;case 40:this.$={text:r[m],type:"text"};break;case 41:this.$={text:r[m],type:"markdown"};break;case 42:this.$=r[m];break;case 43:this.$=r[m-1]+""+r[m];break}},"anonymous"),table:[e(t,i,{3:1,4:2,7:4,5:s,36:n,37:o,38:h}),{1:[3]},e(t,i,{4:2,7:4,3:8,5:s,36:n,37:o,38:h}),e(t,i,{4:2,7:4,6:9,3:10,5:s,8:[1,11],36:n,37:o,38:h}),{1:[2,4],9:12,10:[1,13],12:[1,14],14:[1,15],16:[1,16],18:[1,17],19:[1,18],21:[1,19],23:[1,20]},e(p,[2,36]),e(p,[2,37]),e(p,[2,38]),{1:[2,1]},e(t,i,{4:2,7:4,3:21,5:s,36:n,37:o,38:h}),{1:[2,3]},e(p,[2,5]),e(t,[2,7],{4:22,36:n,37:o,38:h}),{11:23,30:u,39:24,40:f,41:27,42:R,43:C,44:y,45:E,46:v,47:L,48:M,49:b,50:D,51:c},{11:39,13:38,24:z,29:F,30:u,31:40,32:41,39:24,40:f,41:27,42:R,43:C,44:y,45:E,46:v,47:L,48:M,49:b,50:D,51:c},{11:45,15:44,29:X,30:u,35:46,39:24,40:f,41:27,42:R,43:C,44:y,45:E,46:v,47:L,48:M,49:b,50:D,51:c},{11:49,17:48,24:N,30:u,39:24,40:f,41:27,42:R,43:C,44:y,45:E,46:v,47:L,48:M,49:b,50:D,51:c},{11:52,17:51,24:N,30:u,39:24,40:f,41:27,42:R,43:C,44:y,45:E,46:v,47:L,48:M,49:b,50:D,51:c},{20:[1,53]},{22:[1,54]},e(k,[2,18]),{1:[2,2]},e(k,[2,8]),e(k,[2,9]),e(H,[2,39],{41:55,42:R,43:C,44:y,45:E,46:v,47:L,48:M,49:b,50:D,51:c}),e(H,[2,40]),e(H,[2,41]),e(A,[2,42]),e(A,[2,44]),e(A,[2,45]),e(A,[2,46]),e(A,[2,47]),e(A,[2,48]),e(A,[2,49]),e(A,[2,50]),e(A,[2,51]),e(A,[2,52]),e(A,[2,53]),e(k,[2,10]),e(k,[2,24],{32:41,31:56,24:z,29:F}),e(k,[2,26]),e(k,[2,27]),{33:[1,57]},{11:59,30:u,34:58,39:24,40:f,41:27,42:R,43:C,44:y,45:E,46:v,47:L,48:M,49:b,50:D,51:c},e(k,[2,11]),e(k,[2,32],{35:60,29:X}),e(k,[2,34]),{33:[1,61]},e(k,[2,12]),{17:62,24:N},{25:63,27:64,29:S},e(k,[2,14]),{17:66,24:N},e(k,[2,16]),e(k,[2,17]),e(A,[2,43]),e(k,[2,25]),{29:[1,67]},{26:[1,68]},{26:[2,31],28:[1,69]},e(k,[2,33]),{29:[1,70]},e(k,[2,13]),{26:[1,71]},{26:[2,21],28:[1,72]},e(O,[2,23],{30:[1,73]}),e(k,[2,15]),e(k,[2,28]),e(k,[2,29]),{11:59,30:u,34:74,39:24,40:f,41:27,42:R,43:C,44:y,45:E,46:v,47:L,48:M,49:b,50:D,51:c},e(k,[2,35]),e(k,[2,19]),{25:75,27:64,29:S},e(O,[2,22]),{26:[2,30]},{26:[2,20]}],defaultActions:{8:[2,1],10:[2,3],21:[2,2],74:[2,30],75:[2,20]},parseError:a(function(l,g){if(g.recoverable)this.trace(l);else{var d=new Error(l);throw d.hash=g,d}},"parseError"),parse:a(function(l){var g=this,d=[0],x=[],_=[null],r=[],lt=this.table,m="",dt=0,Ot=0,ui=2,Vt=1,di=r.slice.call(arguments,1),P=Object.create(this.lexer),$={yy:{}};for(var bt in this.yy)Object.prototype.hasOwnProperty.call(this.yy,bt)&&($.yy[bt]=this.yy[bt]);P.setInput(l,$.yy),$.yy.lexer=P,$.yy.parser=this,typeof P.yylloc>"u"&&(P.yylloc={});var wt=P.yylloc;r.push(wt);var xi=P.options&&P.options.ranges;typeof $.yy.parseError=="function"?this.parseError=$.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function fi(B){d.length=d.length-2*B,_.length=_.length-B,r.length=r.length-B}a(fi,"popStack");function Ft(){var B;return B=x.pop()||P.lex()||Vt,typeof B!="number"&&(B instanceof Array&&(x=B,B=x.pop()),B=g.symbols_[B]||B),B}a(Ft,"lex");for(var I,U,V,At,j={},xt,Y,Wt,ft;;){if(U=d[d.length-1],this.defaultActions[U]?V=this.defaultActions[U]:((I===null||typeof I>"u")&&(I=Ft()),V=lt[U]&<[U][I]),typeof V>"u"||!V.length||!V[0]){var Ct="";ft=[];for(xt in lt[U])this.terminals_[xt]&&xt>ui&&ft.push("'"+this.terminals_[xt]+"'");P.showPosition?Ct="Parse error on line "+(dt+1)+`:
|
|
2
|
+
`+P.showPosition()+`
|
|
3
|
+
Expecting `+ft.join(", ")+", got '"+(this.terminals_[I]||I)+"'":Ct="Parse error on line "+(dt+1)+": Unexpected "+(I==Vt?"end of input":"'"+(this.terminals_[I]||I)+"'"),this.parseError(Ct,{text:P.match,token:this.terminals_[I]||I,line:P.yylineno,loc:wt,expected:ft})}if(V[0]instanceof Array&&V.length>1)throw new Error("Parse Error: multiple actions possible at state: "+U+", token: "+I);switch(V[0]){case 1:d.push(I),_.push(P.yytext),r.push(P.yylloc),d.push(V[1]),I=null,Ot=P.yyleng,m=P.yytext,dt=P.yylineno,wt=P.yylloc;break;case 2:if(Y=this.productions_[V[1]][1],j.$=_[_.length-Y],j._$={first_line:r[r.length-(Y||1)].first_line,last_line:r[r.length-1].last_line,first_column:r[r.length-(Y||1)].first_column,last_column:r[r.length-1].last_column},xi&&(j._$.range=[r[r.length-(Y||1)].range[0],r[r.length-1].range[1]]),At=this.performAction.apply(j,[m,Ot,dt,$.yy,V[1],_,r].concat(di)),typeof At<"u")return At;Y&&(d=d.slice(0,-1*Y*2),_=_.slice(0,-1*Y),r=r.slice(0,-1*Y)),d.push(this.productions_[V[1]][0]),_.push(j.$),r.push(j._$),Wt=lt[d[d.length-2]][d[d.length-1]],d.push(Wt);break;case 3:return!0}}return!0},"parse")},ht=function(){var W={EOF:1,parseError:a(function(g,d){if(this.yy.parser)this.yy.parser.parseError(g,d);else throw new Error(g)},"parseError"),setInput:a(function(l,g){return this.yy=g||this.yy||{},this._input=l,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},"setInput"),input:a(function(){var l=this._input[0];this.yytext+=l,this.yyleng++,this.offset++,this.match+=l,this.matched+=l;var g=l.match(/(?:\r\n?|\n).*/g);return g?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),l},"input"),unput:a(function(l){var g=l.length,d=l.split(/(?:\r\n?|\n)/g);this._input=l+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-g),this.offset-=g;var x=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),d.length-1&&(this.yylineno-=d.length-1);var _=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:d?(d.length===x.length?this.yylloc.first_column:0)+x[x.length-d.length].length-d[0].length:this.yylloc.first_column-g},this.options.ranges&&(this.yylloc.range=[_[0],_[0]+this.yyleng-g]),this.yyleng=this.yytext.length,this},"unput"),more:a(function(){return this._more=!0,this},"more"),reject:a(function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
|
|
4
|
+
`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},"reject"),less:a(function(l){this.unput(this.match.slice(l))},"less"),pastInput:a(function(){var l=this.matched.substr(0,this.matched.length-this.match.length);return(l.length>20?"...":"")+l.substr(-20).replace(/\n/g,"")},"pastInput"),upcomingInput:a(function(){var l=this.match;return l.length<20&&(l+=this._input.substr(0,20-l.length)),(l.substr(0,20)+(l.length>20?"...":"")).replace(/\n/g,"")},"upcomingInput"),showPosition:a(function(){var l=this.pastInput(),g=new Array(l.length+1).join("-");return l+this.upcomingInput()+`
|
|
5
|
+
`+g+"^"},"showPosition"),test_match:a(function(l,g){var d,x,_;if(this.options.backtrack_lexer&&(_={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(_.yylloc.range=this.yylloc.range.slice(0))),x=l[0].match(/(?:\r\n?|\n).*/g),x&&(this.yylineno+=x.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:x?x[x.length-1].length-x[x.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+l[0].length},this.yytext+=l[0],this.match+=l[0],this.matches=l,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(l[0].length),this.matched+=l[0],d=this.performAction.call(this,this.yy,this,g,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),d)return d;if(this._backtrack){for(var r in _)this[r]=_[r];return!1}return!1},"test_match"),next:a(function(){if(this.done)return this.EOF;this._input||(this.done=!0);var l,g,d,x;this._more||(this.yytext="",this.match="");for(var _=this._currentRules(),r=0;r<_.length;r++)if(d=this._input.match(this.rules[_[r]]),d&&(!g||d[0].length>g[0].length)){if(g=d,x=r,this.options.backtrack_lexer){if(l=this.test_match(d,_[r]),l!==!1)return l;if(this._backtrack){g=!1;continue}else return!1}else if(!this.options.flex)break}return g?(l=this.test_match(g,_[x]),l!==!1?l:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text.
|
|
6
|
+
`+this.showPosition(),{text:"",token:null,line:this.yylineno})},"next"),lex:a(function(){var g=this.next();return g||this.lex()},"lex"),begin:a(function(g){this.conditionStack.push(g)},"begin"),popState:a(function(){var g=this.conditionStack.length-1;return g>0?this.conditionStack.pop():this.conditionStack[0]},"popState"),_currentRules:a(function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},"_currentRules"),topState:a(function(g){return g=this.conditionStack.length-1-Math.abs(g||0),g>=0?this.conditionStack[g]:"INITIAL"},"topState"),pushState:a(function(g){this.begin(g)},"pushState"),stateStackSize:a(function(){return this.conditionStack.length},"stateStackSize"),options:{"case-insensitive":!0},performAction:a(function(g,d,x,_){switch(x){case 0:break;case 1:break;case 2:return this.popState(),36;case 3:return this.popState(),36;case 4:return 36;case 5:break;case 6:return 10;case 7:return this.pushState("acc_title"),19;case 8:return this.popState(),"acc_title_value";case 9:return this.pushState("acc_descr"),21;case 10:return this.popState(),"acc_descr_value";case 11:this.pushState("acc_descr_multiline");break;case 12:this.popState();break;case 13:return"acc_descr_multiline_value";case 14:return 5;case 15:return 5;case 16:return 8;case 17:return this.pushState("axis_data"),"X_AXIS";case 18:return this.pushState("axis_data"),"Y_AXIS";case 19:return this.pushState("axis_band_data"),24;case 20:return 33;case 21:return this.pushState("data"),16;case 22:return this.pushState("data"),18;case 23:return this.pushState("data_inner"),24;case 24:return 29;case 25:return this.popState(),26;case 26:this.popState();break;case 27:this.pushState("string");break;case 28:this.popState();break;case 29:return"STR";case 30:return 24;case 31:return 26;case 32:return 44;case 33:return"COLON";case 34:return 45;case 35:return 28;case 36:return 46;case 37:return 47;case 38:return 49;case 39:return 51;case 40:return 48;case 41:return 42;case 42:return 50;case 43:return 43;case 44:break;case 45:return 37;case 46:return 38}},"anonymous"),rules:[/^(?:%%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:(\r?\n))/i,/^(?:(\r?\n))/i,/^(?:[\n\r]+)/i,/^(?:%%[^\n]*)/i,/^(?:title\b)/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:\})/i,/^(?:[^\}]*)/i,/^(?:xychart-beta\b)/i,/^(?:xychart\b)/i,/^(?:(?:vertical|horizontal))/i,/^(?:x-axis\b)/i,/^(?:y-axis\b)/i,/^(?:\[)/i,/^(?:-->)/i,/^(?:line\b)/i,/^(?:bar\b)/i,/^(?:\[)/i,/^(?:[+-]?(?:\d+(?:\.\d+)?|\.\d+))/i,/^(?:\])/i,/^(?:(?:`\) \{ this\.pushState\(md_string\); \}\n<md_string>\(\?:\(\?!`"\)\.\)\+ \{ return MD_STR; \}\n<md_string>\(\?:`))/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:\[)/i,/^(?:\])/i,/^(?:[A-Za-z]+)/i,/^(?::)/i,/^(?:\+)/i,/^(?:,)/i,/^(?:=)/i,/^(?:\*)/i,/^(?:#)/i,/^(?:[\_])/i,/^(?:\.)/i,/^(?:&)/i,/^(?:-)/i,/^(?:[0-9]+)/i,/^(?:\s+)/i,/^(?:;)/i,/^(?:$)/i],conditions:{data_inner:{rules:[0,1,4,5,6,7,9,11,14,15,16,17,18,21,22,24,25,26,27,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],inclusive:!0},data:{rules:[0,1,3,4,5,6,7,9,11,14,15,16,17,18,21,22,23,26,27,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],inclusive:!0},axis_band_data:{rules:[0,1,4,5,6,7,9,11,14,15,16,17,18,21,22,25,26,27,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],inclusive:!0},axis_data:{rules:[0,1,2,4,5,6,7,9,11,14,15,16,17,18,19,20,21,22,24,26,27,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],inclusive:!0},acc_descr_multiline:{rules:[12,13],inclusive:!1},acc_descr:{rules:[10],inclusive:!1},acc_title:{rules:[8],inclusive:!1},title:{rules:[],inclusive:!1},md_string:{rules:[],inclusive:!1},string:{rules:[28,29],inclusive:!1},INITIAL:{rules:[0,1,4,5,6,7,9,11,14,15,16,17,18,21,22,26,27,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],inclusive:!0}}};return W}();T.lexer=ht;function q(){this.yy={}}return a(q,"Parser"),q.prototype=T,T.Parser=q,new q}();Rt.parser=Rt;var Li=Rt;function pt(e){return e.type==="bar"}a(pt,"isBarPlot");function mt(e){return e.type==="band"}a(mt,"isBandAxisData");function Q(e){return e.type==="linear"}a(Q,"isLinearAxisData");var K,Pt=(K=class{constructor(t){this.parentGroup=t}getMaxDimension(t,i){if(!this.parentGroup)return{width:t.reduce((o,h)=>Math.max(h.length,o),0)*i,height:i};const s={width:0,height:0},n=this.parentGroup.append("g").attr("visibility","hidden").attr("font-size",i);for(const o of t){const h=Ti(n,1,o),p=h?h.width:o.length*i,u=h?h.height:i;s.width=Math.max(s.width,p),s.height=Math.max(s.height,u)}return n.remove(),s}},a(K,"TextDimensionCalculatorWithFont"),K),Yt=.7,Ht=.2,Z,qt=(Z=class{constructor(t,i,s,n){this.axisConfig=t,this.title=i,this.textDimensionCalculator=s,this.axisThemeConfig=n,this.boundingRect={x:0,y:0,width:0,height:0},this.axisPosition="left",this.showTitle=!1,this.showLabel=!1,this.showTick=!1,this.showAxisLine=!1,this.outerPadding=0,this.titleTextHeight=0,this.labelTextHeight=0,this.normalizedLabelRotationInRad=0,this.range=[0,10],this.boundingRect={x:0,y:0,width:0,height:0},this.axisPosition="left",this.normalizedLabelRotationInRad=this.axisConfig.labelRotation>=-90&&this.axisConfig.labelRotation<=90?this.axisConfig.labelRotation*Math.PI/180:0}setRange(t){this.range=t,this.axisPosition==="left"||this.axisPosition==="right"?this.boundingRect.height=t[1]-t[0]:this.boundingRect.width=t[1]-t[0],this.recalculateScale()}getRange(){return[this.range[0]+this.outerPadding,this.range[1]-this.outerPadding]}setAxisPosition(t){this.axisPosition=t,this.setRange(this.range)}getTickDistance(){const t=this.getRange();return Math.abs(t[0]-t[1])/this.getTickValues().length}getAxisOuterPadding(){return this.outerPadding}getLabelDimension(){return this.textDimensionCalculator.getMaxDimension(this.getTickValues().map(t=>t.toString()),this.axisConfig.labelFontSize)}recalculateOuterPaddingToDrawBar(){Yt*this.getTickDistance()>this.outerPadding*2&&(this.outerPadding=Math.floor(Yt*this.getTickDistance()/2)),this.recalculateScale()}calculateSpaceIfDrawnHorizontally(t){let i=t.height;if(this.axisConfig.showAxisLine&&i>this.axisConfig.axisLineWidth&&(i-=this.axisConfig.axisLineWidth,this.showAxisLine=!0),this.axisConfig.showLabel){const s=this.getLabelDimension(),n=Ht*t.width;this.outerPadding=Math.min(s.width/2,n);let o=s.height;this.axisPosition==="bottom"&&this.normalizedLabelRotationInRad!==0&&(o=Math.max(o,Math.abs(Math.sin(this.normalizedLabelRotationInRad)*s.width)+Math.abs(Math.cos(this.normalizedLabelRotationInRad)*s.height))),o+=this.axisConfig.labelPadding*2,this.labelTextHeight=s.height,o<=i&&(i-=o,this.showLabel=!0)}if(this.axisConfig.showTick&&i>=this.axisConfig.tickLength&&(this.showTick=!0,i-=this.axisConfig.tickLength),this.axisConfig.showTitle&&this.title){const s=this.textDimensionCalculator.getMaxDimension([this.title],this.axisConfig.titleFontSize),n=s.height+this.axisConfig.titlePadding*2;this.titleTextHeight=s.height,n<=i&&(i-=n,this.showTitle=!0)}this.boundingRect.width=t.width,this.boundingRect.height=t.height-i}calculateSpaceIfDrawnVertical(t){let i=t.width;if(this.axisConfig.showAxisLine&&i>this.axisConfig.axisLineWidth&&(i-=this.axisConfig.axisLineWidth,this.showAxisLine=!0),this.axisConfig.showLabel){const s=this.getLabelDimension(),n=Ht*t.height;this.outerPadding=Math.min(s.height/2,n);const o=s.width+this.axisConfig.labelPadding*2;o<=i&&(i-=o,this.showLabel=!0)}if(this.axisConfig.showTick&&i>=this.axisConfig.tickLength&&(this.showTick=!0,i-=this.axisConfig.tickLength),this.axisConfig.showTitle&&this.title){const s=this.textDimensionCalculator.getMaxDimension([this.title],this.axisConfig.titleFontSize),n=s.height+this.axisConfig.titlePadding*2;this.titleTextHeight=s.height,n<=i&&(i-=n,this.showTitle=!0)}this.boundingRect.width=t.width-i,this.boundingRect.height=t.height}calculateSpace(t){return this.axisPosition==="left"||this.axisPosition==="right"?this.calculateSpaceIfDrawnVertical(t):this.calculateSpaceIfDrawnHorizontally(t),this.recalculateScale(),{width:this.boundingRect.width,height:this.boundingRect.height}}setBoundingBoxXY(t){this.boundingRect.x=t.x,this.boundingRect.y=t.y}calculateOffsetByRotation(t){const i=this.normalizedLabelRotationInRad;return i===0?0:Math.sin(i)*this.getLabelDimension()[t]/2}getDrawableElementsForLeftAxis(){const t=[];if(this.showAxisLine){const i=this.boundingRect.x+this.boundingRect.width-this.axisConfig.axisLineWidth/2;t.push({type:"path",groupTexts:["left-axis","axisl-line"],data:[{path:`M ${i},${this.boundingRect.y} L ${i},${this.boundingRect.y+this.boundingRect.height} `,strokeFill:this.axisThemeConfig.axisLineColor,strokeWidth:this.axisConfig.axisLineWidth}]})}if(this.showLabel&&t.push({type:"text",groupTexts:["left-axis","label"],data:this.getTickValues().map(i=>({text:i.toString(),x:this.boundingRect.x+this.boundingRect.width-(this.showLabel?this.axisConfig.labelPadding:0)-(this.showTick?this.axisConfig.tickLength:0)-(this.showAxisLine?this.axisConfig.axisLineWidth:0),y:this.getScaleValue(i),fill:this.axisThemeConfig.labelColor,fontSize:this.axisConfig.labelFontSize,rotation:0,verticalPos:"middle",horizontalPos:"right"}))}),this.showTick){const i=this.boundingRect.x+this.boundingRect.width-(this.showAxisLine?this.axisConfig.axisLineWidth:0);t.push({type:"path",groupTexts:["left-axis","ticks"],data:this.getTickValues().map(s=>({path:`M ${i},${this.getScaleValue(s)} L ${i-this.axisConfig.tickLength},${this.getScaleValue(s)}`,strokeFill:this.axisThemeConfig.tickColor,strokeWidth:this.axisConfig.tickWidth}))})}return this.showTitle&&t.push({type:"text",groupTexts:["left-axis","title"],data:[{text:this.title,x:this.boundingRect.x+this.axisConfig.titlePadding,y:this.boundingRect.y+this.boundingRect.height/2,fill:this.axisThemeConfig.titleColor,fontSize:this.axisConfig.titleFontSize,rotation:270,verticalPos:"top",horizontalPos:"center"}]}),t}getDrawableElementsForBottomAxis(){const t=[];if(this.showAxisLine){const i=this.boundingRect.y+this.axisConfig.axisLineWidth/2;t.push({type:"path",groupTexts:["bottom-axis","axis-line"],data:[{path:`M ${this.boundingRect.x},${i} L ${this.boundingRect.x+this.boundingRect.width},${i}`,strokeFill:this.axisThemeConfig.axisLineColor,strokeWidth:this.axisConfig.axisLineWidth}]})}if(this.showLabel&&t.push({type:"text",groupTexts:["bottom-axis","label"],data:this.getTickValues().map(i=>({text:i.toString(),x:this.getScaleValue(i)+this.calculateOffsetByRotation("height"),y:this.boundingRect.y+this.axisConfig.labelPadding+(this.showTick?this.axisConfig.tickLength:0)+(this.showAxisLine?this.axisConfig.axisLineWidth:0)+Math.abs(this.calculateOffsetByRotation("width")),fill:this.axisThemeConfig.labelColor,fontSize:this.axisConfig.labelFontSize,rotation:this.normalizedLabelRotationInRad*180/Math.PI,verticalPos:"top",horizontalPos:"center"}))}),this.showTick){const i=this.boundingRect.y+(this.showAxisLine?this.axisConfig.axisLineWidth:0);t.push({type:"path",groupTexts:["bottom-axis","ticks"],data:this.getTickValues().map(s=>({path:`M ${this.getScaleValue(s)},${i} L ${this.getScaleValue(s)},${i+this.axisConfig.tickLength}`,strokeFill:this.axisThemeConfig.tickColor,strokeWidth:this.axisConfig.tickWidth}))})}return this.showTitle&&t.push({type:"text",groupTexts:["bottom-axis","title"],data:[{text:this.title,x:this.range[0]+(this.range[1]-this.range[0])/2,y:this.boundingRect.y+this.boundingRect.height-this.axisConfig.titlePadding-this.titleTextHeight,fill:this.axisThemeConfig.titleColor,fontSize:this.axisConfig.titleFontSize,rotation:0,verticalPos:"top",horizontalPos:"center"}]}),t}getDrawableElementsForTopAxis(){const t=[];if(this.showAxisLine){const i=this.boundingRect.y+this.boundingRect.height-this.axisConfig.axisLineWidth/2;t.push({type:"path",groupTexts:["top-axis","axis-line"],data:[{path:`M ${this.boundingRect.x},${i} L ${this.boundingRect.x+this.boundingRect.width},${i}`,strokeFill:this.axisThemeConfig.axisLineColor,strokeWidth:this.axisConfig.axisLineWidth}]})}if(this.showLabel&&t.push({type:"text",groupTexts:["top-axis","label"],data:this.getTickValues().map(i=>({text:i.toString(),x:this.getScaleValue(i),y:this.boundingRect.y+(this.showTitle?this.titleTextHeight+this.axisConfig.titlePadding*2:0)+this.axisConfig.labelPadding,fill:this.axisThemeConfig.labelColor,fontSize:this.axisConfig.labelFontSize,rotation:0,verticalPos:"top",horizontalPos:"center"}))}),this.showTick){const i=this.boundingRect.y;t.push({type:"path",groupTexts:["top-axis","ticks"],data:this.getTickValues().map(s=>({path:`M ${this.getScaleValue(s)},${i+this.boundingRect.height-(this.showAxisLine?this.axisConfig.axisLineWidth:0)} L ${this.getScaleValue(s)},${i+this.boundingRect.height-this.axisConfig.tickLength-(this.showAxisLine?this.axisConfig.axisLineWidth:0)}`,strokeFill:this.axisThemeConfig.tickColor,strokeWidth:this.axisConfig.tickWidth}))})}return this.showTitle&&t.push({type:"text",groupTexts:["top-axis","title"],data:[{text:this.title,x:this.boundingRect.x+this.boundingRect.width/2,y:this.boundingRect.y+this.axisConfig.titlePadding,fill:this.axisThemeConfig.titleColor,fontSize:this.axisConfig.titleFontSize,rotation:0,verticalPos:"top",horizontalPos:"center"}]}),t}getDrawableElements(){if(this.axisPosition==="left")return this.getDrawableElementsForLeftAxis();if(this.axisPosition==="right")throw Error("Drawing of right axis is not implemented");return this.axisPosition==="bottom"?this.getDrawableElementsForBottomAxis():this.axisPosition==="top"?this.getDrawableElementsForTopAxis():[]}},a(Z,"BaseAxis"),Z),J,Ei=(J=class extends qt{constructor(t,i,s,n,o){super(t,n,o,i),this.categories=s,this.scale=St().domain(this.categories).range(this.getRange())}setRange(t){super.setRange(t)}recalculateScale(){this.scale=St().domain(this.categories).range(this.getRange()).paddingInner(1).paddingOuter(0).align(.5),Ut.trace("BandAxis axis final categories, range: ",this.categories,this.getRange())}getTickValues(){return this.categories}getScaleValue(t){return this.scale(t)??this.getRange()[0]}},a(J,"BandAxis"),J),tt,Mi=(tt=class extends qt{constructor(t,i,s,n,o){super(t,n,o,i),this.domain=s,this.scale=Xt().domain(this.domain).range(this.getRange())}getTickValues(){return this.scale.ticks()}recalculateScale(){const t=[...this.domain];this.axisPosition==="left"&&t.reverse(),this.scale=Xt().domain(t).range(this.getRange())}getScaleValue(t){return this.scale(t)}},a(tt,"LinearAxis"),tt);function _t(e,t,i,s){const n=new Pt(s);return mt(e)?new Ei(t,i,e.categories,e.title,n):new Mi(t,i,[e.min,e.max],e.title,n)}a(_t,"getAxis");var it,Ii=(it=class{constructor(t,i,s,n){this.textDimensionCalculator=t,this.chartConfig=i,this.chartData=s,this.chartThemeConfig=n,this.boundingRect={x:0,y:0,width:0,height:0},this.showChartTitle=!1}setBoundingBoxXY(t){this.boundingRect.x=t.x,this.boundingRect.y=t.y}calculateSpace(t){const i=this.textDimensionCalculator.getMaxDimension([this.chartData.title],this.chartConfig.titleFontSize),s=Math.max(i.width,t.width),n=i.height+2*this.chartConfig.titlePadding;return i.width<=s&&i.height<=n&&this.chartConfig.showTitle&&this.chartData.title&&(this.boundingRect.width=s,this.boundingRect.height=n,this.showChartTitle=!0),{width:this.boundingRect.width,height:this.boundingRect.height}}getDrawableElements(){const t=[];return this.showChartTitle&&t.push({groupTexts:["chart-title"],type:"text",data:[{fontSize:this.chartConfig.titleFontSize,text:this.chartData.title,verticalPos:"middle",horizontalPos:"center",x:this.boundingRect.x+this.boundingRect.width/2,y:this.boundingRect.y+this.boundingRect.height/2,fill:this.chartThemeConfig.titleColor,rotation:0}]}),t}},a(it,"ChartTitle"),it);function jt(e,t,i,s){const n=new Pt(s);return new Ii(n,e,t,i)}a(jt,"getChartTitleComponent");var Bi=.75,zi=.5,Oi=.35;function kt(e){return{fontSize:e,markerSize:e*Bi,markerSpacing:e*Oi,itemSpacing:e*zi}}a(kt,"getLegendLayout");var et,Vi=(et=class{constructor(t,i,s,n){this.textDimensionCalculator=t,this.chartConfig=i,this.chartData=s,this.chartThemeConfig=n,this.boundingRect={x:0,y:0,width:0,height:0},this.visiblePlots=[]}setBoundingBoxXY(t){this.boundingRect.x=t.x,this.boundingRect.y=t.y}calculateSpace(t){if(this.visiblePlots=this.chartConfig.showLegend?this.chartData.plots.filter(f=>f.title):[],this.visiblePlots.length===0)return this.boundingRect.width=0,this.boundingRect.height=0,{width:0,height:0};const{fontSize:i,markerSize:s,markerSpacing:n,itemSpacing:o}=kt(this.chartConfig.legendFontSize),h=this.textDimensionCalculator.getMaxDimension(this.visiblePlots.map(f=>f.title),i),p=this.chartConfig.legendPadding*2+s+n+h.width,u=this.chartConfig.legendPadding*2+this.visiblePlots.length*i+(this.visiblePlots.length-1)*o;return p<=t.width&&u<=t.height?(this.boundingRect.width=p,this.boundingRect.height=u):(this.visiblePlots=[],this.boundingRect.width=0,this.boundingRect.height=0),{width:this.boundingRect.width,height:this.boundingRect.height}}getDrawableElements(){if(this.visiblePlots.length===0)return[];const{fontSize:t,markerSize:i,markerSpacing:s,itemSpacing:n}=kt(this.chartConfig.legendFontSize),o=t+n,h=this.boundingRect.x+this.chartConfig.legendPadding,p=this.boundingRect.y+this.chartConfig.legendPadding,u=[],f=[];for(const[R,C]of this.visiblePlots.entries())if(pt(C))u.push({x:h,y:p+R*o,width:i,height:i,fill:C.fill,strokeFill:C.fill,strokeWidth:0});else{const y=p+R*o+i/2;f.push({path:`M ${h},${y} L ${h+i},${y}`,strokeFill:C.strokeFill,strokeWidth:C.strokeWidth})}return[{groupTexts:["legend","markers"],type:"rect",data:u},{groupTexts:["legend","markers"],type:"path",data:f},{groupTexts:["legend","label"],type:"text",data:this.visiblePlots.map((R,C)=>({text:R.title,x:h+i+s,y:p+C*o+i/2,fill:this.chartThemeConfig.legendTextColor,fontSize:t,rotation:0,verticalPos:"middle",horizontalPos:"left"}))}]}},a(et,"ChartLegend"),et);function Qt(e,t,i,s){const n=new Pt(s);return new Vi(n,e,t,i)}a(Qt,"getChartLegendComponent");var st,Fi=(st=class{constructor(t,i,s,n,o){this.plotData=t,this.xAxis=i,this.yAxis=s,this.orientation=n,this.plotIndex=o}getDrawableElement(){const t=this.plotData.data.map(n=>[this.xAxis.getScaleValue(n[0]),this.yAxis.getScaleValue(n[1])]);let i;if(this.orientation==="horizontal"?i=Nt().y(n=>n[0]).x(n=>n[1])(t):i=Nt().x(n=>n[0]).y(n=>n[1])(t),!i)return[];const s=[{groupTexts:["plot",`line-plot-${this.plotIndex}`],type:"path",data:[{path:i,strokeFill:this.plotData.strokeFill,strokeWidth:this.plotData.strokeWidth}]}];if(this.plotData.pointLabels&&this.plotData.pointLabels.length>0){const h=[];for(const[p,[u,f]]of t.entries()){const R=this.plotData.pointLabels[p];R&&(this.orientation==="horizontal"?h.push({x:f+10,y:u,text:R,fill:this.plotData.strokeFill,verticalPos:"middle",horizontalPos:"left",fontSize:12,rotation:0}):h.push({x:u,y:f-10,text:R,fill:this.plotData.strokeFill,verticalPos:"middle",horizontalPos:"center",fontSize:12,rotation:0}))}h.length>0&&s.push({groupTexts:["plot",`line-plot-${this.plotIndex}`,"labels"],type:"text",data:h})}return s}},a(st,"LinePlot"),st),nt,Wi=(nt=class{constructor(t,i,s,n,o,h){this.barData=t,this.boundingRect=i,this.xAxis=s,this.yAxis=n,this.orientation=o,this.plotIndex=h}getDrawableElement(){const t=this.barData.data.map(o=>[this.xAxis.getScaleValue(o[0]),this.yAxis.getScaleValue(o[1])]),s=Math.min(this.xAxis.getAxisOuterPadding()*2,this.xAxis.getTickDistance())*(1-.05),n=s/2;return this.orientation==="horizontal"?[{groupTexts:["plot",`bar-plot-${this.plotIndex}`],type:"rect",data:t.map(o=>({x:this.boundingRect.x,y:o[0]-n,height:s,width:o[1]-this.boundingRect.x,fill:this.barData.fill,strokeWidth:0,strokeFill:this.barData.fill}))}]:[{groupTexts:["plot",`bar-plot-${this.plotIndex}`],type:"rect",data:t.map(o=>({x:o[0]-n,y:o[1],width:s,height:this.boundingRect.y+this.boundingRect.height-o[1],fill:this.barData.fill,strokeWidth:0,strokeFill:this.barData.fill}))}]}},a(nt,"BarPlot"),nt),at,Xi=(at=class{constructor(t,i,s){this.chartConfig=t,this.chartData=i,this.chartThemeConfig=s,this.boundingRect={x:0,y:0,width:0,height:0}}setAxes(t,i){this.xAxis=t,this.yAxis=i}setBoundingBoxXY(t){this.boundingRect.x=t.x,this.boundingRect.y=t.y}calculateSpace(t){return this.boundingRect.width=t.width,this.boundingRect.height=t.height,{width:this.boundingRect.width,height:this.boundingRect.height}}getDrawableElements(){if(!(this.xAxis&&this.yAxis))throw Error("Axes must be passed to render Plots");const t=[];for(const[i,s]of this.chartData.plots.entries())switch(s.type){case"line":{const n=new Fi(s,this.xAxis,this.yAxis,this.chartConfig.chartOrientation,i);t.push(...n.getDrawableElement())}break;case"bar":{const n=new Wi(s,this.boundingRect,this.xAxis,this.yAxis,this.chartConfig.chartOrientation,i);t.push(...n.getDrawableElement())}break}return t}},a(at,"BasePlot"),at);function Kt(e,t,i){return new Xi(e,t,i)}a(Kt,"getPlotComponent");var ot,Ni=(ot=class{constructor(t,i,s,n){this.chartConfig=t,this.chartData=i,this.componentStore={title:jt(t,i,s,n),plot:Kt(t,i,s),legend:Qt(t,i,s,n),xAxis:_t(i.xAxis,t.xAxis,{titleColor:s.xAxisTitleColor,labelColor:s.xAxisLabelColor,tickColor:s.xAxisTickColor,axisLineColor:s.xAxisLineColor},n),yAxis:_t(i.yAxis,t.yAxis,{titleColor:s.yAxisTitleColor,labelColor:s.yAxisLabelColor,tickColor:s.yAxisTickColor,axisLineColor:s.yAxisLineColor},n)}}calculateVerticalSpace(){let t=this.chartConfig.width,i=this.chartConfig.height,s=0,n=0,o={width:0,height:0},h=Math.floor(t*this.chartConfig.plotReservedSpacePercent/100),p=Math.floor(i*this.chartConfig.plotReservedSpacePercent/100),u=this.componentStore.plot.calculateSpace({width:h,height:p});t-=u.width,i-=u.height,u=this.componentStore.title.calculateSpace({width:this.chartConfig.width,height:i}),n=u.height,i-=u.height,this.componentStore.xAxis.setAxisPosition("bottom"),u=this.componentStore.xAxis.calculateSpace({width:t,height:i}),i-=u.height,this.componentStore.yAxis.setAxisPosition("left"),u=this.componentStore.yAxis.calculateSpace({width:t,height:i}),s=u.width,t-=u.width,o=this.componentStore.legend.calculateSpace({width:t,height:p}),t-=o.width,t>0&&(h+=t,t=0),i>0&&(p+=i,i=0),this.componentStore.plot.calculateSpace({width:h,height:p}),this.componentStore.plot.setBoundingBoxXY({x:s,y:n}),this.componentStore.legend.setBoundingBoxXY({x:s+h,y:n+Math.max((p-o.height)/2,0)}),this.componentStore.xAxis.setRange([s,s+h]),this.componentStore.xAxis.setBoundingBoxXY({x:s,y:n+p}),this.componentStore.yAxis.setRange([n,n+p]),this.componentStore.yAxis.setBoundingBoxXY({x:0,y:n}),this.chartData.plots.some(f=>pt(f))&&this.componentStore.xAxis.recalculateOuterPaddingToDrawBar()}calculateHorizontalSpace(){let t=this.chartConfig.width,i=this.chartConfig.height,s=0,n=0,o=0,h={width:0,height:0},p=Math.floor(t*this.chartConfig.plotReservedSpacePercent/100),u=Math.floor(i*this.chartConfig.plotReservedSpacePercent/100),f=this.componentStore.plot.calculateSpace({width:p,height:u});t-=f.width,i-=f.height,f=this.componentStore.title.calculateSpace({width:this.chartConfig.width,height:i}),s=f.height,i-=f.height,this.componentStore.xAxis.setAxisPosition("left"),f=this.componentStore.xAxis.calculateSpace({width:t,height:i}),t-=f.width,n=f.width,this.componentStore.yAxis.setAxisPosition("top"),f=this.componentStore.yAxis.calculateSpace({width:t,height:i}),i-=f.height,o=s+f.height,h=this.componentStore.legend.calculateSpace({width:t,height:u}),t-=h.width,t>0&&(p+=t,t=0),i>0&&(u+=i,i=0),this.componentStore.plot.calculateSpace({width:p,height:u}),this.componentStore.plot.setBoundingBoxXY({x:n,y:o}),this.componentStore.legend.setBoundingBoxXY({x:n+p,y:o+Math.max((u-h.height)/2,0)}),this.componentStore.yAxis.setRange([n,n+p]),this.componentStore.yAxis.setBoundingBoxXY({x:n,y:s}),this.componentStore.xAxis.setRange([o,o+u]),this.componentStore.xAxis.setBoundingBoxXY({x:0,y:o}),this.chartData.plots.some(R=>pt(R))&&this.componentStore.xAxis.recalculateOuterPaddingToDrawBar()}calculateSpace(){this.chartConfig.chartOrientation==="horizontal"?this.calculateHorizontalSpace():this.calculateVerticalSpace()}getDrawableElement(){this.calculateSpace();const t=[];this.componentStore.plot.setAxes(this.componentStore.xAxis,this.componentStore.yAxis);for(const i of Object.values(this.componentStore))t.push(...i.getDrawableElements());return t}},a(ot,"Orchestrator"),ot),rt,Yi=(rt=class{static build(t,i,s,n){return new Ni(t,i,s,n).getDrawableElement()}},a(rt,"XYChartBuilder"),rt),ct=0,Zt,gt=Et(),ut=Lt(),w=Mt(),Tt=ut.plotColorPalette.split(",").map(e=>e.trim()),yt=!1,vt=!1;function Lt(){const e=ki(),t=Dt();return Gt(e.xyChart,t.themeVariables.xyChart)}a(Lt,"getChartDefaultThemeConfig");function Et(){const e=Dt();return Gt(_i.xyChart,e.xyChart)}a(Et,"getChartDefaultConfig");function Mt(){return{yAxis:{type:"linear",title:"",min:1/0,max:-1/0},xAxis:{type:"band",title:"",categories:[]},title:"",plots:[]}}a(Mt,"getChartDefaultData");function G(e){const t=Dt();return Ri(e.trim(),t)}a(G,"textSanitizer");function Jt(e){Zt=e}a(Jt,"setTmpSVGG");function ti(e){e==="horizontal"?gt.chartOrientation="horizontal":gt.chartOrientation="vertical"}a(ti,"setOrientation");function ii(e){w.xAxis.title=G(e.text)}a(ii,"setXAxisTitle");function It(e,t){w.xAxis={type:"linear",title:w.xAxis.title,min:e,max:t},yt=!0}a(It,"setXAxisRangeData");function ei(e){w.xAxis={type:"band",title:w.xAxis.title,categories:e.map(t=>G(t.text))},yt=!0}a(ei,"setXAxisBand");function si(e){w.yAxis.title=G(e.text)}a(si,"setYAxisTitle");function ni(e,t){w.yAxis={type:"linear",title:w.yAxis.title,min:e,max:t},vt=!0}a(ni,"setYAxisRangeData");function ai(e){const t=Math.min(...e),i=Math.max(...e),s=Q(w.yAxis)?w.yAxis.min:1/0,n=Q(w.yAxis)?w.yAxis.max:-1/0;w.yAxis={type:"linear",title:w.yAxis.title,min:Math.min(s,t),max:Math.max(n,i)}}a(ai,"setYAxisRangeFromPlotData");function Bt(e){let t=[];if(e.length===0)return t;if(!yt){const i=Q(w.xAxis)?w.xAxis.min:1/0,s=Q(w.xAxis)?w.xAxis.max:-1/0;It(Math.min(i,1),Math.max(s,e.length))}if(mt(w.xAxis)&&e.length>w.xAxis.categories.length&&(e=e.slice(0,w.xAxis.categories.length)),vt||ai(e),mt(w.xAxis)&&(t=w.xAxis.categories.map((i,s)=>[i,e[s]])),Q(w.xAxis)){const i=w.xAxis.min,s=w.xAxis.max;if(e.length===1)t=[[`${i}`,e[0]]];else{const n=(s-i)/(e.length-1);t=e.map((o,h)=>[`${i+h*n}`,o])}}return t}a(Bt,"transformDataWithoutCategory");function zt(e){return Tt[e===0?0:e%Tt.length]}a(zt,"getPlotColorFromPalette");function oi(e,t){const i=t.map(h=>h.value),s=t.map(h=>h.label?G(h.label):""),n=Bt(i),o=s.some(h=>h!=="");w.plots.push({type:"line",title:G(e.text),strokeFill:zt(ct),strokeWidth:2,data:n,...o?{pointLabels:s}:{}}),ct++}a(oi,"setLineData");function ri(e,t){const i=t.map(n=>n.value),s=Bt(i);w.plots.push({type:"bar",title:G(e.text),fill:zt(ct),data:s}),ct++}a(ri,"setBarData");function hi(){if(w.plots.length===0)throw Error("No Plot to render, please provide a plot with some data");return w.title=$t(),Yi.build(gt,w,ut,Zt)}a(hi,"getDrawableElem");function li(){return ut}a(li,"getChartThemeConfig");function ci(){return gt}a(ci,"getChartConfig");function gi(){return w}a(gi,"getXYChartData");var Hi=a(function(){Si(),ct=0,gt=Et(),w=Mt(),ut=Lt(),Tt=ut.plotColorPalette.split(",").map(e=>e.trim()),yt=!1,vt=!1},"clear"),$i={getDrawableElem:hi,clear:Hi,setAccTitle:wi,getAccTitle:bi,setDiagramTitle:yi,getDiagramTitle:$t,getAccDescription:mi,setAccDescription:pi,setOrientation:ti,setXAxisTitle:ii,setXAxisRangeData:It,setXAxisBand:ei,setYAxisTitle:si,setYAxisRangeData:ni,setLineData:oi,setBarData:ri,setTmpSVGG:Jt,getChartThemeConfig:li,getChartConfig:ci,getXYChartData:gi},Ui=a((e,t,i,s)=>{const n=s.db,o=n.getChartThemeConfig(),h=n.getChartConfig(),p=n.getXYChartData().plots[0].data.map(b=>b[1]);function u(b){return b==="top"?"text-before-edge":"middle"}a(u,"getDominantBaseLine");function f(b){return b==="left"?"start":b==="right"?"end":"middle"}a(f,"getTextAnchor");function R(b){return`translate(${b.x}, ${b.y}) rotate(${b.rotation||0})`}a(R,"getTextTransformation"),Ut.debug(`Rendering xychart chart
|
|
7
|
+
`+e);const C=Ai(t),y=C.append("g").attr("class","main"),E=y.append("rect").attr("width",h.width).attr("height",h.height).attr("class","background");Ci(C,h.height,h.width,!0),C.attr("viewBox",`0 0 ${h.width} ${h.height}`),E.attr("fill",o.backgroundColor),n.setTmpSVGG(C.append("g").attr("class","mermaid-tmp-group"));const v=n.getDrawableElem(),L={};function M(b){let D=y,c="";for(const[z]of b.entries()){let F=y;z>0&&L[c]&&(F=L[c]),c+=b[z],D=L[c],D||(D=L[c]=F.append("g").attr("class",b[z]))}return D}a(M,"getGroup");for(const b of v){if(b.data.length===0)continue;const D=M(b.groupTexts);switch(b.type){case"rect":if(D.selectAll("rect").data(b.data).enter().append("rect").attr("x",c=>c.x).attr("y",c=>c.y).attr("width",c=>c.width).attr("height",c=>c.height).attr("fill",c=>c.fill).attr("stroke",c=>c.strokeFill).attr("stroke-width",c=>c.strokeWidth),h.showDataLabel){const c=h.showDataLabelOutsideBar;if(h.chartOrientation==="horizontal"){let z=function(S,O){const{data:T,label:ht}=S;return O*ht.length*F<=T.width-X};a(z,"fitsHorizontally");const F=.7,X=10,N=b.data.map((S,O)=>({data:S,label:p[O].toString()})).filter(S=>S.data.width>0&&S.data.height>0),k=N.map(S=>{const{data:O}=S;let T=O.height*.7;for(;!z(S,T)&&T>0;)T-=1;return T}),H=Math.floor(Math.min(...k)),A=a(S=>c?S.data.x+S.data.width+X:S.data.x+S.data.width-X,"determineLabelXPosition");D.selectAll("text").data(N).enter().append("text").attr("x",A).attr("y",S=>S.data.y+S.data.height/2).attr("text-anchor",c?"start":"end").attr("dominant-baseline","middle").attr("fill",o.dataLabelColor).attr("font-size",`${H}px`).text(S=>S.label)}else{let z=function(A,S,O){const{data:T,label:ht}=A,W=S*ht.length*.7,l=T.x+T.width/2,g=l-W/2,d=l+W/2,x=g>=T.x&&d<=T.x+T.width,_=T.y+O+S<=T.y+T.height;return x&&_};a(z,"fitsInBar");const F=10,X=b.data.map((A,S)=>({data:A,label:p[S].toString()})).filter(A=>A.data.width>0&&A.data.height>0),N=X.map(A=>{const{data:S,label:O}=A;let T=S.width/(O.length*.7);for(;!z(A,T,F)&&T>0;)T-=1;return T}),k=Math.floor(Math.min(...N)),H=a(A=>c?A.data.y-F:A.data.y+F,"determineLabelYPosition");D.selectAll("text").data(X).enter().append("text").attr("x",A=>A.data.x+A.data.width/2).attr("y",H).attr("text-anchor","middle").attr("dominant-baseline",c?"auto":"hanging").attr("fill",o.dataLabelColor).attr("font-size",`${k}px`).text(A=>A.label)}}break;case"text":D.selectAll("text").data(b.data).enter().append("text").attr("x",0).attr("y",0).attr("fill",c=>c.fill).attr("font-size",c=>c.fontSize).attr("dominant-baseline",c=>u(c.verticalPos)).attr("text-anchor",c=>f(c.horizontalPos)).attr("transform",c=>R(c)).text(c=>c.text);break;case"path":D.selectAll("path").data(b.data).enter().append("path").attr("d",c=>c.path).attr("fill",c=>c.fill?c.fill:"none").attr("stroke",c=>c.strokeFill).attr("stroke-width",c=>c.strokeWidth);break}}},"draw"),Gi={draw:Ui},ee={parser:Li,db:$i,renderer:Gi};export{ee as diagram};
|
package/dist/client/index.html
CHANGED
|
@@ -8,11 +8,10 @@
|
|
|
8
8
|
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
|
9
9
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
|
10
10
|
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
|
11
|
-
<script type="module" crossorigin src="/assets/index-
|
|
12
|
-
<link rel="stylesheet" href="/assets/index-
|
|
11
|
+
<script type="module" crossorigin src="/assets/index-CIhkXT_z.js"></script>
|
|
12
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DEiH2AE7.css">
|
|
13
13
|
</head>
|
|
14
14
|
<body>
|
|
15
15
|
<div id="app"></div>
|
|
16
|
-
|
|
17
16
|
</body>
|
|
18
17
|
</html>
|
package/dist/server/app.js
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
// Pure Hono application — no startup side effects.
|
|
2
2
|
// Exported so tests can import it without spinning up a real server.
|
|
3
3
|
import { Hono } from "hono";
|
|
4
|
+
import { bodyLimit } from "hono/body-limit";
|
|
4
5
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
5
6
|
import { existsSync } from "node:fs";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { applyLoadedSnapshotResult, appendFrameAndBroadcast, commitRenderResult, commitStepFramesResult, initStepFramesResult, seekAndBroadcast, stepAndBroadcast, validateWorkspaceInput, } from "./render-core.js";
|
|
14
|
-
import { generateExportHtml } from "./export-html.js";
|
|
15
|
-
import { setViewport } from "./viewport-cache.js";
|
|
16
|
-
import { getSnapshotsRoot } from "./paths.js";
|
|
7
|
+
import { hasMermaidKeyword } from "./validate.js";
|
|
8
|
+
import { registerRenderRoutes } from "./routes/render.js";
|
|
9
|
+
import { registerSlideshowRoutes } from "./routes/slideshow.js";
|
|
10
|
+
import { registerSnapshotRoutes } from "./routes/snapshots.js";
|
|
11
|
+
import { registerExportRoutes } from "./routes/export.js";
|
|
12
|
+
import { registerImportRoutes } from "./routes/import.js";
|
|
13
|
+
import { registerQuizRoutes } from "./routes/quiz.js";
|
|
17
14
|
// Re-export for tests that reference MERMAID_KEYWORDS / isValidMermaid directly.
|
|
18
15
|
export { MERMAID_KEYWORDS } from "./validate.js";
|
|
19
16
|
export function isValidMermaid(payload) {
|
|
@@ -30,397 +27,32 @@ export function isValidMermaid(payload) {
|
|
|
30
27
|
const CSP_HEADER = "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; " +
|
|
31
28
|
"img-src 'self' data:; connect-src 'self' ws: wss:; object-src 'none'; base-uri 'none'; " +
|
|
32
29
|
"frame-ancestors 'none'";
|
|
30
|
+
// NF48 (docs/03 §6): caps every JSON-accepting route's request body so an
|
|
31
|
+
// oversized payload gets a fast 413 instead of running unbounded input
|
|
32
|
+
// through synchronous rendering (mermaid/katex/vega-lite parsing).
|
|
33
|
+
const MAX_BODY_SIZE_BYTES = 10 * 1024 * 1024; // 10 MB
|
|
33
34
|
export function createApp(options = {}) {
|
|
34
35
|
const app = new Hono();
|
|
35
36
|
app.use("*", async (c, next) => {
|
|
36
37
|
await next();
|
|
37
38
|
c.header("Content-Security-Policy", CSP_HEADER);
|
|
38
39
|
});
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const validationError = await validateFrame({ type, payload });
|
|
56
|
-
if (validationError) {
|
|
57
|
-
return c.json({ ok: false, error: validationError });
|
|
58
|
-
}
|
|
59
|
-
const result = commitRenderResult(type, payload, workspace, title);
|
|
60
|
-
return c.json(result);
|
|
61
|
-
});
|
|
62
|
-
app.post("/step", async (c) => {
|
|
63
|
-
const body = await c.req.json();
|
|
64
|
-
if (body.direction !== "next" && body.direction !== "prev") {
|
|
65
|
-
return c.json({ ok: false, error: 'direction must be "next" or "prev"' }, 400);
|
|
66
|
-
}
|
|
67
|
-
return c.json(stepAndBroadcast(body.direction));
|
|
68
|
-
});
|
|
69
|
-
app.post("/seek", async (c) => {
|
|
70
|
-
const body = await c.req.json();
|
|
71
|
-
if (typeof body.frame !== "number" || !Number.isInteger(body.frame)) {
|
|
72
|
-
return c.json({ ok: false, error: "frame must be an integer" }, 400);
|
|
73
|
-
}
|
|
74
|
-
return c.json(seekAndBroadcast(body.frame));
|
|
75
|
-
});
|
|
76
|
-
app.post("/clear", (c) => {
|
|
77
|
-
cancelSlideshow({ persist: false }); // clear() must never produce a snapshot (F10)
|
|
78
|
-
clearCanvas();
|
|
79
|
-
broadcast({ action: "clear" });
|
|
80
|
-
return c.json({ ok: true });
|
|
81
|
-
});
|
|
82
|
-
// ── Slideshow (Phase 2 — Sprint 9) ───────────────────────────────────────────
|
|
83
|
-
app.post("/slideshow", async (c) => {
|
|
84
|
-
const body = await c.req.json();
|
|
85
|
-
if (!Array.isArray(body.slides) || body.slides.length === 0) {
|
|
86
|
-
return c.json({ ok: false, error: "slides must be a non-empty array" }, 400);
|
|
87
|
-
}
|
|
88
|
-
if (typeof body.delay_ms !== "number" || body.delay_ms <= 0) {
|
|
89
|
-
return c.json({ ok: false, error: "delay_ms must be a positive number" }, 400);
|
|
90
|
-
}
|
|
91
|
-
const workspaceResult = validateWorkspaceInput(body.workspace);
|
|
92
|
-
if (!workspaceResult.ok) {
|
|
93
|
-
return c.json({ ok: false, error: workspaceResult.error }, 400);
|
|
94
|
-
}
|
|
95
|
-
const { workspace } = workspaceResult;
|
|
96
|
-
const rawSlides = body.slides;
|
|
97
|
-
// Validate each slide — same rules as POST /render.
|
|
98
|
-
const validatedSlides = [];
|
|
99
|
-
for (let i = 0; i < rawSlides.length; i++) {
|
|
100
|
-
const s = rawSlides[i];
|
|
101
|
-
if (typeof s.type !== "string" || typeof s.payload !== "string") {
|
|
102
|
-
return c.json({
|
|
103
|
-
ok: false,
|
|
104
|
-
error: `slide[${i}]: "type" and "payload" must be strings`,
|
|
105
|
-
}, 400);
|
|
106
|
-
}
|
|
107
|
-
if (!FRAME_TYPES.includes(s.type)) {
|
|
108
|
-
return c.json({ ok: false, error: `slide[${i}]: type must be one of: ${FRAME_TYPES.join(", ")}` }, 400);
|
|
109
|
-
}
|
|
110
|
-
if (s.title !== undefined && typeof s.title !== "string") {
|
|
111
|
-
return c.json({ ok: false, error: `slide[${i}]: "title" must be a string` }, 400);
|
|
112
|
-
}
|
|
113
|
-
const err = await validateFrame({ type: s.type, payload: s.payload });
|
|
114
|
-
if (err) {
|
|
115
|
-
return c.json({ ok: false, error: `slide[${i}]: ${err}` });
|
|
116
|
-
}
|
|
117
|
-
validatedSlides.push({
|
|
118
|
-
type: s.type,
|
|
119
|
-
payload: s.payload,
|
|
120
|
-
...(s.title !== undefined ? { title: s.title } : {}),
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
startSlideshow(validatedSlides, body.delay_ms, workspace);
|
|
124
|
-
return c.json({ ok: true });
|
|
125
|
-
});
|
|
126
|
-
app.post("/slideshow/stop", (c) => {
|
|
127
|
-
cancelSlideshow();
|
|
128
|
-
return c.json({ ok: true });
|
|
129
|
-
});
|
|
130
|
-
// ── Incremental step-frames builder (v0.8) ───────────────────────────────────
|
|
131
|
-
app.post("/step-frames/init", async (c) => {
|
|
132
|
-
const body = await c.req.json();
|
|
133
|
-
if (typeof body.frame_type !== "string" || !FRAME_TYPES.includes(body.frame_type)) {
|
|
134
|
-
return c.json({
|
|
135
|
-
ok: false,
|
|
136
|
-
error: `frame_type must be one of: ${FRAME_TYPES.join(", ")}`,
|
|
137
|
-
}, 400);
|
|
138
|
-
}
|
|
139
|
-
const workspaceResult = validateWorkspaceInput(body.workspace);
|
|
140
|
-
if (!workspaceResult.ok) {
|
|
141
|
-
return c.json({ ok: false, error: workspaceResult.error }, 400);
|
|
142
|
-
}
|
|
143
|
-
const { workspace } = workspaceResult;
|
|
144
|
-
const title = typeof body.title === "string" ? body.title : undefined;
|
|
145
|
-
const { id } = initStepFramesResult(body.frame_type, workspace, title);
|
|
146
|
-
return c.json({ ok: true, id });
|
|
147
|
-
});
|
|
148
|
-
app.post("/step-frames/:id/frame", async (c) => {
|
|
149
|
-
const id = c.req.param("id");
|
|
150
|
-
const body = await c.req.json();
|
|
151
|
-
if (typeof body.payload !== "string") {
|
|
152
|
-
return c.json({ ok: false, error: "payload must be a string" }, 400);
|
|
153
|
-
}
|
|
154
|
-
const label = typeof body.label === "string" ? body.label : undefined;
|
|
155
|
-
const type = typeof body.type === "string" ? body.type : undefined;
|
|
156
|
-
const result = await appendFrameAndBroadcast(id, body.payload, label, type);
|
|
157
|
-
if (!result.ok) {
|
|
158
|
-
return c.json(result, result.error.includes("not found or expired") ? 404 : 400);
|
|
159
|
-
}
|
|
160
|
-
return c.json({ ok: true, frame_count: result.frame_count });
|
|
161
|
-
});
|
|
162
|
-
app.post("/step-frames/:id/commit", async (c) => {
|
|
163
|
-
const id = c.req.param("id");
|
|
164
|
-
let nodeToFrame;
|
|
165
|
-
try {
|
|
166
|
-
const body = await c.req.json();
|
|
167
|
-
if (body.node_to_frame !== undefined) {
|
|
168
|
-
const parsed = nodeToFrameSchema.safeParse(body.node_to_frame);
|
|
169
|
-
if (!parsed.success) {
|
|
170
|
-
return c.json({ ok: false, error: "node_to_frame must be a map of node ID → frame index" }, 400);
|
|
171
|
-
}
|
|
172
|
-
nodeToFrame = parsed.data;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
catch {
|
|
176
|
-
// No body or non-JSON body — commit with no node_to_frame.
|
|
177
|
-
}
|
|
178
|
-
const result = commitStepFramesResult(id, nodeToFrame);
|
|
179
|
-
if (!result.ok) {
|
|
180
|
-
return c.json(result, result.error.includes("not found or expired") ? 404 : 400);
|
|
181
|
-
}
|
|
182
|
-
return c.json(result);
|
|
183
|
-
});
|
|
184
|
-
// ── User events — bidirectionality (Sprint 10 experiment) ───────────────────
|
|
185
|
-
app.post("/user-done", async (c) => {
|
|
186
|
-
signalDone(); // wake any pending wait_done() MCP tool calls
|
|
187
|
-
// Also forward to channel relay if Claude Code was started with the channels flag.
|
|
188
|
-
const channelPort = Number(process.env.CHANNEL_PORT ?? 3001);
|
|
189
|
-
try {
|
|
190
|
-
await fetch(`http://127.0.0.1:${channelPort}/user-done`, { method: "POST" });
|
|
191
|
-
}
|
|
192
|
-
catch {
|
|
193
|
-
// Channel server not running — ignore.
|
|
194
|
-
}
|
|
195
|
-
return c.json({ ok: true });
|
|
196
|
-
});
|
|
197
|
-
app.post("/wait-done", async (c) => {
|
|
198
|
-
await waitForDone();
|
|
199
|
-
return c.json({ ok: true });
|
|
200
|
-
});
|
|
201
|
-
// ── Node / edge click events (Phase 2 — Sprint 12) ───────────────────────────
|
|
202
|
-
app.post("/node-click", async (c) => {
|
|
203
|
-
const body = await c.req.json();
|
|
204
|
-
if (body.type !== "node" && body.type !== "edge") {
|
|
205
|
-
return c.json({ ok: false, error: 'type must be "node" or "edge"' }, 400);
|
|
206
|
-
}
|
|
207
|
-
const event = {
|
|
208
|
-
type: body.type,
|
|
209
|
-
id: body.id ?? "",
|
|
210
|
-
label: body.label ?? "",
|
|
211
|
-
action: body.action ?? null,
|
|
212
|
-
};
|
|
213
|
-
signalClick(event); // no-op if no wait_click() is pending
|
|
214
|
-
return c.json({ ok: true });
|
|
215
|
-
});
|
|
216
|
-
app.post("/wait-click", async (c) => {
|
|
217
|
-
let nodeActions = {};
|
|
218
|
-
try {
|
|
219
|
-
const body = await c.req.json();
|
|
220
|
-
if (body.node_actions !== undefined) {
|
|
221
|
-
const parsed = nodeActionsSchema.safeParse(body.node_actions);
|
|
222
|
-
if (!parsed.success) {
|
|
223
|
-
return c.json({ ok: false, error: "node_actions must be a map of node ID → string[]" }, 400);
|
|
224
|
-
}
|
|
225
|
-
nodeActions = parsed.data;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
catch {
|
|
229
|
-
// No body or non-JSON body — treat as plain click (node_actions stays {}).
|
|
230
|
-
}
|
|
231
|
-
broadcast({ action: "set_node_actions", node_actions: nodeActions, enabled: true });
|
|
232
|
-
const event = await waitForClick();
|
|
233
|
-
broadcast({ action: "set_node_actions", enabled: false });
|
|
234
|
-
return c.json({ ok: true, ...event });
|
|
235
|
-
});
|
|
236
|
-
app.get("/export", (c) => {
|
|
237
|
-
const id = c.req.query("id");
|
|
238
|
-
if (id !== undefined && id !== "") {
|
|
239
|
-
const root = getSnapshotsRoot();
|
|
240
|
-
const payload = findSnapshotById(id, root);
|
|
241
|
-
if (payload === null) {
|
|
242
|
-
return c.json({ ok: false, error: "graph not found" }, 404);
|
|
243
|
-
}
|
|
244
|
-
return c.json({ ok: true, data: payload });
|
|
245
|
-
}
|
|
246
|
-
return c.json({ ok: true, data: exportCanvas() });
|
|
247
|
-
});
|
|
248
|
-
// ── History navigator (v0.4 — Sprint 17) ──────────────────────────────────────
|
|
249
|
-
app.get("/snapshots", (c) => {
|
|
250
|
-
// Workspace is mandatory, no lastWorkspace fallback — matches MCP's
|
|
251
|
-
// list_snapshots exactly (F3/NF20; same validateWorkspaceInput() both
|
|
252
|
-
// transports already use for render()/slideshow()).
|
|
253
|
-
const workspaceResult = validateWorkspaceInput(c.req.query("workspace"));
|
|
254
|
-
if (!workspaceResult.ok) {
|
|
255
|
-
return c.json({ ok: false, error: workspaceResult.error }, 400);
|
|
256
|
-
}
|
|
257
|
-
const { workspace } = workspaceResult;
|
|
258
|
-
const root = getSnapshotsRoot();
|
|
259
|
-
const snapshots = listSnapshots(workspace, root);
|
|
260
|
-
return c.json({ ok: true, snapshots });
|
|
261
|
-
});
|
|
262
|
-
// ── Sprint 18 — GET /snapshots/all (v0.5) ────────────────────────────────────
|
|
263
|
-
app.get("/snapshots/all", (c) => {
|
|
264
|
-
const workspace = getLastWorkspace();
|
|
265
|
-
const root = getSnapshotsRoot();
|
|
266
|
-
const workspaces = listAllSnapshots(root, workspace);
|
|
267
|
-
return c.json({ ok: true, workspaces });
|
|
268
|
-
});
|
|
269
|
-
app.post("/snapshots/load", async (c) => {
|
|
270
|
-
const body = await c.req.json();
|
|
271
|
-
const filename = body.filename;
|
|
272
|
-
if (typeof filename !== "string") {
|
|
273
|
-
return c.json({ ok: false, error: "filename must be a string" }, 400);
|
|
274
|
-
}
|
|
275
|
-
// Path safety: filename must end with _screen.json and contain no / or ..
|
|
276
|
-
if (!isValidSnapshotFilename(filename)) {
|
|
277
|
-
return c.json({ ok: false, error: "invalid filename: path traversal not allowed" });
|
|
278
|
-
}
|
|
279
|
-
const currentWorkspace = getLastWorkspace();
|
|
280
|
-
const root = getSnapshotsRoot();
|
|
281
|
-
// Optional workspace override (v0.5 cross-workspace load).
|
|
282
|
-
let workspace;
|
|
283
|
-
if (body.workspace !== undefined) {
|
|
284
|
-
const validated = validateWorkspaceInput(body.workspace);
|
|
285
|
-
if (!validated.ok) {
|
|
286
|
-
return c.json({ ok: false, error: "invalid workspace: path traversal not allowed" }, 400);
|
|
287
|
-
}
|
|
288
|
-
workspace = validated.workspace;
|
|
289
|
-
}
|
|
290
|
-
else {
|
|
291
|
-
workspace = currentWorkspace;
|
|
292
|
-
}
|
|
293
|
-
const raw = loadSnapshotContent(workspace, root, filename);
|
|
294
|
-
if (raw === null) {
|
|
295
|
-
return c.json({ ok: false, error: `snapshot not found: ${filename}` });
|
|
296
|
-
}
|
|
297
|
-
let snapshot;
|
|
298
|
-
try {
|
|
299
|
-
snapshot = JSON.parse(raw);
|
|
300
|
-
}
|
|
301
|
-
catch {
|
|
302
|
-
return c.json({ ok: false, error: "snapshot file is malformed JSON" });
|
|
303
|
-
}
|
|
304
|
-
if (!isFrameArray(snapshot.frames)) {
|
|
305
|
-
return c.json({ ok: false, error: "snapshot file is missing required fields" });
|
|
306
|
-
}
|
|
307
|
-
const frames = snapshot.frames;
|
|
308
|
-
const title = typeof snapshot.title === "string" ? snapshot.title : undefined;
|
|
309
|
-
const nodeToFrame = snapshot.nodeToFrame !== null && typeof snapshot.nodeToFrame === "object"
|
|
310
|
-
? snapshot.nodeToFrame
|
|
311
|
-
: undefined;
|
|
312
|
-
// Pre-v0.11 snapshots may lack an id (J1, `02`) — not addressable by the
|
|
313
|
-
// viewport cache; the browser falls back to treating it as unseen (auto-fit).
|
|
314
|
-
const snapshotId = typeof snapshot.id === "string" ? snapshot.id : undefined;
|
|
315
|
-
const rawPayload = typeof snapshot.rawPayload === "string" ? snapshot.rawPayload : undefined;
|
|
316
|
-
const result = await applyLoadedSnapshotResult(frames, workspace, title, nodeToFrame, snapshotId, rawPayload);
|
|
317
|
-
if (!result.ok) {
|
|
318
|
-
return c.json({ ok: false, error: result.error });
|
|
319
|
-
}
|
|
320
|
-
return c.json({ ok: true });
|
|
321
|
-
});
|
|
322
|
-
// ── Mermaid viewport persistence (v0.19, F19/C3) ────────────────────────────
|
|
323
|
-
app.post("/viewport", async (c) => {
|
|
324
|
-
const body = await c.req.json();
|
|
325
|
-
if (typeof body.id !== "string" || body.id.length === 0) {
|
|
326
|
-
return c.json({ ok: false, error: "id must be a non-empty string" }, 400);
|
|
327
|
-
}
|
|
328
|
-
// frame (v0.26.1, bug B19/FR21): the cache key is now id:frameIndex, so each
|
|
329
|
-
// frame of a sequence persists its own manual viewport independently.
|
|
330
|
-
if (typeof body.frame !== "number" || !Number.isInteger(body.frame) || body.frame < 0) {
|
|
331
|
-
return c.json({ ok: false, error: "frame must be a non-negative integer" }, 400);
|
|
332
|
-
}
|
|
333
|
-
const { scale, positionX, positionY } = body;
|
|
334
|
-
if (typeof scale !== "number" || !Number.isFinite(scale)) {
|
|
335
|
-
return c.json({ ok: false, error: "scale must be a finite number" }, 400);
|
|
336
|
-
}
|
|
337
|
-
if (typeof positionX !== "number" || !Number.isFinite(positionX)) {
|
|
338
|
-
return c.json({ ok: false, error: "positionX must be a finite number" }, 400);
|
|
339
|
-
}
|
|
340
|
-
if (typeof positionY !== "number" || !Number.isFinite(positionY)) {
|
|
341
|
-
return c.json({ ok: false, error: "positionY must be a finite number" }, 400);
|
|
342
|
-
}
|
|
343
|
-
const viewport = { scale, positionX, positionY };
|
|
344
|
-
setViewport(body.id, body.frame, viewport);
|
|
345
|
-
return c.json({ ok: true });
|
|
346
|
-
});
|
|
347
|
-
// ── Snapshot delete endpoints (v0.12) ─────────────────────────────────────
|
|
348
|
-
app.post("/snapshots/delete-files", async (c) => {
|
|
349
|
-
const body = await c.req.json();
|
|
350
|
-
const root = getSnapshotsRoot();
|
|
351
|
-
const validated = validateWorkspaceForDelete(body.workspace, root);
|
|
352
|
-
if (!validated.ok) {
|
|
353
|
-
return c.json({ ok: false, error: validated.error }, validated.status);
|
|
354
|
-
}
|
|
355
|
-
const { workspace } = validated;
|
|
356
|
-
if (!Array.isArray(body.filenames) || body.filenames.length === 0) {
|
|
357
|
-
return c.json({ ok: false, error: "filenames must be a non-empty array" }, 400);
|
|
358
|
-
}
|
|
359
|
-
const filenames = body.filenames;
|
|
360
|
-
for (const f of filenames) {
|
|
361
|
-
if (typeof f !== "string") {
|
|
362
|
-
return c.json({ ok: false, error: "each filename must be a string" }, 400);
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
const result = deleteSnapshotFiles(workspace, root, filenames);
|
|
366
|
-
if (!result.ok) {
|
|
367
|
-
return c.json({ ok: false, error: result.error }, 400);
|
|
368
|
-
}
|
|
369
|
-
return c.json({ ok: true, deleted: result.deleted });
|
|
370
|
-
});
|
|
371
|
-
app.post("/snapshots/delete-workspace", async (c) => {
|
|
372
|
-
const body = await c.req.json();
|
|
373
|
-
const root = getSnapshotsRoot();
|
|
374
|
-
const validated = validateWorkspaceForDelete(body.workspace, root);
|
|
375
|
-
if (!validated.ok) {
|
|
376
|
-
return c.json({ ok: false, error: validated.error }, validated.status);
|
|
377
|
-
}
|
|
378
|
-
const { workspace } = validated;
|
|
379
|
-
deleteWorkspace(workspace, root);
|
|
380
|
-
if (getLastWorkspace() === workspace) {
|
|
381
|
-
setLastWorkspace("");
|
|
382
|
-
}
|
|
383
|
-
return c.json({ ok: true });
|
|
384
|
-
});
|
|
385
|
-
// ── HTML Export (v0.13) ────────────────────────────────────────────────────
|
|
386
|
-
app.post("/export-html", async (c) => {
|
|
387
|
-
const body = await c.req.json();
|
|
388
|
-
if (!Array.isArray(body.items) || body.items.length === 0) {
|
|
389
|
-
return c.json({ ok: false, error: "items must be a non-empty array" }, 400);
|
|
390
|
-
}
|
|
391
|
-
// Default cdn (v0.32, F23): offline (fully embedded, today's pre-v0.32
|
|
392
|
-
// behavior) is opt-in via mode: "offline"; any other value falls back to cdn.
|
|
393
|
-
const mode = body.mode === "offline" ? "offline" : "cdn";
|
|
394
|
-
const root = getSnapshotsRoot();
|
|
395
|
-
const validItems = [];
|
|
396
|
-
for (const item of body.items) {
|
|
397
|
-
if (typeof item !== "object" || item === null)
|
|
398
|
-
continue;
|
|
399
|
-
const { workspace, id } = item;
|
|
400
|
-
if (typeof workspace !== "string")
|
|
401
|
-
continue;
|
|
402
|
-
const validated = validateWorkspaceInput(workspace);
|
|
403
|
-
if (!validated.ok)
|
|
404
|
-
continue;
|
|
405
|
-
if (typeof id !== "string")
|
|
406
|
-
continue;
|
|
407
|
-
const record = findSnapshotByIdInWorkspace(validated.workspace, id, root);
|
|
408
|
-
if (record === null)
|
|
409
|
-
continue;
|
|
410
|
-
validItems.push({ workspace: validated.workspace, id, record });
|
|
411
|
-
}
|
|
412
|
-
if (validItems.length === 0) {
|
|
413
|
-
return c.json({ ok: false, error: "no valid items to export" }, 400);
|
|
414
|
-
}
|
|
415
|
-
const { html, downloadFilename } = await generateExportHtml(validItems, mode);
|
|
416
|
-
return new Response(html, {
|
|
417
|
-
status: 200,
|
|
418
|
-
headers: {
|
|
419
|
-
"Content-Type": "text/html; charset=utf-8",
|
|
420
|
-
"Content-Disposition": `attachment; filename="${downloadFilename}"`,
|
|
421
|
-
},
|
|
422
|
-
});
|
|
423
|
-
});
|
|
40
|
+
// /import (NF55) enforces its own larger, route-specific limit inside
|
|
41
|
+
// registerImportRoutes() — excluded here so the two caps don't stack (a
|
|
42
|
+
// second, stricter bodyLimit later in the chain would otherwise still
|
|
43
|
+
// reject anything over MAX_BODY_SIZE_BYTES regardless of the route's own
|
|
44
|
+
// override).
|
|
45
|
+
app.use("*", async (c, next) => {
|
|
46
|
+
if (c.req.path === "/import")
|
|
47
|
+
return next();
|
|
48
|
+
return bodyLimit({ maxSize: MAX_BODY_SIZE_BYTES })(c, next);
|
|
49
|
+
});
|
|
50
|
+
registerRenderRoutes(app);
|
|
51
|
+
registerSlideshowRoutes(app);
|
|
52
|
+
registerSnapshotRoutes(app);
|
|
53
|
+
registerExportRoutes(app);
|
|
54
|
+
registerImportRoutes(app);
|
|
55
|
+
registerQuizRoutes(app);
|
|
424
56
|
// ── Static client (v1.0 — NF33) ──────────────────────────────────────────
|
|
425
57
|
// Mounted last so it never shadows an API route above; only serves GET
|
|
426
58
|
// requests that didn't match anything else (assets, and "/" -> index.html).
|
package/dist/server/channel.js
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
9
9
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
10
10
|
import { createServer } from 'node:http';
|
|
11
|
-
|
|
11
|
+
import { parsePort } from './port.js';
|
|
12
|
+
const CHANNEL_PORT = parsePort(process.env.CHANNEL_PORT, 3001, 'CHANNEL_PORT');
|
|
12
13
|
const mcp = new Server({ name: 'agent-whiteboard-channel', version: '0.1.0' }, {
|
|
13
14
|
capabilities: {
|
|
14
15
|
// Declares this server as a Claude Code channel.
|
|
@@ -20,7 +21,6 @@ await mcp.connect(new StdioServerTransport());
|
|
|
20
21
|
// Tiny HTTP relay: main server POSTs here when the browser fires a user event.
|
|
21
22
|
const relay = createServer((req, res) => {
|
|
22
23
|
if (req.method === 'POST' && req.url === '/user-done') {
|
|
23
|
-
// notifications/claude/channel is a Claude-proprietary extension not in the MCP schema.
|
|
24
24
|
;
|
|
25
25
|
mcp.notification({
|
|
26
26
|
method: 'notifications/claude/channel',
|
|
@@ -28,7 +28,9 @@ const relay = createServer((req, res) => {
|
|
|
28
28
|
content: 'User has finished exploring the whiteboard and is ready for you to continue.',
|
|
29
29
|
meta: { event: 'user_done' },
|
|
30
30
|
},
|
|
31
|
-
}).catch(() => {
|
|
31
|
+
}).catch((err) => {
|
|
32
|
+
console.error('[agent-whiteboard-channel] notification failed:', err);
|
|
33
|
+
});
|
|
32
34
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
33
35
|
res.end(JSON.stringify({ ok: true }));
|
|
34
36
|
}
|