@ryan_nookpi/pi-skill-excalidraw 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +25 -0
- package/package.json +44 -0
- package/skills/excalidraw/SKILL.md +58 -0
- package/skills/excalidraw/app/dist/assets/Assistant-Bold-gm-uSS1B.woff2 +0 -0
- package/skills/excalidraw/app/dist/assets/Assistant-Medium-DrcxCXg3.woff2 +0 -0
- package/skills/excalidraw/app/dist/assets/Assistant-Regular-DVxZuzxb.woff2 +0 -0
- package/skills/excalidraw/app/dist/assets/Assistant-SemiBold-SCI4bEL9.woff2 +0 -0
- package/skills/excalidraw/app/dist/assets/abnfDiagram-VCTEODGH-Y56Pk8sn.js +1 -0
- package/skills/excalidraw/app/dist/assets/ar-SA-G6X2FPQ2-DatABGjX.js +10 -0
- package/skills/excalidraw/app/dist/assets/arc-DgcGdgmL.js +1 -0
- package/skills/excalidraw/app/dist/assets/architecture-7GRP2DOG-BECp2Zrk.js +1 -0
- package/skills/excalidraw/app/dist/assets/architectureDiagram-5GKGNRK7-BkBTZ8aU.js +36 -0
- package/skills/excalidraw/app/dist/assets/array-BifhSqXX.js +1 -0
- package/skills/excalidraw/app/dist/assets/az-AZ-76LH7QW2-WQrHOob7.js +1 -0
- package/skills/excalidraw/app/dist/assets/bg-BG-XCXSNQG7-BVvnFVRX.js +5 -0
- package/skills/excalidraw/app/dist/assets/blockDiagram-I7D4REHJ-D7KnLVtF.js +129 -0
- package/skills/excalidraw/app/dist/assets/bn-BD-2XOGV67Q-DzlalUE2.js +5 -0
- package/skills/excalidraw/app/dist/assets/c4Diagram-7LVT6UL2-nV-MvTJT.js +38 -0
- package/skills/excalidraw/app/dist/assets/ca-ES-6MX7JW3Y-ILmKOQy8.js +8 -0
- package/skills/excalidraw/app/dist/assets/channel-Ca-ODdO0.js +1 -0
- package/skills/excalidraw/app/dist/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- package/skills/excalidraw/app/dist/assets/chunk-4HAMMTFA-CZal2Pyz.js +62 -0
- package/skills/excalidraw/app/dist/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- package/skills/excalidraw/app/dist/assets/chunk-75Z2AOVW-DVqFChOg.js +2 -0
- package/skills/excalidraw/app/dist/assets/chunk-DU6HZSFF-BavxyZSY.js +127 -0
- package/skills/excalidraw/app/dist/assets/chunk-EIO257PC-LlbbXIq6.js +22 -0
- package/skills/excalidraw/app/dist/assets/chunk-F27PBJKO-BWDl5_Sz.js +1 -0
- package/skills/excalidraw/app/dist/assets/chunk-FOHPRMQF-DzxwRta7.js +161 -0
- package/skills/excalidraw/app/dist/assets/chunk-GMAD6QVW-Rjz_G1RQ.js +72 -0
- package/skills/excalidraw/app/dist/assets/chunk-GVQU2GXP-BjxGnl2S.js +1 -0
- package/skills/excalidraw/app/dist/assets/chunk-IMKFNOWR-BJ1FymPn.js +231 -0
- package/skills/excalidraw/app/dist/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- package/skills/excalidraw/app/dist/assets/chunk-L3NEJ4N5-sJejB3eG.js +1 -0
- package/skills/excalidraw/app/dist/assets/chunk-OSK3NFVY-DLz3HNrx.js +10 -0
- package/skills/excalidraw/app/dist/assets/chunk-P2QGCYS3-Dhy4aMJl.js +1 -0
- package/skills/excalidraw/app/dist/assets/chunk-POPQ4Y6H-DOEx_tr4.js +1 -0
- package/skills/excalidraw/app/dist/assets/chunk-PWAF6VOD-Bq0yNT01.js +1 -0
- package/skills/excalidraw/app/dist/assets/chunk-SHT3W25Y-CICAAbIL.js +168 -0
- package/skills/excalidraw/app/dist/assets/chunk-SVP7TREG-f6pYNHg0.js +88 -0
- package/skills/excalidraw/app/dist/assets/chunk-TICWLB2K-DdRa5lMo.js +206 -0
- package/skills/excalidraw/app/dist/assets/chunk-XXDRQBXY-BvKO0v-W.js +1 -0
- package/skills/excalidraw/app/dist/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- package/skills/excalidraw/app/dist/assets/classDiagram-ZZMXUADV-DCPVGkLh.js +1 -0
- package/skills/excalidraw/app/dist/assets/classDiagram-v2-VYDZK3BY-DCPVGkLh.js +1 -0
- package/skills/excalidraw/app/dist/assets/cose-bilkent-JH36ORCC-COXSdE6a.js +1 -0
- package/skills/excalidraw/app/dist/assets/cs-CZ-2BRQDIVT-tV1CvCxu.js +11 -0
- package/skills/excalidraw/app/dist/assets/cynefin-OW5HDTMX-D-XvS_F8.js +1 -0
- package/skills/excalidraw/app/dist/assets/cynefinDiagram-5FMLGOSQ-DWgEonYW.js +62 -0
- package/skills/excalidraw/app/dist/assets/cytoscape.esm-Yq6u8L66.js +321 -0
- package/skills/excalidraw/app/dist/assets/da-DK-5WZEPLOC-zceHT2GU.js +5 -0
- package/skills/excalidraw/app/dist/assets/dagre-C-rnJpZF.js +1 -0
- package/skills/excalidraw/app/dist/assets/dagre-GXQ25YYZ-d3UPf-z-.js +4 -0
- package/skills/excalidraw/app/dist/assets/de-DE-XR44H4JA-U1KbS0X3.js +8 -0
- package/skills/excalidraw/app/dist/assets/defaultLocale-BFoDCU3G.js +1 -0
- package/skills/excalidraw/app/dist/assets/diagram-S7CK7UJ4-CRc82Fb9.js +30 -0
- package/skills/excalidraw/app/dist/assets/diagram-UQ7AKVKN-CgfviMBL.js +41 -0
- package/skills/excalidraw/app/dist/assets/diagram-VSXAHHWV-Btexo3l8.js +3 -0
- package/skills/excalidraw/app/dist/assets/diagram-VX7I27RA-DoMnip1P.js +24 -0
- package/skills/excalidraw/app/dist/assets/diagram-Z3DM3KII-BTsxq82z.js +24 -0
- package/skills/excalidraw/app/dist/assets/directory-open-01563666-D4xXyWb_.js +1 -0
- package/skills/excalidraw/app/dist/assets/directory-open-4ed118d0-1i309Asm.js +1 -0
- package/skills/excalidraw/app/dist/assets/dist-B_J_HbC0.js +1 -0
- package/skills/excalidraw/app/dist/assets/dist-DVyo1T_H.js +62 -0
- package/skills/excalidraw/app/dist/assets/ebnfDiagram-PWID7BFC-BYsNxk9n.js +1 -0
- package/skills/excalidraw/app/dist/assets/el-GR-BZB4AONW-CgSV8rfE.js +10 -0
- package/skills/excalidraw/app/dist/assets/en-B4ZKOASM-Byd7DbO_.js +1 -0
- package/skills/excalidraw/app/dist/assets/erDiagram-RLTQ6QDP-LkewsTFZ.js +99 -0
- package/skills/excalidraw/app/dist/assets/es-ES-U4NZUMDT-d42UjG1W.js +9 -0
- package/skills/excalidraw/app/dist/assets/eu-ES-A7QVB2H4-CeMeFdnp.js +11 -0
- package/skills/excalidraw/app/dist/assets/eventmodeling-NTZA5JFV-160-dgiE.js +1 -0
- package/skills/excalidraw/app/dist/assets/fa-IR-HGAKTJCU-CVXIrtPl.js +8 -0
- package/skills/excalidraw/app/dist/assets/fi-FI-Z5N7JZ37-DIW6dubX.js +6 -0
- package/skills/excalidraw/app/dist/assets/file-open-002ab408-BHUWm0Sh.js +1 -0
- package/skills/excalidraw/app/dist/assets/file-open-7c801643-DZtJT5zp.js +1 -0
- package/skills/excalidraw/app/dist/assets/file-save-3189631c-CO9S4HFW.js +1 -0
- package/skills/excalidraw/app/dist/assets/file-save-745eba88-Bwdfz6OZ.js +1 -0
- package/skills/excalidraw/app/dist/assets/flowDiagram-HODETNUW-XE0UaaJt.js +1 -0
- package/skills/excalidraw/app/dist/assets/fr-FR-RHASNOE6-EPyEt_4g.js +9 -0
- package/skills/excalidraw/app/dist/assets/ganttDiagram-EL5Y4UJY-DuJaTNOL.js +292 -0
- package/skills/excalidraw/app/dist/assets/gitGraph-4MIJSDKK-DHGj5WCj.js +1 -0
- package/skills/excalidraw/app/dist/assets/gitGraphDiagram-WWUBYQGX-DdvnVTzU.js +106 -0
- package/skills/excalidraw/app/dist/assets/gl-ES-HMX3MZ6V-Cbr9hGRI.js +10 -0
- package/skills/excalidraw/app/dist/assets/graphlib-DS17s2tU.js +1 -0
- package/skills/excalidraw/app/dist/assets/he-IL-6SHJWFNN-B5Iboi8a.js +10 -0
- package/skills/excalidraw/app/dist/assets/hi-IN-IWLTKZ5I-k6swWOWn.js +4 -0
- package/skills/excalidraw/app/dist/assets/hu-HU-A5ZG7DT2-DaDlVvTE.js +7 -0
- package/skills/excalidraw/app/dist/assets/id-ID-SAP4L64H-DiV3qfW7.js +10 -0
- package/skills/excalidraw/app/dist/assets/image-GAAHSSAO-stUGVFAH.js +1 -0
- package/skills/excalidraw/app/dist/assets/image-blob-reduce.esm-BFq-Mx5V.js +2 -0
- package/skills/excalidraw/app/dist/assets/index-ChSm4O-k.js +208 -0
- package/skills/excalidraw/app/dist/assets/index-DtRVLazd.css +1 -0
- package/skills/excalidraw/app/dist/assets/info-A6RAGUB7-EjytcsrH.js +1 -0
- package/skills/excalidraw/app/dist/assets/infoDiagram-27XIBGKW-D5p952K8.js +2 -0
- package/skills/excalidraw/app/dist/assets/init-C-OQMol4.js +1 -0
- package/skills/excalidraw/app/dist/assets/ishikawaDiagram-5VMMS53U-Cl9GrB8p.js +70 -0
- package/skills/excalidraw/app/dist/assets/it-IT-JPQ66NNP-B3YDn8c7.js +11 -0
- package/skills/excalidraw/app/dist/assets/ja-JP-DBVTYXUO-r8GJRlz8.js +8 -0
- package/skills/excalidraw/app/dist/assets/journeyDiagram-3NMN7TZE-DPL61tuu.js +139 -0
- package/skills/excalidraw/app/dist/assets/kaa-6HZHGXH3-CQXO0smT.js +1 -0
- package/skills/excalidraw/app/dist/assets/kab-KAB-ZGHBKWFO-CcnpslfP.js +8 -0
- package/skills/excalidraw/app/dist/assets/kanban-definition-UXKFOSKX-CrEwB5Tt.js +89 -0
- package/skills/excalidraw/app/dist/assets/katex-ZlcWpGUi.js +257 -0
- package/skills/excalidraw/app/dist/assets/kk-KZ-P5N5QNE5-DRBBwSLY.js +1 -0
- package/skills/excalidraw/app/dist/assets/km-KH-HSX4SM5Z-aDqmSt43.js +11 -0
- package/skills/excalidraw/app/dist/assets/ko-KR-MTYHY66A-CrTedvVS.js +9 -0
- package/skills/excalidraw/app/dist/assets/ku-TR-6OUDTVRD-hNhm9YQ0.js +9 -0
- package/skills/excalidraw/app/dist/assets/line-C4N-NEvZ.js +1 -0
- package/skills/excalidraw/app/dist/assets/linear-BUnzfXgk.js +1 -0
- package/skills/excalidraw/app/dist/assets/lt-LT-XHIRWOB4-HeBwh7CL.js +3 -0
- package/skills/excalidraw/app/dist/assets/lv-LV-5QDEKY6T-DXU4B6YW.js +7 -0
- package/skills/excalidraw/app/dist/assets/mermaid-parser.core-g7vsDY1V.js +7 -0
- package/skills/excalidraw/app/dist/assets/mindmap-definition-YA3MSWOX-D__pf1Yg.js +96 -0
- package/skills/excalidraw/app/dist/assets/mr-IN-CRQNXWMA-BYsXnQkb.js +13 -0
- package/skills/excalidraw/app/dist/assets/my-MM-5M5IBNSE-C871ZDtQ.js +1 -0
- package/skills/excalidraw/app/dist/assets/nb-NO-T6EIAALU-Cm-d6hjp.js +10 -0
- package/skills/excalidraw/app/dist/assets/nl-NL-IS3SIHDZ-XlSpYp1l.js +8 -0
- package/skills/excalidraw/app/dist/assets/nn-NO-6E72VCQL-BJPmp-_h.js +8 -0
- package/skills/excalidraw/app/dist/assets/oc-FR-POXYY2M6-D1rPi0z7.js +8 -0
- package/skills/excalidraw/app/dist/assets/ordinal-BDEzSJ7C.js +1 -0
- package/skills/excalidraw/app/dist/assets/pa-IN-N4M65BXN-hKsyWK74.js +4 -0
- package/skills/excalidraw/app/dist/assets/packet-AYTQ26CC-4PAjvWSX.js +1 -0
- package/skills/excalidraw/app/dist/assets/path-fybaL0A-.js +1 -0
- package/skills/excalidraw/app/dist/assets/pegDiagram-XKGWAZYB-CUfmvI5h.js +1 -0
- package/skills/excalidraw/app/dist/assets/percentages-BXMCSKIN-CfhMReVO.js +1 -0
- package/skills/excalidraw/app/dist/assets/pica-BPrp-GK1.js +2 -0
- package/skills/excalidraw/app/dist/assets/pie-WAS4IAKB-B5FgQybZ.js +1 -0
- package/skills/excalidraw/app/dist/assets/pieDiagram-E7YTZNPT-CU8w4Jjl.js +39 -0
- package/skills/excalidraw/app/dist/assets/pl-PL-T2D74RX3-DOodWdkP.js +9 -0
- package/skills/excalidraw/app/dist/assets/pt-BR-5N22H2LF-dyjRDPfa.js +9 -0
- package/skills/excalidraw/app/dist/assets/pt-PT-UZXXM6DQ-DXb9iBoj.js +9 -0
- package/skills/excalidraw/app/dist/assets/quadrantDiagram-AXDQQJYC-C60Jl0ho.js +7 -0
- package/skills/excalidraw/app/dist/assets/radar-RG4KPBEZ-Bb6LV2iq.js +1 -0
- package/skills/excalidraw/app/dist/assets/railroad-74A4TZTK-DYFjVugV.js +1 -0
- package/skills/excalidraw/app/dist/assets/railroad-abnf-HS5TGJTU-CCpAO9jj.js +1 -0
- package/skills/excalidraw/app/dist/assets/railroad-ebnf-LZEXJU2U-BTtgE2v0.js +1 -0
- package/skills/excalidraw/app/dist/assets/railroad-peg-WCYAUIDC-qT7-4WNw.js +1 -0
- package/skills/excalidraw/app/dist/assets/railroadDiagram-O6MQD6OU-D-Q-2PY3.js +1 -0
- package/skills/excalidraw/app/dist/assets/requirementDiagram-BXWQKSXE-DUJGchGn.js +84 -0
- package/skills/excalidraw/app/dist/assets/ro-RO-JPDTUUEW-D2t-SdK7.js +11 -0
- package/skills/excalidraw/app/dist/assets/rolldown-runtime-Dd_uD5pT.js +1 -0
- package/skills/excalidraw/app/dist/assets/rough.esm-Dy-Kn_BL.js +1 -0
- package/skills/excalidraw/app/dist/assets/roundRect-D01gJrlt.js +1 -0
- package/skills/excalidraw/app/dist/assets/ru-RU-B4JR7IUQ-B3zBvqM8.js +9 -0
- package/skills/excalidraw/app/dist/assets/sankeyDiagram-P5KCCOFB-B7gzsCzv.js +40 -0
- package/skills/excalidraw/app/dist/assets/sequenceDiagram-WJ2MYXX4-C1gETguU.js +162 -0
- package/skills/excalidraw/app/dist/assets/si-LK-N5RQ5JYF-x9atOM2o.js +1 -0
- package/skills/excalidraw/app/dist/assets/sizeCapture-INFHLROL-3uHXrFqA.js +1 -0
- package/skills/excalidraw/app/dist/assets/sk-SK-C5VTKIMK-Dc-U7HwG.js +6 -0
- package/skills/excalidraw/app/dist/assets/sl-SI-NN7IZMDC-DBErI-th.js +6 -0
- package/skills/excalidraw/app/dist/assets/src-oBChb5qS.js +1 -0
- package/skills/excalidraw/app/dist/assets/stateDiagram-D77RDMKH-ms90ttRw.js +1 -0
- package/skills/excalidraw/app/dist/assets/stateDiagram-v2-MP3YSRHH-BLT-8Bst.js +1 -0
- package/skills/excalidraw/app/dist/assets/subset-shared.chunk-JkuiVUYR.js +1 -0
- package/skills/excalidraw/app/dist/assets/subset-worker.chunk-BBqoITZT.js +1 -0
- package/skills/excalidraw/app/dist/assets/sv-SE-XGPEYMSR-DIhT7VhP.js +10 -0
- package/skills/excalidraw/app/dist/assets/swimlanes-42K2YHIH-C03UW4hY.js +1 -0
- package/skills/excalidraw/app/dist/assets/swimlanesDiagram-VR7AAH4N-OUQB4gXu.js +8 -0
- package/skills/excalidraw/app/dist/assets/ta-IN-2NMHFXQM-ollyGw17.js +9 -0
- package/skills/excalidraw/app/dist/assets/th-TH-HPSO5L25-GycTdvha.js +2 -0
- package/skills/excalidraw/app/dist/assets/timeline-definition-24CTP7MA-BWQ2CWiF.js +120 -0
- package/skills/excalidraw/app/dist/assets/tr-TR-DEFEU3FU-C0EQI1hS.js +7 -0
- package/skills/excalidraw/app/dist/assets/treeView-Q6P3EWNA-B4gjxheB.js +1 -0
- package/skills/excalidraw/app/dist/assets/treemap-WGGIJYW6-C6ZNbWbw.js +1 -0
- package/skills/excalidraw/app/dist/assets/uk-UA-QMV73CPH--gALSA3R.js +6 -0
- package/skills/excalidraw/app/dist/assets/vennDiagram-4TSXK5OY-DB2q0NWm.js +34 -0
- package/skills/excalidraw/app/dist/assets/vi-VN-M7AON7JQ-BU-don7N.js +5 -0
- package/skills/excalidraw/app/dist/assets/wardley-WFR3VGLG-CMlUPGFV.js +1 -0
- package/skills/excalidraw/app/dist/assets/wardleyDiagram-VM6X3IG4-D7s4KunH.js +78 -0
- package/skills/excalidraw/app/dist/assets/xychartDiagram-S5SC5T6Z-C3Ka4xi8.js +7 -0
- package/skills/excalidraw/app/dist/assets/zh-CN-LNUGB5OW-D-2E446q.js +10 -0
- package/skills/excalidraw/app/dist/assets/zh-HK-E62DVLB3-cftaz5Rd.js +1 -0
- package/skills/excalidraw/app/dist/assets/zh-TW-RAJ6MFWO-BO55Yqh9.js +9 -0
- package/skills/excalidraw/app/dist/fonts/Assistant/Assistant-Bold.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Assistant/Assistant-Medium.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Assistant/Assistant-Regular.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Assistant/Assistant-SemiBold.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Cascadia/CascadiaCode-Regular.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/ComicShanns/ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/ComicShanns/ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/ComicShanns/ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/ComicShanns/ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Excalifont/Excalifont-Regular-349fac6ca4700ffec595a7150a0d1e1d.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Excalifont/Excalifont-Regular-3f2c5db56cc93c5a6873b1361d730c16.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Excalifont/Excalifont-Regular-41b173a47b57366892116a575a43e2b6.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Excalifont/Excalifont-Regular-623ccf21b21ef6b3a0d87738f77eb071.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Excalifont/Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Excalifont/Excalifont-Regular-b9dcf9d2e50a1eaf42fc664b50a3fd0d.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Excalifont/Excalifont-Regular-be310b9bcd4f1a43f571c46df7809174.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Liberation/LiberationSans-Regular.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYE98RXi4EwSsbg.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYEF8RXi4EwQ.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTA3j6zbXWjgevT5.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTQ3j6zbXWjgeg.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTk3j6zbXWjgevT5.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTo3j6zbXWjgevT5.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTs3j6zbXWjgevT5.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Virgil/Virgil-Regular.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-019d66dcad46dc156b162d267f981c20.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-04b718e5623574919c8b0dea5f301444.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-069e77aac84590e2e991d0a0176d34f2.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-06c77b8c66e51ed6c63ccb502dd8b8af.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-08e0dc436ad0ad61ba5558db0674d762.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-093b9ef39a46ceae95a1df18a0a3a326.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-095c169f3314805276f603a362766abd.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-09850c4077f3fffe707905872e0e2460.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-0986d134c05864f5025962eef9f994a0.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-0b5d723fdc4e249c140f0909e87d03b4.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-0f626226ba1272e832aea87bafd9720e.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-0f7fb1e0d5015bb1371343153ecf7ce3.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-0fa55a080fcd0f9dc2e0b0058b793df8.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-0facdf1ea213ba40261022f5d5ed4493.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-10a7ae9a371830a80c3d844acf1c02d7.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-112c051027b2d766c19a519f6ee1f4f7.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-11c345711937f0ba4b8f7b6b919c8440.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-12b52b58eb3df36804b9a654ec9ee194.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-13ae07ed2e272d26d59bc0691cd7117a.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-13d2887ec8ee73c43acdabc52a05af7b.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-145aa02cdd91946e67dc934e1acffe75.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-15dc6d811c9cd078f9086a740d5a1038.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-173945821411c09f70c95f98d590e697.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-1b611157cd46bb184d4fa4dae2d6a2b8.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-1e6fd68f1f3902ce48ce8c69df385622.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-1ee544f0f1dac422545c505baa788992.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-1fdc0c67ed57263a80fd108c1f6ccf24.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-203b0e569e3b14aac86a003dc3fa523e.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-20cc1bbf50e7efb442756cb605672c1f.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-20e7bf72fa05de9adf7dbcc7bf51dde6.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-21430ee05a1248901da8d0de08744d47.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-23686f7f29da6e8008c36dd3a80c83d6.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-23ad2d71b280f00b1363b95b7bea94eb.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-23f228f3999c01983860012330e4be08.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-24476a126f129212beb33f66853ea151.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-24a21c1e4449222e8d1898d69ff3a404.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-25b7f38e18f035f96cb5e547bd2bd08c.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-29cec36cd205b211da97acabaa62f055.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-2a26d20a23b00898ce82f09d2ee47c3f.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-2adbc89c11e65905393d3dfc468b9d5b.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-2b7441d46298788ac94e610ffcc709b6.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-2b77e8ebfb2367ab2662396a60e7d320.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-2cf96d082d35ea3d8106851223ad0d16.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-2d43040e86ff03ba677f6f9c04cd0805.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-2e33e8dc771ef5e1d9127d60a6b73679.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-33432927cd87d40cfe393c7482bf221f.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-353f33792a8f60dc69323ddf635a269e.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-36925dfe329a45086cbb7fc5c20d45ac.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-3717077e38f98d89eae729b6c14e56dc.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-3756e81d3e149cf6099163ee79944fec.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-395c35dd584b56b0789f58a0559beaf1.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-3c9de2ae0ea4bc91a510942dfa4be8d2.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-3cc70dbb64df5b21f1326cc24dee2195.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-3e1f8f654357353bf0e04ba5c34b5f7f.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-3e63ed8162808a9e425ed80a8bc79114.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-3eaa538115d76932653c21d8dc28f207.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4095eb84ef3874e2600247bee0b04026.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-41521fade99856108931b4768b1b2648.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-450da755d5bcb70906e1295e559b9602.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-452225341522a7942f0f6aab1a5c91a3.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4535823663ad81405188a528d8f2b1a2.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4806e761d750087c2d734fc64596eaff.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4a0fdb40036e87b40aa08dd30584cb85.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4a38cc3e9cf104e69ba246d37f8cf135.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4aca6a43e59aceee2166b0c7e4e85ef1.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4bfaa8ffa64c5ee560aa2daba7c9cbd3.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4dc6d5f188d5c96d44815cd1e81aa885.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4ddc14ed3eb0c3e46364317dfc0144a3.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4ee10ae43505e2e0bc62656ced49c0fa.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4f50e5136e136527280bc902c5817561.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-51502f1206be09c565f1547c406e9558.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-51a0e808bbc8361236ac521a119758a3.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-52a84a22fd1369bffeaf21da2d6158dc.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-5330a2119a716e4e7224ed108b085dac.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-543fa46ace099a7099dad69123399400.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-544fc28abe2c5c30e62383fd4dac255f.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-54acdfc2166ad7fcbd074f75fd4a56ba.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-5572b3513ba8df57a3d5d7303ee6b11b.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-56467a5c8840c4d23a60b2f935114848.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-56a32a7689abd0326e57c10c6c069bb4.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-57862b464a55b18c7bf234ce22907d73.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-583d166e56ba0de4b77eabb47ef67839.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-5882ffa04f32584d26109137e2da4352.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-58fd02350d0bc52cf1ca3bb32ce9766e.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-5935a5775af3d5c6307ac667bd9ae74e.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-59e9ff77b0efaf684bc09274fb6908c9.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-5a1ce3117cfe90c48e8fb4a9a00f694d.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-5a45d991244d4c7140217e1e5f5ca4f4.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-5a7fac4b8b23a6e4e5ba0c9bf1756c91.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-5b0ed6971aaab9c8ad563230bd5471a7.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-5d2898fbc097a7e24c6f38d80587621e.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-603aefd23e350ba7eb124273e3c9bcf1.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-60a3089806700d379f11827ee9843b6b.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-60a41c7e1c68f22424e6d22df544bc82.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-642b26e2e5f5fb780b51b593dbc8c851.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-66493ba5a8367f2928812f446f47b56a.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-670ba603758d94268e8606f240a42e12.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-671a2c20b1eb9e4ef8a192833940e319.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-684d65f1793cac449dde5d59cb3c47fb.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-69c09cc5fa3e55c74fc4821f76909cc3.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-6ae5b42180ad70b971c91e7eefb8eba2.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-6e092f71c1e634059ada0e52abadce67.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-6f3256af8454371776bc46670d33cc65.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-6fe5c5973cc06f74b2387a631ea36b88.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-70c2eb8d64e71a42a834eb857ea9df51.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-70e811fd7994e61f408c923de6ddd078.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-7197d6fda6cba7c3874c53d6381ca239.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-72252d73220fa3cd856677888cee1635.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-72536a3d71b694a0d53dd90ddceae41e.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-726303e0774b4e678bff8c2deb6ca603.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-733171b4ffcd17ea1fe1c0ba627173bf.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-739bc1a567439c7cffcd1614644593d2.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-73e309718fd16cea44b4d54a33581811.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-7494dc504ae00ee9cd0505f990f88c5d.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-74e2263a91439c25b91d5132ce9f4d62.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-761d05e3cd968cf574166867998ef06a.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-7718fe60986d8b42b1be9c5ace5ccf25.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-774d4f764a1299da5d28ec2f2ffe0d69.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-79d494361ae093b69e74ee9dbe65bfd4.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-79f007c1c6d07557120982951ea67998.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-7a07ddc0f0c0f5f4a9bad6ee3dda66b5.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-7ab2bed91166a9dca83a5ebfbe2a7f38.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-7ccce86603f80a099ddb0cb21d4ae3e3.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-7e4bde7e9c7f84cd34d8a845e384c746.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-7e929f262f30c8ee78bf398150b1a7cd.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-7eb9fffd1aa890d07d0f88cc82e6cfe4.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-7f855356ab893b0d2b9c1c83b8116f0e.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-829615148e6357d826b9242eb7fbbd1e.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-866fa7613df6b3fd272bcfd4530c0bb9.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-87599f94b6cc129d505b375798d0d751.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-8c2f33cee3993174f7e87c28e4bf42ee.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-8d3bcabb847b56243b16afe62adaaf21.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-8de5b863cb50dfefdd07cb11c774d579.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-8e9f97f01034820170065b2921b4fb5e.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-8f476c4c99813d57cbe6eca4727388ad.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-903bb6865f3452e2fda42e3a25547bc5.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-91ddb2969bf2d31ba02ad82998d1314c.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-938d90c10ff8c20386af7f242c05d6b0.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-93fc8f28a33234bcadf1527cafabd502.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-95429962233afd82db1c27df1500a28c.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-9544732d2e62d1a429674f8ee41b5d3a.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-9592bfc861f07bcb8d75c196b370e548.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-95bfd249da4902577b4b7d76ebdd0b44.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-968cffdc8ee679da094e77ebf50f58ef.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-97f7f48ce90c9429bf32ae51469db74d.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-982b630266d87db93d2539affb1275c6.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-98f2ad84457de7f3740d9920b8fa8667.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-99a16ef6a64934d5781933dbd9c46b2e.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-9cfb2a77a4e45025105ad29a1748b90d.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-9d81066dd2b337c938df6e90380a00dc.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-9eb5a99df4e76ac3363453ac9ca288b1.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-a004ddfcb26e67bd6e678c8ed19e25ce.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-a0ca5df4258213d7fc9fce80f65ce760.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-a1f916d6039285c4ffb900cd654e418f.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-a203b91dad570bf05a58c3c3ddb529bf.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-a365e82ed54697a52f27adcea1315fe8.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-a4c34be6d42152e64b0df90bc4607f64.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-a7accba310e821da5505f71c03b76bdb.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-aa0d470430e6391eca720c7cfa44446f.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-aa5c9ca6cf4fba00433b7aa3fa10671a.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-ac9ceb44437becc3e9c4dbfebab7fc2d.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-b1220a3c61f85cc0408deedb4c5f57a2.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-b358f7a51ece39a3247942b1feabdb29.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-b57aaedfd8ebdf3931f25119dc6a5eb2.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-b5c1596551c256e0e9cf02028595b092.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-b6d128682ee29e471486354d486a1b90.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-b6fd38ca30869792244804b04bc058da.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-b7d203b051eff504ff59ddca7576b6a9.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-b96d9226ce77ec94ceca043d712182e6.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-ba3de316d63c7e339987b16f41a0b879.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-bafff7a14c27403dcc6cf1432e8ea836.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-bd77e3c7f9e0b072d96af37f73d1aa32.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-be549ab72f0719d606a5c01e2c0219b6.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-c16ed9740b85badf16e86ea782a3062f.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-c1f94158256bb1f3bf665b053d895af9.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-c40533fdf4cc57177b12803598af7e59.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-c4a687ac4f0c2766eefc9f77ed99cddf.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-c69f61a4ab18d0488c8d1fc12e7028e8.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-c8b71798409ccc126ee264a00aadcf21.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-c99eda15fc26a2941579560f76c3a5cf.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-cb17fc3db95f6d139afc9d31a8e93293.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-cbaaefaaf326668277aa24dfa93c4d28.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-cd145ce4a0ea18469358df53c207bc1b.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-cdbce89e82cc1ab53a2decbf5819278f.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-ce4884f96f11589608b76b726a755803.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-cf2cc71752631e579e35b0e423bf2638.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-cf6ff4e0f491ca0cf3038187a997b9b4.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-cfb211578629b7e8153b37240de6a9d5.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-d0cf73942fea1c74edbdf0b3011f4656.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-d2666cbed13462c5dc36fa2f15c202ca.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-d3716376641d615e2995605b29bca7b6.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-dac48066b5883d8b4551fc584f0c2a3e.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-dbea1af6dcd9860be40c3d18254338f5.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-e11567fd2accf9957cd0d3c2be937d87.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-e2ead7ea7da0437f085f42ffc05f8d13.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-e3fcf5180fd466c8915c4e8069491054.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-e480d9c614742d05f0e78f274f1e69e6.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-e4bca6cfa53e499cae0a6be4894a90e9.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-e51ef413167c6e14e0c0fdcc585f2fc9.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-e5f453bb04da18eed01675eeebd88bf8.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-e656f091b9dc4709722c9f4b84d3c797.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-ec181b795ac1fb5a50d700b6e996d745.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-ee8bae97908d5147b423f77ad0d3c1bb.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-f0f13b5c60e0af5553bd359f5513be1b.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-f2b54d4e7be0eaefe1c2c56836fa5368.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-f56414bf9bced67990def8660e306759.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-f5d079153c99a25b9be5b8583c4cc8a7.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-f6032fc06eb20480f096199713f70885.woff2 +0 -0
- package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-f8ee5d36068a42b51d0e4a1116cfcec1.woff2 +0 -0
- package/skills/excalidraw/app/dist/index.html +16 -0
- package/skills/excalidraw/app/index.html +14 -0
- package/skills/excalidraw/app/package.json +20 -0
- package/skills/excalidraw/app/pnpm-lock.yaml +2593 -0
- package/skills/excalidraw/app/src/main.jsx +334 -0
- package/skills/excalidraw/app/src/scene.js +247 -0
- package/skills/excalidraw/app/vite.config.js +19 -0
- package/skills/excalidraw/assets/examples/flowchart.excalidraw +19 -0
- package/skills/excalidraw/references/setup.md +27 -0
- package/skills/excalidraw/references/skeleton.md +84 -0
- package/skills/excalidraw/references/style.md +46 -0
- package/skills/excalidraw/references/sync-protocol.md +47 -0
- package/skills/excalidraw/scripts/excal.mjs +416 -0
- package/skills/excalidraw/scripts/lib.mjs +81 -0
- package/skills/excalidraw/scripts/server.mjs +476 -0
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CaptureUpdateAction,
|
|
3
|
+
convertToExcalidrawElements,
|
|
4
|
+
Excalidraw,
|
|
5
|
+
exportToBlob,
|
|
6
|
+
restoreElements,
|
|
7
|
+
serializeAsJSON,
|
|
8
|
+
} from "@excalidraw/excalidraw";
|
|
9
|
+
import "@excalidraw/excalidraw/index.css";
|
|
10
|
+
import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
11
|
+
import { createRoot } from "react-dom/client";
|
|
12
|
+
import {
|
|
13
|
+
contentKey,
|
|
14
|
+
convertMixed,
|
|
15
|
+
isSkeleton,
|
|
16
|
+
recenterLabels,
|
|
17
|
+
repairScene,
|
|
18
|
+
sameContent,
|
|
19
|
+
sceneSig,
|
|
20
|
+
threeWayMerge,
|
|
21
|
+
} from "./scene.js";
|
|
22
|
+
|
|
23
|
+
const params = new URLSearchParams(location.search);
|
|
24
|
+
const FILE_ID = params.get("file");
|
|
25
|
+
const TOKEN = params.get("token");
|
|
26
|
+
const CLIENT_ID = crypto.randomUUID();
|
|
27
|
+
const SAVE_DEBOUNCE_MS = 400;
|
|
28
|
+
const RESTORE_OPTS = { refreshDimensions: true, repairBindings: true };
|
|
29
|
+
const randomNonce = () => Math.floor(Math.random() * 2 ** 31);
|
|
30
|
+
|
|
31
|
+
async function api(pathname, init = {}) {
|
|
32
|
+
return fetch(`/api/files/${FILE_ID}${pathname}`, {
|
|
33
|
+
...init,
|
|
34
|
+
headers: { "x-excal-token": TOKEN, ...(init.headers || {}) },
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Parse file content and turn skeleton / mermaid input into full elements. */
|
|
39
|
+
async function prepareScene(content, prevElements = []) {
|
|
40
|
+
const data = JSON.parse(content);
|
|
41
|
+
let elements = Array.isArray(data.elements) ? data.elements : [];
|
|
42
|
+
let normalized = false;
|
|
43
|
+
if (typeof data.pendingMermaid === "string" && data.pendingMermaid.trim()) {
|
|
44
|
+
// A mermaid import replaces the diagram. Node ids are stable, so
|
|
45
|
+
// re-importing an edited .mmd updates the same elements in place.
|
|
46
|
+
const { parseMermaidToExcalidraw } = await import("@excalidraw/mermaid-to-excalidraw");
|
|
47
|
+
const { elements: skel } = await parseMermaidToExcalidraw(data.pendingMermaid, {
|
|
48
|
+
themeVariables: { fontSize: "20px" },
|
|
49
|
+
});
|
|
50
|
+
elements = convertToExcalidrawElements(skel, { regenerateIds: false });
|
|
51
|
+
normalized = true;
|
|
52
|
+
}
|
|
53
|
+
if (elements.some(isSkeleton)) {
|
|
54
|
+
elements = convertMixed(elements);
|
|
55
|
+
normalized = true;
|
|
56
|
+
}
|
|
57
|
+
const repaired = repairScene(elements, prevElements);
|
|
58
|
+
if (repaired.changed) {
|
|
59
|
+
elements = repaired.elements;
|
|
60
|
+
normalized = true;
|
|
61
|
+
}
|
|
62
|
+
return { elements, appState: data.appState || {}, files: data.files || {}, normalized };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function describe(ids, elements) {
|
|
66
|
+
const byId = new Map(elements.map((e) => [e.id, e]));
|
|
67
|
+
const labelOf = (id) => {
|
|
68
|
+
const el = byId.get(id);
|
|
69
|
+
if (!el) return null;
|
|
70
|
+
if (el.type === "text") return el.text;
|
|
71
|
+
const t = (el.boundElements || []).find((b) => b.type === "text");
|
|
72
|
+
return t ? byId.get(t.id)?.text : null;
|
|
73
|
+
};
|
|
74
|
+
const named = ids.map(labelOf).filter(Boolean);
|
|
75
|
+
if (!named.length) return `요소 ${ids.length}개`;
|
|
76
|
+
const head = `"${named[0].split("\n")[0].slice(0, 20)}"`;
|
|
77
|
+
return ids.length > 1 ? `${head} 외 ${ids.length - 1}개` : head;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function App() {
|
|
81
|
+
const [excalidrawAPI, setAPI] = useState(null);
|
|
82
|
+
const [status, setStatus] = useState("연결 중");
|
|
83
|
+
const s = useRef({
|
|
84
|
+
rev: 0,
|
|
85
|
+
ready: false,
|
|
86
|
+
lastSig: "",
|
|
87
|
+
lastError: null,
|
|
88
|
+
baseline: new Map(),
|
|
89
|
+
saveTimer: null,
|
|
90
|
+
queue: Promise.resolve(),
|
|
91
|
+
firstLoad: true,
|
|
92
|
+
}).current;
|
|
93
|
+
|
|
94
|
+
// Serialize all scene mutations (remote apply / save) so they never interleave.
|
|
95
|
+
const enqueue = useCallback((fn) => {
|
|
96
|
+
s.queue = s.queue.then(fn).catch((err) => {
|
|
97
|
+
console.error(err);
|
|
98
|
+
s.lastError = err.message;
|
|
99
|
+
setStatus(`오류: ${err.message}`);
|
|
100
|
+
});
|
|
101
|
+
return s.queue;
|
|
102
|
+
}, []);
|
|
103
|
+
|
|
104
|
+
const setBaseline = (elements) => {
|
|
105
|
+
s.baseline = new Map(elements.map((e) => [e.id, { version: e.version, key: contentKey(e) }]));
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const save = useCallback(async () => {
|
|
109
|
+
const API = excalidrawAPI;
|
|
110
|
+
const elements = API.getSceneElementsIncludingDeleted();
|
|
111
|
+
const content = serializeAsJSON(elements, API.getAppState(), API.getFiles(), "local");
|
|
112
|
+
setStatus("저장 중");
|
|
113
|
+
const res = await api("/scene", {
|
|
114
|
+
method: "PUT",
|
|
115
|
+
headers: { "content-type": "application/json" },
|
|
116
|
+
body: JSON.stringify({ baseRev: s.rev, content, clientId: CLIENT_ID }),
|
|
117
|
+
});
|
|
118
|
+
if (res.status === 409) {
|
|
119
|
+
const { rev, content: remote } = await res.json();
|
|
120
|
+
await applyRemote(remote, rev);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (!res.ok) throw new Error(`save failed ${res.status}`);
|
|
124
|
+
s.rev = (await res.json()).rev;
|
|
125
|
+
s.lastSig = sceneSig(elements);
|
|
126
|
+
setBaseline(elements.filter((e) => !e.isDeleted));
|
|
127
|
+
setStatus("동기화됨");
|
|
128
|
+
}, [excalidrawAPI]);
|
|
129
|
+
|
|
130
|
+
const applyRemote = useCallback(
|
|
131
|
+
async (content, rev) => {
|
|
132
|
+
const API = excalidrawAPI;
|
|
133
|
+
const local = API.getSceneElementsIncludingDeleted();
|
|
134
|
+
const prepared = await prepareScene(content, local);
|
|
135
|
+
// Label centering needs the text size re-measured by restoreElements.
|
|
136
|
+
const { elements: remote } = recenterLabels(restoreElements(prepared.elements, local, RESTORE_OPTS));
|
|
137
|
+
// Anything restore/recenter fixed (dangling bindings, text size, label
|
|
138
|
+
// position) must reach the file too, not just the canvas.
|
|
139
|
+
const writeBack = prepared.normalized || !sameContent(prepared.elements, remote);
|
|
140
|
+
|
|
141
|
+
const dirty = sceneSig(local) !== s.lastSig && !s.firstLoad;
|
|
142
|
+
let { elements, keptLocal } = dirty
|
|
143
|
+
? threeWayMerge(s.baseline, remote, local)
|
|
144
|
+
: { elements: remote, keptLocal: 0 };
|
|
145
|
+
|
|
146
|
+
// Elements removed in the file become tombstones and changed ones get a
|
|
147
|
+
// version bump; otherwise Excalidraw's store sees no change and Cmd+Z
|
|
148
|
+
// would skip (and later clobber) the external edit.
|
|
149
|
+
const localById = new Map(local.map((e) => [e.id, e]));
|
|
150
|
+
const ids = new Set(elements.map((e) => e.id));
|
|
151
|
+
elements = [
|
|
152
|
+
...elements,
|
|
153
|
+
...local.filter((l) => !l.isDeleted && !ids.has(l.id)).map((l) => ({ ...l, isDeleted: true })),
|
|
154
|
+
];
|
|
155
|
+
elements = elements.map((e) => {
|
|
156
|
+
const l = localById.get(e.id);
|
|
157
|
+
if (!l || contentKey(l) === contentKey(e)) return e;
|
|
158
|
+
return { ...e, version: Math.max(l.version, e.version) + 1, versionNonce: randomNonce() };
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
const changedIds = new Set();
|
|
162
|
+
for (const e of elements) {
|
|
163
|
+
const l = localById.get(e.id);
|
|
164
|
+
if (l && contentKey(l) === contentKey(e)) continue;
|
|
165
|
+
if (!l && e.isDeleted) continue;
|
|
166
|
+
changedIds.add(e.type === "text" && e.containerId ? e.containerId : e.id);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
API.updateScene({
|
|
170
|
+
elements,
|
|
171
|
+
appState: prepared.appState.viewBackgroundColor
|
|
172
|
+
? { viewBackgroundColor: prepared.appState.viewBackgroundColor }
|
|
173
|
+
: {},
|
|
174
|
+
captureUpdate: s.firstLoad ? CaptureUpdateAction.NEVER : CaptureUpdateAction.IMMEDIATELY,
|
|
175
|
+
});
|
|
176
|
+
if (Object.keys(prepared.files).length) API.addFiles(Object.values(prepared.files));
|
|
177
|
+
if (s.firstLoad) {
|
|
178
|
+
API.scrollToContent(undefined, { fitToContent: true });
|
|
179
|
+
s.firstLoad = false;
|
|
180
|
+
} else if (changedIds.size) {
|
|
181
|
+
API.setToast({
|
|
182
|
+
message: `파일 변경 반영: ${describe([...changedIds], elements)} (Cmd+Z로 취소)`,
|
|
183
|
+
duration: 2500,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
s.rev = rev;
|
|
188
|
+
s.lastError = null;
|
|
189
|
+
const now = API.getSceneElementsIncludingDeleted();
|
|
190
|
+
s.lastSig = sceneSig(now);
|
|
191
|
+
const nowById = new Map(now.map((e) => [e.id, e]));
|
|
192
|
+
s.baseline = new Map(
|
|
193
|
+
remote.map((r) => [r.id, { version: nowById.get(r.id)?.version ?? r.version, key: contentKey(r) }]),
|
|
194
|
+
);
|
|
195
|
+
s.ready = true;
|
|
196
|
+
setStatus("동기화됨");
|
|
197
|
+
if (writeBack || keptLocal > 0) await save();
|
|
198
|
+
},
|
|
199
|
+
[excalidrawAPI, save],
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
const snapshot = useCallback(
|
|
203
|
+
async ({ reqId, rev }) => {
|
|
204
|
+
const API = excalidrawAPI;
|
|
205
|
+
const post = (body, type) =>
|
|
206
|
+
fetch(`/api/snapshots/${reqId}`, {
|
|
207
|
+
method: "POST",
|
|
208
|
+
headers: { "x-excal-token": TOKEN, "content-type": type },
|
|
209
|
+
body,
|
|
210
|
+
});
|
|
211
|
+
const deadline = Date.now() + 5000;
|
|
212
|
+
while (s.rev < rev && Date.now() < deadline) await new Promise((r) => setTimeout(r, 100));
|
|
213
|
+
await s.queue;
|
|
214
|
+
if (s.rev < rev) {
|
|
215
|
+
const why = s.lastError ? `: ${s.lastError}` : "";
|
|
216
|
+
await post(
|
|
217
|
+
JSON.stringify({ error: `창이 최신 파일(rev ${rev})을 반영하지 못했습니다 (현재 rev ${s.rev})${why}` }),
|
|
218
|
+
"application/json",
|
|
219
|
+
);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
await document.fonts.ready;
|
|
223
|
+
try {
|
|
224
|
+
const blob = await exportToBlob({
|
|
225
|
+
elements: API.getSceneElements(),
|
|
226
|
+
appState: { ...API.getAppState(), exportBackground: true, exportWithDarkMode: false },
|
|
227
|
+
files: API.getFiles(),
|
|
228
|
+
mimeType: "image/png",
|
|
229
|
+
exportPadding: 24,
|
|
230
|
+
getDimensions: (w, h) => {
|
|
231
|
+
const scale = Math.min(2, 4000 / Math.max(w, h, 1));
|
|
232
|
+
return { width: w * scale, height: h * scale, scale };
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
await post(blob, "image/png");
|
|
236
|
+
} catch (err) {
|
|
237
|
+
await post(JSON.stringify({ error: err.message }), "application/json");
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
[excalidrawAPI],
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
useEffect(() => {
|
|
244
|
+
if (!excalidrawAPI) return;
|
|
245
|
+
window.__excal = { api: excalidrawAPI, state: s };
|
|
246
|
+
const loadLatest = () =>
|
|
247
|
+
enqueue(async () => {
|
|
248
|
+
const res = await api("/scene");
|
|
249
|
+
if (!res.ok) throw new Error(`load failed ${res.status}`);
|
|
250
|
+
const { rev, content, name } = await res.json();
|
|
251
|
+
document.title = `${name} · Excalidraw`;
|
|
252
|
+
if (rev !== s.rev) await applyRemote(content, rev);
|
|
253
|
+
});
|
|
254
|
+
const handlers = {
|
|
255
|
+
hello: () => loadLatest(),
|
|
256
|
+
scene: ({ rev, content }) => enqueue(() => (rev > s.rev ? applyRemote(content, rev) : undefined)),
|
|
257
|
+
snapshot: (data) => snapshot(data),
|
|
258
|
+
problem: ({ message }) => {
|
|
259
|
+
excalidrawAPI.setToast({ message, closable: true, duration: 6000 });
|
|
260
|
+
setStatus("파일 오류");
|
|
261
|
+
},
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
// WebSocket instead of SSE: SSE holds one of Chrome's 6 HTTP/1.1
|
|
265
|
+
// connections per origin, so a 6th window would starve every save.
|
|
266
|
+
let ws;
|
|
267
|
+
let retry = 0;
|
|
268
|
+
let closed = false;
|
|
269
|
+
let timer;
|
|
270
|
+
const connect = () => {
|
|
271
|
+
const proto = location.protocol === "https:" ? "wss" : "ws";
|
|
272
|
+
ws = new WebSocket(`${proto}://${location.host}/api/files/${FILE_ID}/ws?clientId=${CLIENT_ID}&token=${TOKEN}`);
|
|
273
|
+
ws.onopen = () => (retry = 0);
|
|
274
|
+
ws.onmessage = (m) => {
|
|
275
|
+
const { event, data } = JSON.parse(m.data);
|
|
276
|
+
handlers[event]?.(data);
|
|
277
|
+
};
|
|
278
|
+
ws.onclose = () => {
|
|
279
|
+
if (closed) return;
|
|
280
|
+
setStatus("연결 끊김, 재시도 중");
|
|
281
|
+
timer = setTimeout(connect, Math.min(5000, 300 * 2 ** retry++));
|
|
282
|
+
};
|
|
283
|
+
};
|
|
284
|
+
connect();
|
|
285
|
+
return () => {
|
|
286
|
+
closed = true;
|
|
287
|
+
clearTimeout(timer);
|
|
288
|
+
ws.close();
|
|
289
|
+
};
|
|
290
|
+
}, [excalidrawAPI]);
|
|
291
|
+
|
|
292
|
+
const onChange = useCallback(
|
|
293
|
+
(elements) => {
|
|
294
|
+
if (!s.ready) return;
|
|
295
|
+
if (sceneSig(elements) === s.lastSig) return;
|
|
296
|
+
setStatus("변경됨");
|
|
297
|
+
clearTimeout(s.saveTimer);
|
|
298
|
+
s.saveTimer = setTimeout(
|
|
299
|
+
() =>
|
|
300
|
+
enqueue(() =>
|
|
301
|
+
sceneSig(excalidrawAPI.getSceneElementsIncludingDeleted()) !== s.lastSig ? save() : undefined,
|
|
302
|
+
),
|
|
303
|
+
SAVE_DEBOUNCE_MS,
|
|
304
|
+
);
|
|
305
|
+
},
|
|
306
|
+
[excalidrawAPI, save],
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
if (!FILE_ID || !TOKEN)
|
|
310
|
+
return <p style={{ padding: 24 }}>file/token 파라미터가 없습니다. `excal open`으로 여세요.</p>;
|
|
311
|
+
|
|
312
|
+
return (
|
|
313
|
+
<Excalidraw
|
|
314
|
+
excalidrawAPI={setAPI}
|
|
315
|
+
onChange={onChange}
|
|
316
|
+
langCode="ko-KR"
|
|
317
|
+
UIOptions={{ canvasActions: { loadScene: false, saveToActiveFile: false } }}
|
|
318
|
+
renderTopRightUI={() => (
|
|
319
|
+
<span
|
|
320
|
+
style={{
|
|
321
|
+
font: "12px system-ui",
|
|
322
|
+
color: status === "동기화됨" ? "#2f9e44" : "#e8590c",
|
|
323
|
+
padding: "0 8px",
|
|
324
|
+
alignSelf: "center",
|
|
325
|
+
}}
|
|
326
|
+
>
|
|
327
|
+
● {status}
|
|
328
|
+
</span>
|
|
329
|
+
)}
|
|
330
|
+
/>
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
createRoot(document.getElementById("root")).render(<App />);
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { convertToExcalidrawElements } from "@excalidraw/excalidraw";
|
|
2
|
+
|
|
3
|
+
/** Elements written by the LLM in skeleton form have no numeric `version`. */
|
|
4
|
+
export const isSkeleton = (el) => typeof el?.version !== "number";
|
|
5
|
+
|
|
6
|
+
const ARROW_GAP = 6;
|
|
7
|
+
|
|
8
|
+
function edgeT(shape, dx, dy) {
|
|
9
|
+
const hw = shape.width / 2;
|
|
10
|
+
const hh = shape.height / 2;
|
|
11
|
+
if (shape.type === "ellipse") return 1 / Math.sqrt((dx / hw) ** 2 + (dy / hh) ** 2);
|
|
12
|
+
if (shape.type === "diamond") return 1 / (Math.abs(dx) / hw + Math.abs(dy) / hh);
|
|
13
|
+
// rectangle / text / everything else: bounding box
|
|
14
|
+
return Math.min(dx === 0 ? Infinity : hw / Math.abs(dx), dy === 0 ? Infinity : hh / Math.abs(dy));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const SHAPE_TYPES = new Set(["rectangle", "ellipse", "diamond"]);
|
|
18
|
+
|
|
19
|
+
const hasBox = (el) =>
|
|
20
|
+
el && [el.x, el.y, el.width, el.height].every((v) => typeof v === "number" && Number.isFinite(v));
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Skeleton arrows that only name `start.id` / `end.id` (no x/y) get coordinates
|
|
24
|
+
* computed from the two shapes: centre-to-centre, clipped at each shape's edge.
|
|
25
|
+
*/
|
|
26
|
+
export function autoRouteArrow(arrow, byId) {
|
|
27
|
+
if (arrow.type !== "arrow" && arrow.type !== "line") return arrow;
|
|
28
|
+
if (typeof arrow.x === "number" && typeof arrow.y === "number") return arrow;
|
|
29
|
+
const a = byId.get(arrow.start?.id);
|
|
30
|
+
const b = byId.get(arrow.end?.id);
|
|
31
|
+
if (!hasBox(a) || !hasBox(b)) return arrow;
|
|
32
|
+
const ca = { x: a.x + a.width / 2, y: a.y + a.height / 2 };
|
|
33
|
+
const cb = { x: b.x + b.width / 2, y: b.y + b.height / 2 };
|
|
34
|
+
const dx = cb.x - ca.x;
|
|
35
|
+
const dy = cb.y - ca.y;
|
|
36
|
+
const len = Math.hypot(dx, dy) || 1;
|
|
37
|
+
const ux = dx / len;
|
|
38
|
+
const uy = dy / len;
|
|
39
|
+
const ta = edgeT(a, dx, dy) * len + ARROW_GAP;
|
|
40
|
+
const tb = edgeT(b, -dx, -dy) * len + ARROW_GAP;
|
|
41
|
+
const sx = ca.x + ux * ta;
|
|
42
|
+
const sy = ca.y + uy * ta;
|
|
43
|
+
const ex = cb.x - ux * tb;
|
|
44
|
+
const ey = cb.y - uy * tb;
|
|
45
|
+
return {
|
|
46
|
+
...arrow,
|
|
47
|
+
x: sx,
|
|
48
|
+
y: sy,
|
|
49
|
+
width: Math.abs(ex - sx),
|
|
50
|
+
height: Math.abs(ey - sy),
|
|
51
|
+
points: [
|
|
52
|
+
[0, 0],
|
|
53
|
+
[ex - sx, ey - sy],
|
|
54
|
+
],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function mergeBound(a, b) {
|
|
59
|
+
const out = [...(a || [])];
|
|
60
|
+
for (const item of b || []) if (!out.some((x) => x.id === item.id)) out.push(item);
|
|
61
|
+
return out.length ? out : null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Convert skeleton elements (possibly mixed with full elements) into full
|
|
66
|
+
* Excalidraw elements. Full elements are passed through untouched except for
|
|
67
|
+
* `boundElements`, which receives bindings created by skeleton arrows/labels.
|
|
68
|
+
*/
|
|
69
|
+
export function convertMixed(input) {
|
|
70
|
+
// An element rewritten as a skeleton (version removed) with a new `label`
|
|
71
|
+
// replaces its old bound text.
|
|
72
|
+
const relabeled = new Set(input.filter((e) => isSkeleton(e) && e.id && e.label).map((e) => e.id));
|
|
73
|
+
const elements = input.filter((e) => !(e.type === "text" && !isSkeleton(e) && relabeled.has(e.containerId)));
|
|
74
|
+
const byId = new Map(elements.filter((e) => e.id).map((e) => [e.id, e]));
|
|
75
|
+
const prepared = elements.map((el) => {
|
|
76
|
+
if (isSkeleton(el)) return autoRouteArrow(el, byId);
|
|
77
|
+
// Full frames carry membership in their children's `frameId`, not in
|
|
78
|
+
// `children`; the converter iterates `children` unguarded.
|
|
79
|
+
if ((el.type === "frame" || el.type === "magicframe") && !Array.isArray(el.children))
|
|
80
|
+
return { ...el, children: [] };
|
|
81
|
+
return el;
|
|
82
|
+
});
|
|
83
|
+
const converted = convertToExcalidrawElements(prepared, { regenerateIds: false });
|
|
84
|
+
const originals = new Map(elements.filter((e) => !isSkeleton(e)).map((e) => [e.id, e]));
|
|
85
|
+
return converted.map((c) => {
|
|
86
|
+
const orig = originals.get(c.id);
|
|
87
|
+
if (!orig) return c;
|
|
88
|
+
return {
|
|
89
|
+
...orig,
|
|
90
|
+
boundElements: mergeBound(orig.boundElements, c.boundElements),
|
|
91
|
+
// a skeleton frame may adopt existing full elements
|
|
92
|
+
frameId: c.frameId ?? orig.frameId ?? null,
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function distToBox(px, py, el) {
|
|
98
|
+
const dx = Math.max(el.x - px, 0, px - (el.x + el.width));
|
|
99
|
+
const dy = Math.max(el.y - py, 0, py - (el.y + el.height));
|
|
100
|
+
return Math.hypot(dx, dy);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Post-processing for full elements edited by hand (before restoreElements):
|
|
105
|
+
* - straight bound arrows whose endpoints drifted away from their shapes
|
|
106
|
+
* (because a shape was moved in the file) are re-routed;
|
|
107
|
+
* - shapes get back-references to arrows bound to them, and bound texts to
|
|
108
|
+
* their containers, so Excalidraw keeps them attached when dragging.
|
|
109
|
+
*/
|
|
110
|
+
const geom = (e) => (e ? [e.x, e.y, e.width, e.height].map((v) => Math.round(v ?? 0)).join(",") : "");
|
|
111
|
+
|
|
112
|
+
export function repairScene(elements, prevElements = []) {
|
|
113
|
+
const byId = new Map(elements.map((e) => [e.id, e]));
|
|
114
|
+
const prev = new Map(prevElements.map((e) => [e.id, e]));
|
|
115
|
+
const arrowGeom = (e) => (e ? geom(e) + JSON.stringify(e.points) : "");
|
|
116
|
+
let changed = false;
|
|
117
|
+
const out = elements.map((el) => {
|
|
118
|
+
if (el.isDeleted || el.type !== "arrow" || el.points?.length !== 2) return el;
|
|
119
|
+
const a = byId.get(el.startBinding?.elementId);
|
|
120
|
+
const b = byId.get(el.endBinding?.elementId);
|
|
121
|
+
if (!hasBox(a) || !hasBox(b)) return el;
|
|
122
|
+
const [p0, p1] = el.points;
|
|
123
|
+
const far = distToBox(el.x + p0[0], el.y + p0[1], a) > 30 || distToBox(el.x + p1[0], el.y + p1[1], b) > 30;
|
|
124
|
+
// a bound shape moved in the file while the arrow itself was left untouched
|
|
125
|
+
const pa = prev.get(el.id);
|
|
126
|
+
const shapeMoved =
|
|
127
|
+
pa &&
|
|
128
|
+
arrowGeom(pa) === arrowGeom(el) &&
|
|
129
|
+
((prev.has(a.id) && geom(prev.get(a.id)) !== geom(a)) || (prev.has(b.id) && geom(prev.get(b.id)) !== geom(b)));
|
|
130
|
+
if (!far && !shapeMoved) return el;
|
|
131
|
+
const routed = autoRouteArrow({ type: "arrow", start: { id: a.id }, end: { id: b.id } }, byId);
|
|
132
|
+
changed = true;
|
|
133
|
+
return { ...el, x: routed.x, y: routed.y, width: routed.width, height: routed.height, points: routed.points };
|
|
134
|
+
});
|
|
135
|
+
const outById = new Map(out.map((e) => [e.id, e]));
|
|
136
|
+
const addRef = (targetId, ref) => {
|
|
137
|
+
const t = outById.get(targetId);
|
|
138
|
+
if (!t || (t.boundElements || []).some((b) => b.id === ref.id)) return;
|
|
139
|
+
const next = { ...t, boundElements: [...(t.boundElements || []), ref] };
|
|
140
|
+
outById.set(targetId, next);
|
|
141
|
+
changed = true;
|
|
142
|
+
};
|
|
143
|
+
for (const el of out) {
|
|
144
|
+
if (el.isDeleted) continue;
|
|
145
|
+
if (el.type === "arrow") {
|
|
146
|
+
if (el.startBinding?.elementId) addRef(el.startBinding.elementId, { id: el.id, type: "arrow" });
|
|
147
|
+
if (el.endBinding?.elementId) addRef(el.endBinding.elementId, { id: el.id, type: "arrow" });
|
|
148
|
+
}
|
|
149
|
+
if (el.type === "text" && el.containerId) addRef(el.containerId, { id: el.id, type: "text" });
|
|
150
|
+
}
|
|
151
|
+
return { elements: out.map((e) => outById.get(e.id)), changed };
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Keep bound labels positioned inside their containers. Must run after
|
|
156
|
+
* restoreElements({refreshDimensions}) so it uses the re-measured text size.
|
|
157
|
+
*/
|
|
158
|
+
export function recenterLabels(elements) {
|
|
159
|
+
const PAD = 5;
|
|
160
|
+
const byId = new Map(elements.map((e) => [e.id, e]));
|
|
161
|
+
let changed = false;
|
|
162
|
+
const out = elements.map((el) => {
|
|
163
|
+
if (el.isDeleted || el.type !== "text" || !el.containerId) return el;
|
|
164
|
+
const c = byId.get(el.containerId);
|
|
165
|
+
if (!c || !SHAPE_TYPES.has(c.type) || !hasBox(c) || !hasBox(el)) return el;
|
|
166
|
+
// non-rectangles use inner-box offsets for non-centred text; leave those to Excalidraw
|
|
167
|
+
if (c.type !== "rectangle" && (el.textAlign !== "center" || el.verticalAlign !== "middle")) return el;
|
|
168
|
+
const x =
|
|
169
|
+
el.textAlign === "left"
|
|
170
|
+
? c.x + PAD
|
|
171
|
+
: el.textAlign === "right"
|
|
172
|
+
? c.x + c.width - el.width - PAD
|
|
173
|
+
: c.x + (c.width - el.width) / 2;
|
|
174
|
+
const y =
|
|
175
|
+
el.verticalAlign === "top"
|
|
176
|
+
? c.y + PAD
|
|
177
|
+
: el.verticalAlign === "bottom"
|
|
178
|
+
? c.y + c.height - el.height - PAD
|
|
179
|
+
: c.y + (c.height - el.height) / 2;
|
|
180
|
+
if (Math.abs(x - el.x) <= 1 && Math.abs(y - el.y) <= 1) return el;
|
|
181
|
+
changed = true;
|
|
182
|
+
return { ...el, x, y };
|
|
183
|
+
});
|
|
184
|
+
return { elements: out, changed };
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Same element ids with the same content (bookkeeping fields ignored). */
|
|
188
|
+
export function sameContent(a, b) {
|
|
189
|
+
if (a.length !== b.length) return false;
|
|
190
|
+
const keys = new Map(a.map((e) => [e.id, contentKey(e)]));
|
|
191
|
+
return b.every((e) => keys.get(e.id) === contentKey(e));
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const VOLATILE = new Set(["version", "versionNonce", "updated", "index", "seed"]);
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Content identity of an element, ignoring bookkeeping fields and sub-pixel
|
|
198
|
+
* drift from text re-measurement.
|
|
199
|
+
*/
|
|
200
|
+
export function contentKey(el) {
|
|
201
|
+
return JSON.stringify(el, (k, v) => (VOLATILE.has(k) ? undefined : typeof v === "number" ? Math.round(v) : v));
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export function sceneSig(elements) {
|
|
205
|
+
let sum = 0;
|
|
206
|
+
for (const e of elements) sum += e.version;
|
|
207
|
+
return `${elements.length}:${sum}`;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Three-way merge between the last synced baseline, the incoming remote
|
|
212
|
+
* elements and the local scene. Remote wins on conflicting edits of the same
|
|
213
|
+
* element; purely local edits made since the baseline are preserved.
|
|
214
|
+
*
|
|
215
|
+
* baseline: Map<id, {version, key}> (local version + content key at last sync)
|
|
216
|
+
*/
|
|
217
|
+
export function threeWayMerge(baseline, remote, local) {
|
|
218
|
+
const localById = new Map(local.map((e) => [e.id, e]));
|
|
219
|
+
const remoteIds = new Set(remote.map((e) => e.id));
|
|
220
|
+
let keptLocal = 0;
|
|
221
|
+
const out = [];
|
|
222
|
+
for (const r of remote) {
|
|
223
|
+
const l = localById.get(r.id);
|
|
224
|
+
const base = baseline.get(r.id);
|
|
225
|
+
const remoteChanged = !base || base.key !== contentKey(r);
|
|
226
|
+
const localChanged = l && base && l.version > base.version;
|
|
227
|
+
if (l && localChanged && !remoteChanged) {
|
|
228
|
+
out.push(l);
|
|
229
|
+
keptLocal++;
|
|
230
|
+
} else if ((!l || l.isDeleted) && base && !remoteChanged) {
|
|
231
|
+
// deleted locally, untouched remotely
|
|
232
|
+
if (l) out.push(l);
|
|
233
|
+
keptLocal++;
|
|
234
|
+
} else {
|
|
235
|
+
out.push(r);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
for (const l of local) {
|
|
239
|
+
if (remoteIds.has(l.id) || l.isDeleted) continue;
|
|
240
|
+
const base = baseline.get(l.id);
|
|
241
|
+
if (!base || l.version > base.version) {
|
|
242
|
+
out.push(l); // new locally, or edited locally while deleted remotely
|
|
243
|
+
keptLocal++;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return { elements: out, keptLocal };
|
|
247
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import react from "@vitejs/plugin-react";
|
|
4
|
+
import { defineConfig } from "vite";
|
|
5
|
+
|
|
6
|
+
// Self-host Excalidraw fonts (offline + Korean Xiaolai fallback).
|
|
7
|
+
const copyFonts = () => ({
|
|
8
|
+
name: "copy-excalidraw-fonts",
|
|
9
|
+
closeBundle() {
|
|
10
|
+
const src = path.resolve("node_modules/@excalidraw/excalidraw/dist/prod/fonts");
|
|
11
|
+
fs.cpSync(src, path.resolve("dist/fonts"), { recursive: true });
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export default defineConfig({
|
|
16
|
+
plugins: [react(), copyFonts()],
|
|
17
|
+
define: { "process.env.IS_PREACT": JSON.stringify("false") },
|
|
18
|
+
build: { chunkSizeWarningLimit: 8000 },
|
|
19
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "excalidraw",
|
|
3
|
+
"version": 2,
|
|
4
|
+
"source": "pi-excalidraw",
|
|
5
|
+
"elements": [
|
|
6
|
+
{ "type": "text", "id": "title", "x": 200, "y": 20, "text": "주문 처리 흐름", "fontSize": 28 },
|
|
7
|
+
{ "type": "ellipse", "id": "start", "x": 240, "y": 90, "width": 160, "height": 64, "backgroundColor": "#b2f2bb", "fillStyle": "solid", "label": { "text": "시작" } },
|
|
8
|
+
{ "type": "rectangle", "id": "order", "x": 220, "y": 214, "width": 200, "height": 72, "backgroundColor": "#a5d8ff", "fillStyle": "solid", "roundness": { "type": 3 }, "label": { "text": "주문 접수" } },
|
|
9
|
+
{ "type": "diamond", "id": "stock", "x": 210, "y": 346, "width": 220, "height": 120, "backgroundColor": "#ffec99", "fillStyle": "solid", "label": { "text": "재고 있음?" } },
|
|
10
|
+
{ "type": "rectangle", "id": "ship", "x": 220, "y": 526, "width": 200, "height": 72, "backgroundColor": "#a5d8ff", "fillStyle": "solid", "roundness": { "type": 3 }, "label": { "text": "배송 준비" } },
|
|
11
|
+
{ "type": "rectangle", "id": "backorder", "x": 520, "y": 370, "width": 200, "height": 72, "backgroundColor": "#ffc9c9", "fillStyle": "solid", "roundness": { "type": 3 }, "label": { "text": "입고 대기 알림" } },
|
|
12
|
+
{ "type": "arrow", "id": "a1", "start": { "id": "start" }, "end": { "id": "order" } },
|
|
13
|
+
{ "type": "arrow", "id": "a2", "start": { "id": "order" }, "end": { "id": "stock" } },
|
|
14
|
+
{ "type": "arrow", "id": "a3", "start": { "id": "stock" }, "end": { "id": "ship" }, "label": { "text": "예" } },
|
|
15
|
+
{ "type": "arrow", "id": "a4", "start": { "id": "stock" }, "end": { "id": "backorder" }, "label": { "text": "아니오" } }
|
|
16
|
+
],
|
|
17
|
+
"appState": { "viewBackgroundColor": "#ffffff", "gridSize": 20 },
|
|
18
|
+
"files": {}
|
|
19
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# excalidraw 최초 설정
|
|
2
|
+
|
|
3
|
+
빌드된 편집기 앱이 패키지에 들어 있어 따로 설치·빌드할 것은 없다. 창을 띄울 브라우저만 필요하다.
|
|
4
|
+
|
|
5
|
+
## 확인
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
open -Ra "Google Chrome" && echo ok # macOS
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`ok`가 나오면 설정할 것이 없다. Linux는 `google-chrome`, `google-chrome-stable`, `chromium`, `chromium-browser` 중 하나가 PATH에 있으면 된다.
|
|
12
|
+
|
|
13
|
+
## 설치 (1회)
|
|
14
|
+
|
|
15
|
+
macOS는 Google Chrome이 필요하다. Chromium이나 다른 브라우저로는 창이 열리지 않는다.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
brew install --cask google-chrome
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
또는 https://www.google.com/chrome/ 에서 내려받는다.
|
|
22
|
+
|
|
23
|
+
## 참고
|
|
24
|
+
|
|
25
|
+
- 창은 사용자 Chrome 프로필과 분리된 전용 프로필(`~/.cache/pi-excalidraw/chrome-profile`)로 열린다. 로그인 정보나 확장 프로그램은 공유되지 않는다.
|
|
26
|
+
- 상태 디렉터리는 `EXCAL_STATE_DIR`로 바꿀 수 있다.
|
|
27
|
+
- 브라우저 없이 쓰려면 `EXCAL_BROWSER=none`을 주고, 출력된 URL을 직접 연다. `lint`, `inspect`는 브라우저가 필요 없다.
|