@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.
Files changed (422) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +25 -0
  3. package/package.json +44 -0
  4. package/skills/excalidraw/SKILL.md +58 -0
  5. package/skills/excalidraw/app/dist/assets/Assistant-Bold-gm-uSS1B.woff2 +0 -0
  6. package/skills/excalidraw/app/dist/assets/Assistant-Medium-DrcxCXg3.woff2 +0 -0
  7. package/skills/excalidraw/app/dist/assets/Assistant-Regular-DVxZuzxb.woff2 +0 -0
  8. package/skills/excalidraw/app/dist/assets/Assistant-SemiBold-SCI4bEL9.woff2 +0 -0
  9. package/skills/excalidraw/app/dist/assets/abnfDiagram-VCTEODGH-Y56Pk8sn.js +1 -0
  10. package/skills/excalidraw/app/dist/assets/ar-SA-G6X2FPQ2-DatABGjX.js +10 -0
  11. package/skills/excalidraw/app/dist/assets/arc-DgcGdgmL.js +1 -0
  12. package/skills/excalidraw/app/dist/assets/architecture-7GRP2DOG-BECp2Zrk.js +1 -0
  13. package/skills/excalidraw/app/dist/assets/architectureDiagram-5GKGNRK7-BkBTZ8aU.js +36 -0
  14. package/skills/excalidraw/app/dist/assets/array-BifhSqXX.js +1 -0
  15. package/skills/excalidraw/app/dist/assets/az-AZ-76LH7QW2-WQrHOob7.js +1 -0
  16. package/skills/excalidraw/app/dist/assets/bg-BG-XCXSNQG7-BVvnFVRX.js +5 -0
  17. package/skills/excalidraw/app/dist/assets/blockDiagram-I7D4REHJ-D7KnLVtF.js +129 -0
  18. package/skills/excalidraw/app/dist/assets/bn-BD-2XOGV67Q-DzlalUE2.js +5 -0
  19. package/skills/excalidraw/app/dist/assets/c4Diagram-7LVT6UL2-nV-MvTJT.js +38 -0
  20. package/skills/excalidraw/app/dist/assets/ca-ES-6MX7JW3Y-ILmKOQy8.js +8 -0
  21. package/skills/excalidraw/app/dist/assets/channel-Ca-ODdO0.js +1 -0
  22. package/skills/excalidraw/app/dist/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  23. package/skills/excalidraw/app/dist/assets/chunk-4HAMMTFA-CZal2Pyz.js +62 -0
  24. package/skills/excalidraw/app/dist/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  25. package/skills/excalidraw/app/dist/assets/chunk-75Z2AOVW-DVqFChOg.js +2 -0
  26. package/skills/excalidraw/app/dist/assets/chunk-DU6HZSFF-BavxyZSY.js +127 -0
  27. package/skills/excalidraw/app/dist/assets/chunk-EIO257PC-LlbbXIq6.js +22 -0
  28. package/skills/excalidraw/app/dist/assets/chunk-F27PBJKO-BWDl5_Sz.js +1 -0
  29. package/skills/excalidraw/app/dist/assets/chunk-FOHPRMQF-DzxwRta7.js +161 -0
  30. package/skills/excalidraw/app/dist/assets/chunk-GMAD6QVW-Rjz_G1RQ.js +72 -0
  31. package/skills/excalidraw/app/dist/assets/chunk-GVQU2GXP-BjxGnl2S.js +1 -0
  32. package/skills/excalidraw/app/dist/assets/chunk-IMKFNOWR-BJ1FymPn.js +231 -0
  33. package/skills/excalidraw/app/dist/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  34. package/skills/excalidraw/app/dist/assets/chunk-L3NEJ4N5-sJejB3eG.js +1 -0
  35. package/skills/excalidraw/app/dist/assets/chunk-OSK3NFVY-DLz3HNrx.js +10 -0
  36. package/skills/excalidraw/app/dist/assets/chunk-P2QGCYS3-Dhy4aMJl.js +1 -0
  37. package/skills/excalidraw/app/dist/assets/chunk-POPQ4Y6H-DOEx_tr4.js +1 -0
  38. package/skills/excalidraw/app/dist/assets/chunk-PWAF6VOD-Bq0yNT01.js +1 -0
  39. package/skills/excalidraw/app/dist/assets/chunk-SHT3W25Y-CICAAbIL.js +168 -0
  40. package/skills/excalidraw/app/dist/assets/chunk-SVP7TREG-f6pYNHg0.js +88 -0
  41. package/skills/excalidraw/app/dist/assets/chunk-TICWLB2K-DdRa5lMo.js +206 -0
  42. package/skills/excalidraw/app/dist/assets/chunk-XXDRQBXY-BvKO0v-W.js +1 -0
  43. package/skills/excalidraw/app/dist/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  44. package/skills/excalidraw/app/dist/assets/classDiagram-ZZMXUADV-DCPVGkLh.js +1 -0
  45. package/skills/excalidraw/app/dist/assets/classDiagram-v2-VYDZK3BY-DCPVGkLh.js +1 -0
  46. package/skills/excalidraw/app/dist/assets/cose-bilkent-JH36ORCC-COXSdE6a.js +1 -0
  47. package/skills/excalidraw/app/dist/assets/cs-CZ-2BRQDIVT-tV1CvCxu.js +11 -0
  48. package/skills/excalidraw/app/dist/assets/cynefin-OW5HDTMX-D-XvS_F8.js +1 -0
  49. package/skills/excalidraw/app/dist/assets/cynefinDiagram-5FMLGOSQ-DWgEonYW.js +62 -0
  50. package/skills/excalidraw/app/dist/assets/cytoscape.esm-Yq6u8L66.js +321 -0
  51. package/skills/excalidraw/app/dist/assets/da-DK-5WZEPLOC-zceHT2GU.js +5 -0
  52. package/skills/excalidraw/app/dist/assets/dagre-C-rnJpZF.js +1 -0
  53. package/skills/excalidraw/app/dist/assets/dagre-GXQ25YYZ-d3UPf-z-.js +4 -0
  54. package/skills/excalidraw/app/dist/assets/de-DE-XR44H4JA-U1KbS0X3.js +8 -0
  55. package/skills/excalidraw/app/dist/assets/defaultLocale-BFoDCU3G.js +1 -0
  56. package/skills/excalidraw/app/dist/assets/diagram-S7CK7UJ4-CRc82Fb9.js +30 -0
  57. package/skills/excalidraw/app/dist/assets/diagram-UQ7AKVKN-CgfviMBL.js +41 -0
  58. package/skills/excalidraw/app/dist/assets/diagram-VSXAHHWV-Btexo3l8.js +3 -0
  59. package/skills/excalidraw/app/dist/assets/diagram-VX7I27RA-DoMnip1P.js +24 -0
  60. package/skills/excalidraw/app/dist/assets/diagram-Z3DM3KII-BTsxq82z.js +24 -0
  61. package/skills/excalidraw/app/dist/assets/directory-open-01563666-D4xXyWb_.js +1 -0
  62. package/skills/excalidraw/app/dist/assets/directory-open-4ed118d0-1i309Asm.js +1 -0
  63. package/skills/excalidraw/app/dist/assets/dist-B_J_HbC0.js +1 -0
  64. package/skills/excalidraw/app/dist/assets/dist-DVyo1T_H.js +62 -0
  65. package/skills/excalidraw/app/dist/assets/ebnfDiagram-PWID7BFC-BYsNxk9n.js +1 -0
  66. package/skills/excalidraw/app/dist/assets/el-GR-BZB4AONW-CgSV8rfE.js +10 -0
  67. package/skills/excalidraw/app/dist/assets/en-B4ZKOASM-Byd7DbO_.js +1 -0
  68. package/skills/excalidraw/app/dist/assets/erDiagram-RLTQ6QDP-LkewsTFZ.js +99 -0
  69. package/skills/excalidraw/app/dist/assets/es-ES-U4NZUMDT-d42UjG1W.js +9 -0
  70. package/skills/excalidraw/app/dist/assets/eu-ES-A7QVB2H4-CeMeFdnp.js +11 -0
  71. package/skills/excalidraw/app/dist/assets/eventmodeling-NTZA5JFV-160-dgiE.js +1 -0
  72. package/skills/excalidraw/app/dist/assets/fa-IR-HGAKTJCU-CVXIrtPl.js +8 -0
  73. package/skills/excalidraw/app/dist/assets/fi-FI-Z5N7JZ37-DIW6dubX.js +6 -0
  74. package/skills/excalidraw/app/dist/assets/file-open-002ab408-BHUWm0Sh.js +1 -0
  75. package/skills/excalidraw/app/dist/assets/file-open-7c801643-DZtJT5zp.js +1 -0
  76. package/skills/excalidraw/app/dist/assets/file-save-3189631c-CO9S4HFW.js +1 -0
  77. package/skills/excalidraw/app/dist/assets/file-save-745eba88-Bwdfz6OZ.js +1 -0
  78. package/skills/excalidraw/app/dist/assets/flowDiagram-HODETNUW-XE0UaaJt.js +1 -0
  79. package/skills/excalidraw/app/dist/assets/fr-FR-RHASNOE6-EPyEt_4g.js +9 -0
  80. package/skills/excalidraw/app/dist/assets/ganttDiagram-EL5Y4UJY-DuJaTNOL.js +292 -0
  81. package/skills/excalidraw/app/dist/assets/gitGraph-4MIJSDKK-DHGj5WCj.js +1 -0
  82. package/skills/excalidraw/app/dist/assets/gitGraphDiagram-WWUBYQGX-DdvnVTzU.js +106 -0
  83. package/skills/excalidraw/app/dist/assets/gl-ES-HMX3MZ6V-Cbr9hGRI.js +10 -0
  84. package/skills/excalidraw/app/dist/assets/graphlib-DS17s2tU.js +1 -0
  85. package/skills/excalidraw/app/dist/assets/he-IL-6SHJWFNN-B5Iboi8a.js +10 -0
  86. package/skills/excalidraw/app/dist/assets/hi-IN-IWLTKZ5I-k6swWOWn.js +4 -0
  87. package/skills/excalidraw/app/dist/assets/hu-HU-A5ZG7DT2-DaDlVvTE.js +7 -0
  88. package/skills/excalidraw/app/dist/assets/id-ID-SAP4L64H-DiV3qfW7.js +10 -0
  89. package/skills/excalidraw/app/dist/assets/image-GAAHSSAO-stUGVFAH.js +1 -0
  90. package/skills/excalidraw/app/dist/assets/image-blob-reduce.esm-BFq-Mx5V.js +2 -0
  91. package/skills/excalidraw/app/dist/assets/index-ChSm4O-k.js +208 -0
  92. package/skills/excalidraw/app/dist/assets/index-DtRVLazd.css +1 -0
  93. package/skills/excalidraw/app/dist/assets/info-A6RAGUB7-EjytcsrH.js +1 -0
  94. package/skills/excalidraw/app/dist/assets/infoDiagram-27XIBGKW-D5p952K8.js +2 -0
  95. package/skills/excalidraw/app/dist/assets/init-C-OQMol4.js +1 -0
  96. package/skills/excalidraw/app/dist/assets/ishikawaDiagram-5VMMS53U-Cl9GrB8p.js +70 -0
  97. package/skills/excalidraw/app/dist/assets/it-IT-JPQ66NNP-B3YDn8c7.js +11 -0
  98. package/skills/excalidraw/app/dist/assets/ja-JP-DBVTYXUO-r8GJRlz8.js +8 -0
  99. package/skills/excalidraw/app/dist/assets/journeyDiagram-3NMN7TZE-DPL61tuu.js +139 -0
  100. package/skills/excalidraw/app/dist/assets/kaa-6HZHGXH3-CQXO0smT.js +1 -0
  101. package/skills/excalidraw/app/dist/assets/kab-KAB-ZGHBKWFO-CcnpslfP.js +8 -0
  102. package/skills/excalidraw/app/dist/assets/kanban-definition-UXKFOSKX-CrEwB5Tt.js +89 -0
  103. package/skills/excalidraw/app/dist/assets/katex-ZlcWpGUi.js +257 -0
  104. package/skills/excalidraw/app/dist/assets/kk-KZ-P5N5QNE5-DRBBwSLY.js +1 -0
  105. package/skills/excalidraw/app/dist/assets/km-KH-HSX4SM5Z-aDqmSt43.js +11 -0
  106. package/skills/excalidraw/app/dist/assets/ko-KR-MTYHY66A-CrTedvVS.js +9 -0
  107. package/skills/excalidraw/app/dist/assets/ku-TR-6OUDTVRD-hNhm9YQ0.js +9 -0
  108. package/skills/excalidraw/app/dist/assets/line-C4N-NEvZ.js +1 -0
  109. package/skills/excalidraw/app/dist/assets/linear-BUnzfXgk.js +1 -0
  110. package/skills/excalidraw/app/dist/assets/lt-LT-XHIRWOB4-HeBwh7CL.js +3 -0
  111. package/skills/excalidraw/app/dist/assets/lv-LV-5QDEKY6T-DXU4B6YW.js +7 -0
  112. package/skills/excalidraw/app/dist/assets/mermaid-parser.core-g7vsDY1V.js +7 -0
  113. package/skills/excalidraw/app/dist/assets/mindmap-definition-YA3MSWOX-D__pf1Yg.js +96 -0
  114. package/skills/excalidraw/app/dist/assets/mr-IN-CRQNXWMA-BYsXnQkb.js +13 -0
  115. package/skills/excalidraw/app/dist/assets/my-MM-5M5IBNSE-C871ZDtQ.js +1 -0
  116. package/skills/excalidraw/app/dist/assets/nb-NO-T6EIAALU-Cm-d6hjp.js +10 -0
  117. package/skills/excalidraw/app/dist/assets/nl-NL-IS3SIHDZ-XlSpYp1l.js +8 -0
  118. package/skills/excalidraw/app/dist/assets/nn-NO-6E72VCQL-BJPmp-_h.js +8 -0
  119. package/skills/excalidraw/app/dist/assets/oc-FR-POXYY2M6-D1rPi0z7.js +8 -0
  120. package/skills/excalidraw/app/dist/assets/ordinal-BDEzSJ7C.js +1 -0
  121. package/skills/excalidraw/app/dist/assets/pa-IN-N4M65BXN-hKsyWK74.js +4 -0
  122. package/skills/excalidraw/app/dist/assets/packet-AYTQ26CC-4PAjvWSX.js +1 -0
  123. package/skills/excalidraw/app/dist/assets/path-fybaL0A-.js +1 -0
  124. package/skills/excalidraw/app/dist/assets/pegDiagram-XKGWAZYB-CUfmvI5h.js +1 -0
  125. package/skills/excalidraw/app/dist/assets/percentages-BXMCSKIN-CfhMReVO.js +1 -0
  126. package/skills/excalidraw/app/dist/assets/pica-BPrp-GK1.js +2 -0
  127. package/skills/excalidraw/app/dist/assets/pie-WAS4IAKB-B5FgQybZ.js +1 -0
  128. package/skills/excalidraw/app/dist/assets/pieDiagram-E7YTZNPT-CU8w4Jjl.js +39 -0
  129. package/skills/excalidraw/app/dist/assets/pl-PL-T2D74RX3-DOodWdkP.js +9 -0
  130. package/skills/excalidraw/app/dist/assets/pt-BR-5N22H2LF-dyjRDPfa.js +9 -0
  131. package/skills/excalidraw/app/dist/assets/pt-PT-UZXXM6DQ-DXb9iBoj.js +9 -0
  132. package/skills/excalidraw/app/dist/assets/quadrantDiagram-AXDQQJYC-C60Jl0ho.js +7 -0
  133. package/skills/excalidraw/app/dist/assets/radar-RG4KPBEZ-Bb6LV2iq.js +1 -0
  134. package/skills/excalidraw/app/dist/assets/railroad-74A4TZTK-DYFjVugV.js +1 -0
  135. package/skills/excalidraw/app/dist/assets/railroad-abnf-HS5TGJTU-CCpAO9jj.js +1 -0
  136. package/skills/excalidraw/app/dist/assets/railroad-ebnf-LZEXJU2U-BTtgE2v0.js +1 -0
  137. package/skills/excalidraw/app/dist/assets/railroad-peg-WCYAUIDC-qT7-4WNw.js +1 -0
  138. package/skills/excalidraw/app/dist/assets/railroadDiagram-O6MQD6OU-D-Q-2PY3.js +1 -0
  139. package/skills/excalidraw/app/dist/assets/requirementDiagram-BXWQKSXE-DUJGchGn.js +84 -0
  140. package/skills/excalidraw/app/dist/assets/ro-RO-JPDTUUEW-D2t-SdK7.js +11 -0
  141. package/skills/excalidraw/app/dist/assets/rolldown-runtime-Dd_uD5pT.js +1 -0
  142. package/skills/excalidraw/app/dist/assets/rough.esm-Dy-Kn_BL.js +1 -0
  143. package/skills/excalidraw/app/dist/assets/roundRect-D01gJrlt.js +1 -0
  144. package/skills/excalidraw/app/dist/assets/ru-RU-B4JR7IUQ-B3zBvqM8.js +9 -0
  145. package/skills/excalidraw/app/dist/assets/sankeyDiagram-P5KCCOFB-B7gzsCzv.js +40 -0
  146. package/skills/excalidraw/app/dist/assets/sequenceDiagram-WJ2MYXX4-C1gETguU.js +162 -0
  147. package/skills/excalidraw/app/dist/assets/si-LK-N5RQ5JYF-x9atOM2o.js +1 -0
  148. package/skills/excalidraw/app/dist/assets/sizeCapture-INFHLROL-3uHXrFqA.js +1 -0
  149. package/skills/excalidraw/app/dist/assets/sk-SK-C5VTKIMK-Dc-U7HwG.js +6 -0
  150. package/skills/excalidraw/app/dist/assets/sl-SI-NN7IZMDC-DBErI-th.js +6 -0
  151. package/skills/excalidraw/app/dist/assets/src-oBChb5qS.js +1 -0
  152. package/skills/excalidraw/app/dist/assets/stateDiagram-D77RDMKH-ms90ttRw.js +1 -0
  153. package/skills/excalidraw/app/dist/assets/stateDiagram-v2-MP3YSRHH-BLT-8Bst.js +1 -0
  154. package/skills/excalidraw/app/dist/assets/subset-shared.chunk-JkuiVUYR.js +1 -0
  155. package/skills/excalidraw/app/dist/assets/subset-worker.chunk-BBqoITZT.js +1 -0
  156. package/skills/excalidraw/app/dist/assets/sv-SE-XGPEYMSR-DIhT7VhP.js +10 -0
  157. package/skills/excalidraw/app/dist/assets/swimlanes-42K2YHIH-C03UW4hY.js +1 -0
  158. package/skills/excalidraw/app/dist/assets/swimlanesDiagram-VR7AAH4N-OUQB4gXu.js +8 -0
  159. package/skills/excalidraw/app/dist/assets/ta-IN-2NMHFXQM-ollyGw17.js +9 -0
  160. package/skills/excalidraw/app/dist/assets/th-TH-HPSO5L25-GycTdvha.js +2 -0
  161. package/skills/excalidraw/app/dist/assets/timeline-definition-24CTP7MA-BWQ2CWiF.js +120 -0
  162. package/skills/excalidraw/app/dist/assets/tr-TR-DEFEU3FU-C0EQI1hS.js +7 -0
  163. package/skills/excalidraw/app/dist/assets/treeView-Q6P3EWNA-B4gjxheB.js +1 -0
  164. package/skills/excalidraw/app/dist/assets/treemap-WGGIJYW6-C6ZNbWbw.js +1 -0
  165. package/skills/excalidraw/app/dist/assets/uk-UA-QMV73CPH--gALSA3R.js +6 -0
  166. package/skills/excalidraw/app/dist/assets/vennDiagram-4TSXK5OY-DB2q0NWm.js +34 -0
  167. package/skills/excalidraw/app/dist/assets/vi-VN-M7AON7JQ-BU-don7N.js +5 -0
  168. package/skills/excalidraw/app/dist/assets/wardley-WFR3VGLG-CMlUPGFV.js +1 -0
  169. package/skills/excalidraw/app/dist/assets/wardleyDiagram-VM6X3IG4-D7s4KunH.js +78 -0
  170. package/skills/excalidraw/app/dist/assets/xychartDiagram-S5SC5T6Z-C3Ka4xi8.js +7 -0
  171. package/skills/excalidraw/app/dist/assets/zh-CN-LNUGB5OW-D-2E446q.js +10 -0
  172. package/skills/excalidraw/app/dist/assets/zh-HK-E62DVLB3-cftaz5Rd.js +1 -0
  173. package/skills/excalidraw/app/dist/assets/zh-TW-RAJ6MFWO-BO55Yqh9.js +9 -0
  174. package/skills/excalidraw/app/dist/fonts/Assistant/Assistant-Bold.woff2 +0 -0
  175. package/skills/excalidraw/app/dist/fonts/Assistant/Assistant-Medium.woff2 +0 -0
  176. package/skills/excalidraw/app/dist/fonts/Assistant/Assistant-Regular.woff2 +0 -0
  177. package/skills/excalidraw/app/dist/fonts/Assistant/Assistant-SemiBold.woff2 +0 -0
  178. package/skills/excalidraw/app/dist/fonts/Cascadia/CascadiaCode-Regular.woff2 +0 -0
  179. package/skills/excalidraw/app/dist/fonts/ComicShanns/ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2 +0 -0
  180. package/skills/excalidraw/app/dist/fonts/ComicShanns/ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2 +0 -0
  181. package/skills/excalidraw/app/dist/fonts/ComicShanns/ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2 +0 -0
  182. package/skills/excalidraw/app/dist/fonts/ComicShanns/ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2 +0 -0
  183. package/skills/excalidraw/app/dist/fonts/Excalifont/Excalifont-Regular-349fac6ca4700ffec595a7150a0d1e1d.woff2 +0 -0
  184. package/skills/excalidraw/app/dist/fonts/Excalifont/Excalifont-Regular-3f2c5db56cc93c5a6873b1361d730c16.woff2 +0 -0
  185. package/skills/excalidraw/app/dist/fonts/Excalifont/Excalifont-Regular-41b173a47b57366892116a575a43e2b6.woff2 +0 -0
  186. package/skills/excalidraw/app/dist/fonts/Excalifont/Excalifont-Regular-623ccf21b21ef6b3a0d87738f77eb071.woff2 +0 -0
  187. package/skills/excalidraw/app/dist/fonts/Excalifont/Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2 +0 -0
  188. package/skills/excalidraw/app/dist/fonts/Excalifont/Excalifont-Regular-b9dcf9d2e50a1eaf42fc664b50a3fd0d.woff2 +0 -0
  189. package/skills/excalidraw/app/dist/fonts/Excalifont/Excalifont-Regular-be310b9bcd4f1a43f571c46df7809174.woff2 +0 -0
  190. package/skills/excalidraw/app/dist/fonts/Liberation/LiberationSans-Regular.woff2 +0 -0
  191. package/skills/excalidraw/app/dist/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYE98RXi4EwSsbg.woff2 +0 -0
  192. package/skills/excalidraw/app/dist/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYEF8RXi4EwQ.woff2 +0 -0
  193. package/skills/excalidraw/app/dist/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTA3j6zbXWjgevT5.woff2 +0 -0
  194. package/skills/excalidraw/app/dist/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTQ3j6zbXWjgeg.woff2 +0 -0
  195. package/skills/excalidraw/app/dist/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTk3j6zbXWjgevT5.woff2 +0 -0
  196. package/skills/excalidraw/app/dist/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTo3j6zbXWjgevT5.woff2 +0 -0
  197. package/skills/excalidraw/app/dist/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTs3j6zbXWjgevT5.woff2 +0 -0
  198. package/skills/excalidraw/app/dist/fonts/Virgil/Virgil-Regular.woff2 +0 -0
  199. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-019d66dcad46dc156b162d267f981c20.woff2 +0 -0
  200. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-04b718e5623574919c8b0dea5f301444.woff2 +0 -0
  201. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-069e77aac84590e2e991d0a0176d34f2.woff2 +0 -0
  202. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-06c77b8c66e51ed6c63ccb502dd8b8af.woff2 +0 -0
  203. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-08e0dc436ad0ad61ba5558db0674d762.woff2 +0 -0
  204. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-093b9ef39a46ceae95a1df18a0a3a326.woff2 +0 -0
  205. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-095c169f3314805276f603a362766abd.woff2 +0 -0
  206. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-09850c4077f3fffe707905872e0e2460.woff2 +0 -0
  207. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-0986d134c05864f5025962eef9f994a0.woff2 +0 -0
  208. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-0b5d723fdc4e249c140f0909e87d03b4.woff2 +0 -0
  209. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-0f626226ba1272e832aea87bafd9720e.woff2 +0 -0
  210. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-0f7fb1e0d5015bb1371343153ecf7ce3.woff2 +0 -0
  211. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-0fa55a080fcd0f9dc2e0b0058b793df8.woff2 +0 -0
  212. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-0facdf1ea213ba40261022f5d5ed4493.woff2 +0 -0
  213. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-10a7ae9a371830a80c3d844acf1c02d7.woff2 +0 -0
  214. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-112c051027b2d766c19a519f6ee1f4f7.woff2 +0 -0
  215. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-11c345711937f0ba4b8f7b6b919c8440.woff2 +0 -0
  216. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-12b52b58eb3df36804b9a654ec9ee194.woff2 +0 -0
  217. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-13ae07ed2e272d26d59bc0691cd7117a.woff2 +0 -0
  218. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-13d2887ec8ee73c43acdabc52a05af7b.woff2 +0 -0
  219. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-145aa02cdd91946e67dc934e1acffe75.woff2 +0 -0
  220. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-15dc6d811c9cd078f9086a740d5a1038.woff2 +0 -0
  221. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-173945821411c09f70c95f98d590e697.woff2 +0 -0
  222. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-1b611157cd46bb184d4fa4dae2d6a2b8.woff2 +0 -0
  223. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-1e6fd68f1f3902ce48ce8c69df385622.woff2 +0 -0
  224. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-1ee544f0f1dac422545c505baa788992.woff2 +0 -0
  225. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-1fdc0c67ed57263a80fd108c1f6ccf24.woff2 +0 -0
  226. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-203b0e569e3b14aac86a003dc3fa523e.woff2 +0 -0
  227. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-20cc1bbf50e7efb442756cb605672c1f.woff2 +0 -0
  228. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-20e7bf72fa05de9adf7dbcc7bf51dde6.woff2 +0 -0
  229. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-21430ee05a1248901da8d0de08744d47.woff2 +0 -0
  230. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-23686f7f29da6e8008c36dd3a80c83d6.woff2 +0 -0
  231. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-23ad2d71b280f00b1363b95b7bea94eb.woff2 +0 -0
  232. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-23f228f3999c01983860012330e4be08.woff2 +0 -0
  233. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-24476a126f129212beb33f66853ea151.woff2 +0 -0
  234. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-24a21c1e4449222e8d1898d69ff3a404.woff2 +0 -0
  235. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-25b7f38e18f035f96cb5e547bd2bd08c.woff2 +0 -0
  236. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-29cec36cd205b211da97acabaa62f055.woff2 +0 -0
  237. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-2a26d20a23b00898ce82f09d2ee47c3f.woff2 +0 -0
  238. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-2adbc89c11e65905393d3dfc468b9d5b.woff2 +0 -0
  239. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-2b7441d46298788ac94e610ffcc709b6.woff2 +0 -0
  240. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-2b77e8ebfb2367ab2662396a60e7d320.woff2 +0 -0
  241. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-2cf96d082d35ea3d8106851223ad0d16.woff2 +0 -0
  242. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-2d43040e86ff03ba677f6f9c04cd0805.woff2 +0 -0
  243. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-2e33e8dc771ef5e1d9127d60a6b73679.woff2 +0 -0
  244. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-33432927cd87d40cfe393c7482bf221f.woff2 +0 -0
  245. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-353f33792a8f60dc69323ddf635a269e.woff2 +0 -0
  246. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-36925dfe329a45086cbb7fc5c20d45ac.woff2 +0 -0
  247. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-3717077e38f98d89eae729b6c14e56dc.woff2 +0 -0
  248. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-3756e81d3e149cf6099163ee79944fec.woff2 +0 -0
  249. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-395c35dd584b56b0789f58a0559beaf1.woff2 +0 -0
  250. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-3c9de2ae0ea4bc91a510942dfa4be8d2.woff2 +0 -0
  251. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-3cc70dbb64df5b21f1326cc24dee2195.woff2 +0 -0
  252. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-3e1f8f654357353bf0e04ba5c34b5f7f.woff2 +0 -0
  253. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-3e63ed8162808a9e425ed80a8bc79114.woff2 +0 -0
  254. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-3eaa538115d76932653c21d8dc28f207.woff2 +0 -0
  255. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4095eb84ef3874e2600247bee0b04026.woff2 +0 -0
  256. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-41521fade99856108931b4768b1b2648.woff2 +0 -0
  257. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-450da755d5bcb70906e1295e559b9602.woff2 +0 -0
  258. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-452225341522a7942f0f6aab1a5c91a3.woff2 +0 -0
  259. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4535823663ad81405188a528d8f2b1a2.woff2 +0 -0
  260. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4806e761d750087c2d734fc64596eaff.woff2 +0 -0
  261. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4a0fdb40036e87b40aa08dd30584cb85.woff2 +0 -0
  262. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4a38cc3e9cf104e69ba246d37f8cf135.woff2 +0 -0
  263. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4aca6a43e59aceee2166b0c7e4e85ef1.woff2 +0 -0
  264. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4bfaa8ffa64c5ee560aa2daba7c9cbd3.woff2 +0 -0
  265. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4dc6d5f188d5c96d44815cd1e81aa885.woff2 +0 -0
  266. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4ddc14ed3eb0c3e46364317dfc0144a3.woff2 +0 -0
  267. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4ee10ae43505e2e0bc62656ced49c0fa.woff2 +0 -0
  268. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-4f50e5136e136527280bc902c5817561.woff2 +0 -0
  269. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-51502f1206be09c565f1547c406e9558.woff2 +0 -0
  270. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-51a0e808bbc8361236ac521a119758a3.woff2 +0 -0
  271. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-52a84a22fd1369bffeaf21da2d6158dc.woff2 +0 -0
  272. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-5330a2119a716e4e7224ed108b085dac.woff2 +0 -0
  273. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-543fa46ace099a7099dad69123399400.woff2 +0 -0
  274. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-544fc28abe2c5c30e62383fd4dac255f.woff2 +0 -0
  275. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-54acdfc2166ad7fcbd074f75fd4a56ba.woff2 +0 -0
  276. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-5572b3513ba8df57a3d5d7303ee6b11b.woff2 +0 -0
  277. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-56467a5c8840c4d23a60b2f935114848.woff2 +0 -0
  278. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-56a32a7689abd0326e57c10c6c069bb4.woff2 +0 -0
  279. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-57862b464a55b18c7bf234ce22907d73.woff2 +0 -0
  280. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-583d166e56ba0de4b77eabb47ef67839.woff2 +0 -0
  281. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-5882ffa04f32584d26109137e2da4352.woff2 +0 -0
  282. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-58fd02350d0bc52cf1ca3bb32ce9766e.woff2 +0 -0
  283. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-5935a5775af3d5c6307ac667bd9ae74e.woff2 +0 -0
  284. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-59e9ff77b0efaf684bc09274fb6908c9.woff2 +0 -0
  285. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-5a1ce3117cfe90c48e8fb4a9a00f694d.woff2 +0 -0
  286. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-5a45d991244d4c7140217e1e5f5ca4f4.woff2 +0 -0
  287. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-5a7fac4b8b23a6e4e5ba0c9bf1756c91.woff2 +0 -0
  288. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-5b0ed6971aaab9c8ad563230bd5471a7.woff2 +0 -0
  289. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-5d2898fbc097a7e24c6f38d80587621e.woff2 +0 -0
  290. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-603aefd23e350ba7eb124273e3c9bcf1.woff2 +0 -0
  291. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-60a3089806700d379f11827ee9843b6b.woff2 +0 -0
  292. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-60a41c7e1c68f22424e6d22df544bc82.woff2 +0 -0
  293. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-642b26e2e5f5fb780b51b593dbc8c851.woff2 +0 -0
  294. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-66493ba5a8367f2928812f446f47b56a.woff2 +0 -0
  295. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-670ba603758d94268e8606f240a42e12.woff2 +0 -0
  296. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-671a2c20b1eb9e4ef8a192833940e319.woff2 +0 -0
  297. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-684d65f1793cac449dde5d59cb3c47fb.woff2 +0 -0
  298. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-69c09cc5fa3e55c74fc4821f76909cc3.woff2 +0 -0
  299. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-6ae5b42180ad70b971c91e7eefb8eba2.woff2 +0 -0
  300. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-6e092f71c1e634059ada0e52abadce67.woff2 +0 -0
  301. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-6f3256af8454371776bc46670d33cc65.woff2 +0 -0
  302. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-6fe5c5973cc06f74b2387a631ea36b88.woff2 +0 -0
  303. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-70c2eb8d64e71a42a834eb857ea9df51.woff2 +0 -0
  304. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-70e811fd7994e61f408c923de6ddd078.woff2 +0 -0
  305. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-7197d6fda6cba7c3874c53d6381ca239.woff2 +0 -0
  306. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-72252d73220fa3cd856677888cee1635.woff2 +0 -0
  307. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-72536a3d71b694a0d53dd90ddceae41e.woff2 +0 -0
  308. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-726303e0774b4e678bff8c2deb6ca603.woff2 +0 -0
  309. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-733171b4ffcd17ea1fe1c0ba627173bf.woff2 +0 -0
  310. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-739bc1a567439c7cffcd1614644593d2.woff2 +0 -0
  311. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-73e309718fd16cea44b4d54a33581811.woff2 +0 -0
  312. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-7494dc504ae00ee9cd0505f990f88c5d.woff2 +0 -0
  313. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-74e2263a91439c25b91d5132ce9f4d62.woff2 +0 -0
  314. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-761d05e3cd968cf574166867998ef06a.woff2 +0 -0
  315. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-7718fe60986d8b42b1be9c5ace5ccf25.woff2 +0 -0
  316. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-774d4f764a1299da5d28ec2f2ffe0d69.woff2 +0 -0
  317. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-79d494361ae093b69e74ee9dbe65bfd4.woff2 +0 -0
  318. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-79f007c1c6d07557120982951ea67998.woff2 +0 -0
  319. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-7a07ddc0f0c0f5f4a9bad6ee3dda66b5.woff2 +0 -0
  320. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-7ab2bed91166a9dca83a5ebfbe2a7f38.woff2 +0 -0
  321. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-7ccce86603f80a099ddb0cb21d4ae3e3.woff2 +0 -0
  322. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-7e4bde7e9c7f84cd34d8a845e384c746.woff2 +0 -0
  323. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-7e929f262f30c8ee78bf398150b1a7cd.woff2 +0 -0
  324. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-7eb9fffd1aa890d07d0f88cc82e6cfe4.woff2 +0 -0
  325. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-7f855356ab893b0d2b9c1c83b8116f0e.woff2 +0 -0
  326. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-829615148e6357d826b9242eb7fbbd1e.woff2 +0 -0
  327. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-866fa7613df6b3fd272bcfd4530c0bb9.woff2 +0 -0
  328. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-87599f94b6cc129d505b375798d0d751.woff2 +0 -0
  329. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-8c2f33cee3993174f7e87c28e4bf42ee.woff2 +0 -0
  330. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-8d3bcabb847b56243b16afe62adaaf21.woff2 +0 -0
  331. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-8de5b863cb50dfefdd07cb11c774d579.woff2 +0 -0
  332. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-8e9f97f01034820170065b2921b4fb5e.woff2 +0 -0
  333. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-8f476c4c99813d57cbe6eca4727388ad.woff2 +0 -0
  334. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-903bb6865f3452e2fda42e3a25547bc5.woff2 +0 -0
  335. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-91ddb2969bf2d31ba02ad82998d1314c.woff2 +0 -0
  336. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-938d90c10ff8c20386af7f242c05d6b0.woff2 +0 -0
  337. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-93fc8f28a33234bcadf1527cafabd502.woff2 +0 -0
  338. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-95429962233afd82db1c27df1500a28c.woff2 +0 -0
  339. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-9544732d2e62d1a429674f8ee41b5d3a.woff2 +0 -0
  340. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-9592bfc861f07bcb8d75c196b370e548.woff2 +0 -0
  341. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-95bfd249da4902577b4b7d76ebdd0b44.woff2 +0 -0
  342. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-968cffdc8ee679da094e77ebf50f58ef.woff2 +0 -0
  343. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-97f7f48ce90c9429bf32ae51469db74d.woff2 +0 -0
  344. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-982b630266d87db93d2539affb1275c6.woff2 +0 -0
  345. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-98f2ad84457de7f3740d9920b8fa8667.woff2 +0 -0
  346. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-99a16ef6a64934d5781933dbd9c46b2e.woff2 +0 -0
  347. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-9cfb2a77a4e45025105ad29a1748b90d.woff2 +0 -0
  348. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-9d81066dd2b337c938df6e90380a00dc.woff2 +0 -0
  349. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-9eb5a99df4e76ac3363453ac9ca288b1.woff2 +0 -0
  350. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-a004ddfcb26e67bd6e678c8ed19e25ce.woff2 +0 -0
  351. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-a0ca5df4258213d7fc9fce80f65ce760.woff2 +0 -0
  352. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-a1f916d6039285c4ffb900cd654e418f.woff2 +0 -0
  353. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-a203b91dad570bf05a58c3c3ddb529bf.woff2 +0 -0
  354. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-a365e82ed54697a52f27adcea1315fe8.woff2 +0 -0
  355. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-a4c34be6d42152e64b0df90bc4607f64.woff2 +0 -0
  356. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-a7accba310e821da5505f71c03b76bdb.woff2 +0 -0
  357. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-aa0d470430e6391eca720c7cfa44446f.woff2 +0 -0
  358. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-aa5c9ca6cf4fba00433b7aa3fa10671a.woff2 +0 -0
  359. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-ac9ceb44437becc3e9c4dbfebab7fc2d.woff2 +0 -0
  360. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-b1220a3c61f85cc0408deedb4c5f57a2.woff2 +0 -0
  361. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-b358f7a51ece39a3247942b1feabdb29.woff2 +0 -0
  362. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-b57aaedfd8ebdf3931f25119dc6a5eb2.woff2 +0 -0
  363. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-b5c1596551c256e0e9cf02028595b092.woff2 +0 -0
  364. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-b6d128682ee29e471486354d486a1b90.woff2 +0 -0
  365. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-b6fd38ca30869792244804b04bc058da.woff2 +0 -0
  366. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-b7d203b051eff504ff59ddca7576b6a9.woff2 +0 -0
  367. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-b96d9226ce77ec94ceca043d712182e6.woff2 +0 -0
  368. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-ba3de316d63c7e339987b16f41a0b879.woff2 +0 -0
  369. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-bafff7a14c27403dcc6cf1432e8ea836.woff2 +0 -0
  370. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-bd77e3c7f9e0b072d96af37f73d1aa32.woff2 +0 -0
  371. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-be549ab72f0719d606a5c01e2c0219b6.woff2 +0 -0
  372. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-c16ed9740b85badf16e86ea782a3062f.woff2 +0 -0
  373. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-c1f94158256bb1f3bf665b053d895af9.woff2 +0 -0
  374. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-c40533fdf4cc57177b12803598af7e59.woff2 +0 -0
  375. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-c4a687ac4f0c2766eefc9f77ed99cddf.woff2 +0 -0
  376. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-c69f61a4ab18d0488c8d1fc12e7028e8.woff2 +0 -0
  377. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-c8b71798409ccc126ee264a00aadcf21.woff2 +0 -0
  378. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-c99eda15fc26a2941579560f76c3a5cf.woff2 +0 -0
  379. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-cb17fc3db95f6d139afc9d31a8e93293.woff2 +0 -0
  380. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-cbaaefaaf326668277aa24dfa93c4d28.woff2 +0 -0
  381. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-cd145ce4a0ea18469358df53c207bc1b.woff2 +0 -0
  382. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-cdbce89e82cc1ab53a2decbf5819278f.woff2 +0 -0
  383. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-ce4884f96f11589608b76b726a755803.woff2 +0 -0
  384. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-cf2cc71752631e579e35b0e423bf2638.woff2 +0 -0
  385. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-cf6ff4e0f491ca0cf3038187a997b9b4.woff2 +0 -0
  386. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-cfb211578629b7e8153b37240de6a9d5.woff2 +0 -0
  387. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-d0cf73942fea1c74edbdf0b3011f4656.woff2 +0 -0
  388. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-d2666cbed13462c5dc36fa2f15c202ca.woff2 +0 -0
  389. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-d3716376641d615e2995605b29bca7b6.woff2 +0 -0
  390. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-dac48066b5883d8b4551fc584f0c2a3e.woff2 +0 -0
  391. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-dbea1af6dcd9860be40c3d18254338f5.woff2 +0 -0
  392. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-e11567fd2accf9957cd0d3c2be937d87.woff2 +0 -0
  393. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-e2ead7ea7da0437f085f42ffc05f8d13.woff2 +0 -0
  394. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-e3fcf5180fd466c8915c4e8069491054.woff2 +0 -0
  395. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-e480d9c614742d05f0e78f274f1e69e6.woff2 +0 -0
  396. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-e4bca6cfa53e499cae0a6be4894a90e9.woff2 +0 -0
  397. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-e51ef413167c6e14e0c0fdcc585f2fc9.woff2 +0 -0
  398. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-e5f453bb04da18eed01675eeebd88bf8.woff2 +0 -0
  399. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-e656f091b9dc4709722c9f4b84d3c797.woff2 +0 -0
  400. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-ec181b795ac1fb5a50d700b6e996d745.woff2 +0 -0
  401. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-ee8bae97908d5147b423f77ad0d3c1bb.woff2 +0 -0
  402. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-f0f13b5c60e0af5553bd359f5513be1b.woff2 +0 -0
  403. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-f2b54d4e7be0eaefe1c2c56836fa5368.woff2 +0 -0
  404. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-f56414bf9bced67990def8660e306759.woff2 +0 -0
  405. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-f5d079153c99a25b9be5b8583c4cc8a7.woff2 +0 -0
  406. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-f6032fc06eb20480f096199713f70885.woff2 +0 -0
  407. package/skills/excalidraw/app/dist/fonts/Xiaolai/Xiaolai-Regular-f8ee5d36068a42b51d0e4a1116cfcec1.woff2 +0 -0
  408. package/skills/excalidraw/app/dist/index.html +16 -0
  409. package/skills/excalidraw/app/index.html +14 -0
  410. package/skills/excalidraw/app/package.json +20 -0
  411. package/skills/excalidraw/app/pnpm-lock.yaml +2593 -0
  412. package/skills/excalidraw/app/src/main.jsx +334 -0
  413. package/skills/excalidraw/app/src/scene.js +247 -0
  414. package/skills/excalidraw/app/vite.config.js +19 -0
  415. package/skills/excalidraw/assets/examples/flowchart.excalidraw +19 -0
  416. package/skills/excalidraw/references/setup.md +27 -0
  417. package/skills/excalidraw/references/skeleton.md +84 -0
  418. package/skills/excalidraw/references/style.md +46 -0
  419. package/skills/excalidraw/references/sync-protocol.md +47 -0
  420. package/skills/excalidraw/scripts/excal.mjs +416 -0
  421. package/skills/excalidraw/scripts/lib.mjs +81 -0
  422. package/skills/excalidraw/scripts/server.mjs +476 -0
@@ -0,0 +1,476 @@
1
+ #!/usr/bin/env node
2
+ // Local Excalidraw sync daemon.
3
+ // - serves the prebuilt app (app/dist)
4
+ // - watches registered .excalidraw files and pushes changes to open windows (WebSocket)
5
+ // - writes edits coming from the window back to disk (atomic, rev-checked)
6
+ // - relays PNG snapshot requests to a connected window
7
+ import crypto from "node:crypto";
8
+ import fs from "node:fs";
9
+ import http from "node:http";
10
+ import path from "node:path";
11
+ import {
12
+ DIST_DIR,
13
+ ensureStateDir,
14
+ fileIdFor,
15
+ HISTORY_DIR,
16
+ REGISTRY_FILE,
17
+ readJSON,
18
+ readToken,
19
+ realPathOf,
20
+ STATE_FILE,
21
+ sha,
22
+ writeFileAtomic,
23
+ } from "./lib.mjs";
24
+
25
+ const PREFERRED_PORT = Number(process.env.EXCAL_PORT || 47813);
26
+ const IDLE_MS = Number(process.env.EXCAL_IDLE_MINUTES || 30) * 60_000;
27
+ const HISTORY_KEEP = 50;
28
+ const USER_HISTORY_INTERVAL_MS = 5 * 60_000;
29
+ const MAX_BODY = 64 * 1024 * 1024;
30
+
31
+ ensureStateDir();
32
+ const TOKEN = readToken();
33
+ let PORT = 0;
34
+ let lastActivity = Date.now();
35
+
36
+ /** @type {Map<string, any>} */
37
+ const entries = new Map();
38
+ /** @type {Map<string, {watcher: fs.FSWatcher, ids: Set<string>}>} */
39
+ const dirWatchers = new Map();
40
+ /** @type {Map<string, {res: http.ServerResponse, timer: NodeJS.Timeout}>} */
41
+ const pendingSnapshots = new Map();
42
+ const registry = readJSON(REGISTRY_FILE, {});
43
+
44
+ function log(...args) {
45
+ console.log(new Date().toISOString(), ...args);
46
+ }
47
+
48
+ function saveRegistry() {
49
+ fs.writeFileSync(REGISTRY_FILE, JSON.stringify(registry, null, 2), { mode: 0o600 });
50
+ }
51
+
52
+ // ---------- file entries ----------
53
+
54
+ function getEntry(id) {
55
+ if (entries.has(id)) return entries.get(id);
56
+ const filePath = registry[id];
57
+ if (!filePath) return null;
58
+ return activate(id, filePath);
59
+ }
60
+
61
+ function activate(id, filePath) {
62
+ let content = "";
63
+ try {
64
+ content = fs.readFileSync(filePath, "utf8");
65
+ } catch {}
66
+ const entry = {
67
+ id,
68
+ path: filePath,
69
+ rev: 1,
70
+ lastContent: content,
71
+ lastHash: sha(content),
72
+ lastUserHistoryAt: 0,
73
+ clients: new Map(),
74
+ timer: null,
75
+ };
76
+ entries.set(id, entry);
77
+ watchDir(entry);
78
+ return entry;
79
+ }
80
+
81
+ function watchDir(entry) {
82
+ const dir = path.dirname(entry.path);
83
+ let w = dirWatchers.get(dir);
84
+ if (!w) {
85
+ // Watch the directory, not the file: editors save via temp file + rename,
86
+ // which silently detaches a file-level watcher.
87
+ const watcher = fs.watch(dir, (_event, filename) => {
88
+ const ids = dirWatchers.get(dir)?.ids ?? new Set();
89
+ for (const id of ids) {
90
+ const e = entries.get(id);
91
+ if (!e) continue;
92
+ if (filename && filename.toString() !== path.basename(e.path)) continue;
93
+ scheduleCheck(e);
94
+ }
95
+ });
96
+ watcher.on("error", (err) => log("watch error", dir, err.message));
97
+ w = { watcher, ids: new Set() };
98
+ dirWatchers.set(dir, w);
99
+ }
100
+ w.ids.add(entry.id);
101
+ }
102
+
103
+ function scheduleCheck(entry) {
104
+ clearTimeout(entry.timer);
105
+ entry.timer = setTimeout(() => checkFile(entry), 80);
106
+ }
107
+
108
+ /** Pick up an external change on disk. Returns true when a new revision was accepted. */
109
+ function checkFile(entry, attempt = 0) {
110
+ let content;
111
+ try {
112
+ content = fs.readFileSync(entry.path, "utf8");
113
+ } catch (err) {
114
+ if (err.code === "ENOENT" && attempt < 3) {
115
+ entry.timer = setTimeout(() => checkFile(entry, attempt + 1), 150);
116
+ } else if (err.code === "ENOENT") {
117
+ broadcast(entry, "problem", { message: `파일이 없습니다: ${entry.path}` });
118
+ }
119
+ return false;
120
+ }
121
+ const hash = sha(content);
122
+ if (hash === entry.lastHash) return false;
123
+ try {
124
+ JSON.parse(content);
125
+ } catch (err) {
126
+ broadcast(entry, "problem", { message: `JSON 파싱 실패: ${err.message}` });
127
+ return false;
128
+ }
129
+ saveHistory(entry, entry.lastContent);
130
+ entry.lastContent = content;
131
+ entry.lastHash = hash;
132
+ entry.rev += 1;
133
+ log("disk change", entry.path, "rev", entry.rev);
134
+ broadcast(entry, "scene", { rev: entry.rev, content, origin: "disk" });
135
+ return true;
136
+ }
137
+
138
+ function saveHistory(entry, content) {
139
+ if (!content) return;
140
+ const dir = path.join(HISTORY_DIR, entry.id);
141
+ fs.mkdirSync(dir, { recursive: true });
142
+ fs.writeFileSync(path.join(dir, `${Date.now()}.excalidraw`), content);
143
+ const files = fs.readdirSync(dir).sort();
144
+ for (const f of files.slice(0, Math.max(0, files.length - HISTORY_KEEP))) {
145
+ fs.rmSync(path.join(dir, f), { force: true });
146
+ }
147
+ fs.writeFileSync(path.join(dir, "SOURCE"), entry.path + "\n");
148
+ }
149
+
150
+ // ---------- minimal WebSocket (server -> client text frames only) ----------
151
+
152
+ function wsFrame(opcode, payload = Buffer.alloc(0)) {
153
+ const len = payload.length;
154
+ let header;
155
+ if (len < 126) header = Buffer.from([0x80 | opcode, len]);
156
+ else if (len < 65536) {
157
+ header = Buffer.alloc(4);
158
+ header[0] = 0x80 | opcode;
159
+ header[1] = 126;
160
+ header.writeUInt16BE(len, 2);
161
+ } else {
162
+ header = Buffer.alloc(10);
163
+ header[0] = 0x80 | opcode;
164
+ header[1] = 127;
165
+ header.writeBigUInt64BE(BigInt(len), 2);
166
+ }
167
+ return Buffer.concat([header, payload]);
168
+ }
169
+
170
+ function wsSend(socket, event, data) {
171
+ if (!socket.destroyed) socket.write(wsFrame(0x1, Buffer.from(JSON.stringify({ event, data }))));
172
+ }
173
+
174
+ function broadcast(entry, event, data, exceptClientId) {
175
+ for (const [clientId, socket] of entry.clients) {
176
+ if (clientId === exceptClientId) continue;
177
+ wsSend(socket, event, data);
178
+ }
179
+ }
180
+
181
+ function totalClients() {
182
+ let n = 0;
183
+ for (const e of entries.values()) n += e.clients.size;
184
+ return n;
185
+ }
186
+
187
+ // ---------- http helpers ----------
188
+
189
+ function send(res, status, body, headers = {}) {
190
+ const isBuf = Buffer.isBuffer(body);
191
+ const data = isBuf ? body : typeof body === "string" ? body : JSON.stringify(body);
192
+ res.writeHead(status, {
193
+ "content-type": isBuf
194
+ ? "application/octet-stream"
195
+ : typeof body === "string"
196
+ ? "text/plain; charset=utf-8"
197
+ : "application/json",
198
+ "cache-control": "no-store",
199
+ ...headers,
200
+ });
201
+ res.end(data);
202
+ }
203
+
204
+ function readBody(req) {
205
+ return new Promise((resolve, reject) => {
206
+ const chunks = [];
207
+ let size = 0;
208
+ req.on("data", (c) => {
209
+ size += c.length;
210
+ if (size > MAX_BODY) {
211
+ reject(new Error("body too large"));
212
+ req.destroy();
213
+ } else chunks.push(c);
214
+ });
215
+ req.on("end", () => resolve(Buffer.concat(chunks)));
216
+ req.on("error", reject);
217
+ });
218
+ }
219
+
220
+ const MIME = {
221
+ ".html": "text/html; charset=utf-8",
222
+ ".js": "text/javascript; charset=utf-8",
223
+ ".css": "text/css; charset=utf-8",
224
+ ".json": "application/json",
225
+ ".svg": "image/svg+xml",
226
+ ".png": "image/png",
227
+ ".ico": "image/x-icon",
228
+ ".woff2": "font/woff2",
229
+ ".woff": "font/woff",
230
+ ".ttf": "font/ttf",
231
+ };
232
+
233
+ function serveStatic(req, res, pathname) {
234
+ const rel = decodeURIComponent(pathname).replace(/^\/+/, "");
235
+ let file = path.join(DIST_DIR, rel);
236
+ if (!file.startsWith(DIST_DIR)) return send(res, 403, "forbidden");
237
+ if (!rel || !fs.existsSync(file) || fs.statSync(file).isDirectory()) file = path.join(DIST_DIR, "index.html");
238
+ if (!fs.existsSync(file)) return send(res, 503, "app is not built. run: excal build");
239
+ const ext = path.extname(file);
240
+ const immutable = rel.startsWith("assets/") || rel.startsWith("fonts/");
241
+ res.writeHead(200, {
242
+ "content-type": MIME[ext] || "application/octet-stream",
243
+ "cache-control": immutable ? "public, max-age=31536000, immutable" : "no-cache",
244
+ });
245
+ fs.createReadStream(file).pipe(res);
246
+ }
247
+
248
+ // ---------- routes ----------
249
+
250
+ async function handleApi(req, res, url) {
251
+ const parts = url.pathname.split("/").filter(Boolean); // ["api", ...]
252
+ const method = req.method;
253
+
254
+ if (parts[1] === "health") return send(res, 200, { ok: true, pid: process.pid, port: PORT });
255
+
256
+ if (parts[1] === "status") {
257
+ return send(res, 200, {
258
+ pid: process.pid,
259
+ port: PORT,
260
+ files: [...entries.values()].map((e) => ({ id: e.id, path: e.path, rev: e.rev, clients: e.clients.size })),
261
+ });
262
+ }
263
+
264
+ if (parts[1] === "shutdown" && method === "POST") {
265
+ send(res, 200, { ok: true });
266
+ setTimeout(shutdown, 50);
267
+ return;
268
+ }
269
+
270
+ if (parts[1] === "files" && parts.length === 2 && method === "POST") {
271
+ const { path: p } = JSON.parse((await readBody(req)).toString() || "{}");
272
+ if (!p) return send(res, 400, { error: "path required" });
273
+ const abs = realPathOf(p);
274
+ if (!fs.existsSync(abs)) return send(res, 404, { error: `file not found: ${abs}` });
275
+ const id = fileIdFor(abs);
276
+ if (registry[id] !== abs) {
277
+ registry[id] = abs;
278
+ saveRegistry();
279
+ }
280
+ const entry = getEntry(id);
281
+ checkFile(entry);
282
+ return send(res, 200, {
283
+ id,
284
+ path: abs,
285
+ rev: entry.rev,
286
+ clients: entry.clients.size,
287
+ url: `http://127.0.0.1:${PORT}/?file=${id}&token=${TOKEN}`,
288
+ });
289
+ }
290
+
291
+ if (parts[1] === "snapshots" && parts[2] && method === "POST") {
292
+ const pending = pendingSnapshots.get(parts[2]);
293
+ const body = await readBody(req);
294
+ if (!pending) return send(res, 404, { error: "unknown snapshot request" });
295
+ pendingSnapshots.delete(parts[2]);
296
+ clearTimeout(pending.timer);
297
+ if (req.headers["content-type"]?.startsWith("application/json")) {
298
+ send(pending.res, 500, JSON.parse(body.toString()));
299
+ } else {
300
+ send(pending.res, 200, body, { "content-type": "image/png" });
301
+ }
302
+ return send(res, 204, "");
303
+ }
304
+
305
+ if (parts[1] === "files" && parts[2]) {
306
+ const entry = getEntry(parts[2]);
307
+ if (!entry) return send(res, 404, { error: "unknown file id" });
308
+ const action = parts[3];
309
+
310
+ if (action === "scene" && method === "GET") {
311
+ checkFile(entry);
312
+ return send(res, 200, {
313
+ rev: entry.rev,
314
+ content: entry.lastContent,
315
+ path: entry.path,
316
+ name: path.basename(entry.path),
317
+ });
318
+ }
319
+
320
+ if (action === "scene" && method === "PUT") {
321
+ const { baseRev, content, clientId } = JSON.parse((await readBody(req)).toString());
322
+ checkFile(entry); // flush a disk change the watcher may not have delivered yet
323
+ if (baseRev !== entry.rev) return send(res, 409, { rev: entry.rev, content: entry.lastContent });
324
+ try {
325
+ JSON.parse(content);
326
+ } catch {
327
+ return send(res, 400, { error: "invalid JSON" });
328
+ }
329
+ const hash = sha(content);
330
+ if (hash !== entry.lastHash) {
331
+ if (Date.now() - entry.lastUserHistoryAt > USER_HISTORY_INTERVAL_MS) {
332
+ saveHistory(entry, entry.lastContent);
333
+ entry.lastUserHistoryAt = Date.now();
334
+ }
335
+ writeFileAtomic(entry.path, content);
336
+ entry.lastContent = content;
337
+ entry.lastHash = hash;
338
+ entry.rev += 1;
339
+ broadcast(entry, "scene", { rev: entry.rev, content, origin: clientId }, clientId);
340
+ }
341
+ return send(res, 200, { rev: entry.rev });
342
+ }
343
+
344
+ if (action === "snapshot" && method === "POST") {
345
+ checkFile(entry);
346
+ const [clientId, client] = [...entry.clients.entries()][0] ?? [];
347
+ if (!client) return send(res, 409, { error: "no-window" });
348
+ const reqId = crypto.randomUUID();
349
+ const timer = setTimeout(() => {
350
+ pendingSnapshots.delete(reqId);
351
+ send(res, 504, { error: "snapshot timeout" });
352
+ }, 20_000);
353
+ pendingSnapshots.set(reqId, { res, timer });
354
+ wsSend(client, "snapshot", { reqId, rev: entry.rev });
355
+ log("snapshot requested", entry.path, "client", clientId);
356
+ return;
357
+ }
358
+ }
359
+
360
+ return send(res, 404, { error: "not found" });
361
+ }
362
+
363
+ const hostOk = (host = "") => host === `127.0.0.1:${PORT}` || host === `localhost:${PORT}`;
364
+
365
+ const server = http.createServer(async (req, res) => {
366
+ lastActivity = Date.now();
367
+ const host = req.headers.host || "";
368
+ if (!hostOk(host)) return send(res, 403, "bad host");
369
+ const url = new URL(req.url, `http://${host}`);
370
+ try {
371
+ if (url.pathname.startsWith("/api/")) {
372
+ const token = req.headers["x-excal-token"] || url.searchParams.get("token");
373
+ if (token !== TOKEN) return send(res, 401, { error: "bad token" });
374
+ return await handleApi(req, res, url);
375
+ }
376
+ return serveStatic(req, res, url.pathname);
377
+ } catch (err) {
378
+ log("error", err.stack || err.message);
379
+ if (!res.headersSent) send(res, 500, { error: err.message });
380
+ }
381
+ });
382
+
383
+ server.on("upgrade", (req, socket) => {
384
+ lastActivity = Date.now();
385
+ const reject = (code) => socket.end(`HTTP/1.1 ${code}\r\nConnection: close\r\n\r\n`);
386
+ if (!hostOk(req.headers.host)) return reject("403 Forbidden");
387
+ const url = new URL(req.url, `http://${req.headers.host}`);
388
+ const m = url.pathname.match(/^\/api\/files\/([a-f0-9]+)\/ws$/);
389
+ if (!m || url.searchParams.get("token") !== TOKEN) return reject("401 Unauthorized");
390
+ const entry = getEntry(m[1]);
391
+ const key = req.headers["sec-websocket-key"];
392
+ if (!entry || !key) return reject("404 Not Found");
393
+ const accept = crypto
394
+ .createHash("sha1")
395
+ .update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
396
+ .digest("base64");
397
+ socket.write(
398
+ `HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: ${accept}\r\n\r\n`,
399
+ );
400
+ socket.setNoDelay(true);
401
+ const clientId = url.searchParams.get("clientId") || crypto.randomUUID();
402
+ entry.clients.set(clientId, socket);
403
+ checkFile(entry);
404
+ wsSend(socket, "hello", { rev: entry.rev });
405
+ const ping = setInterval(() => !socket.destroyed && socket.write(wsFrame(0x9)), 20_000);
406
+ // The browser never sends data frames; only watch for a close frame.
407
+ socket.on("data", (buf) => {
408
+ if ((buf[0] & 0x0f) === 0x8) socket.end(wsFrame(0x8));
409
+ });
410
+ const cleanup = () => {
411
+ clearInterval(ping);
412
+ if (entry.clients.get(clientId) === socket) entry.clients.delete(clientId);
413
+ lastActivity = Date.now();
414
+ };
415
+ socket.on("close", cleanup);
416
+ socket.on("error", cleanup);
417
+ });
418
+
419
+ function shutdown() {
420
+ log("shutdown");
421
+ const state = readJSON(STATE_FILE, null);
422
+ if (state?.pid === process.pid) fs.rmSync(STATE_FILE, { force: true });
423
+ for (const e of entries.values()) for (const socket of e.clients.values()) socket.end(wsFrame(0x8));
424
+ process.exit(0);
425
+ }
426
+
427
+ process.on("SIGTERM", shutdown);
428
+ process.on("SIGINT", shutdown);
429
+
430
+ setInterval(() => {
431
+ if (totalClients() === 0 && Date.now() - lastActivity > IDLE_MS) {
432
+ log("idle timeout");
433
+ shutdown();
434
+ }
435
+ }, 60_000).unref();
436
+
437
+ function listen(port) {
438
+ server.once("error", (err) => {
439
+ if (err.code === "EADDRINUSE" && port !== 0) return listen(0);
440
+ throw err;
441
+ });
442
+ server.listen(port, "127.0.0.1", () => {
443
+ PORT = server.address().port;
444
+ fs.writeFileSync(
445
+ STATE_FILE,
446
+ JSON.stringify({ pid: process.pid, port: PORT, startedAt: new Date().toISOString() }),
447
+ {
448
+ mode: 0o600,
449
+ },
450
+ );
451
+ log(`listening on http://127.0.0.1:${PORT}`);
452
+ });
453
+ }
454
+
455
+ // Single instance: bail out if a healthy daemon already owns the state file.
456
+ const existing = readJSON(STATE_FILE, null);
457
+ if (existing?.pid && existing.pid !== process.pid) {
458
+ let alive = false;
459
+ try {
460
+ process.kill(existing.pid, 0);
461
+ alive = true;
462
+ } catch {}
463
+ if (alive) {
464
+ try {
465
+ const r = await fetch(`http://127.0.0.1:${existing.port}/api/health`, {
466
+ headers: { "x-excal-token": TOKEN },
467
+ signal: AbortSignal.timeout(1000),
468
+ });
469
+ if (r.ok) {
470
+ log("another daemon is running", existing);
471
+ process.exit(0);
472
+ }
473
+ } catch {}
474
+ }
475
+ }
476
+ listen(PREFERRED_PORT);