sketchboard-app 1.0.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/bin/sketchboard.js +49 -0
- package/package.json +38 -0
- package/public/Assistant-Regular.woff2 +0 -0
- package/public/Cascadia.woff2 +0 -0
- package/public/Virgil.woff2 +0 -0
- package/public/_headers +2 -0
- package/public/android-chrome-192x192.png +0 -0
- package/public/android-chrome-512x512.png +0 -0
- package/public/apple-touch-icon.png +0 -0
- package/public/assets/CodeMirrorEditor-DLdTFwmz.js +2 -0
- package/public/assets/CodeMirrorEditor-DLdTFwmz.js.map +1 -0
- package/public/assets/_basePickBy-ZfSBwMAc.js +2 -0
- package/public/assets/_basePickBy-ZfSBwMAc.js.map +1 -0
- package/public/assets/_baseUniq-BrAtqm7r.js +2 -0
- package/public/assets/_baseUniq-BrAtqm7r.js.map +1 -0
- package/public/assets/architectureDiagram-VXUJARFQ-CM5vRAuo.js +37 -0
- package/public/assets/architectureDiagram-VXUJARFQ-CM5vRAuo.js.map +1 -0
- package/public/assets/blockDiagram-VD42YOAC-B1Z6hTXo.js +123 -0
- package/public/assets/blockDiagram-VD42YOAC-B1Z6hTXo.js.map +1 -0
- package/public/assets/bug-issue-template-BID_ABWq.js +12 -0
- package/public/assets/bug-issue-template-BID_ABWq.js.map +1 -0
- package/public/assets/c4Diagram-YG6GDRKO-Cv9Zizqx.js +11 -0
- package/public/assets/c4Diagram-YG6GDRKO-Cv9Zizqx.js.map +1 -0
- package/public/assets/chunk-4BX2VUAB-Bb3u24_X.js +2 -0
- package/public/assets/chunk-4BX2VUAB-Bb3u24_X.js.map +1 -0
- package/public/assets/chunk-55IACEB6-91xqgfYx.js +2 -0
- package/public/assets/chunk-55IACEB6-91xqgfYx.js.map +1 -0
- package/public/assets/chunk-B4BG7PRW-CQKyBsz0.js +166 -0
- package/public/assets/chunk-B4BG7PRW-CQKyBsz0.js.map +1 -0
- package/public/assets/chunk-DI55MBZ5-BY2TlPT6.js +221 -0
- package/public/assets/chunk-DI55MBZ5-BY2TlPT6.js.map +1 -0
- package/public/assets/chunk-FMBD7UC4-B2zhnDqu.js +16 -0
- package/public/assets/chunk-FMBD7UC4-B2zhnDqu.js.map +1 -0
- package/public/assets/chunk-QN33PNHL-CkKTlLkk.js +2 -0
- package/public/assets/chunk-QN33PNHL-CkKTlLkk.js.map +1 -0
- package/public/assets/chunk-QZHKN3VN-CD9rwyT-.js +2 -0
- package/public/assets/chunk-QZHKN3VN-CD9rwyT-.js.map +1 -0
- package/public/assets/chunk-TZMSLE5B-CGEL2dZG.js +2 -0
- package/public/assets/chunk-TZMSLE5B-CGEL2dZG.js.map +1 -0
- package/public/assets/classDiagram-2ON5EDUG-OE1zz8Rb.js +2 -0
- package/public/assets/classDiagram-2ON5EDUG-OE1zz8Rb.js.map +1 -0
- package/public/assets/classDiagram-v2-WZHVMYZB-OE1zz8Rb.js +2 -0
- package/public/assets/classDiagram-v2-WZHVMYZB-OE1zz8Rb.js.map +1 -0
- package/public/assets/clone-DKsuYKPC.js +2 -0
- package/public/assets/clone-DKsuYKPC.js.map +1 -0
- package/public/assets/codemirror.chunk-CLhMQAUm.js +13 -0
- package/public/assets/codemirror.chunk-CLhMQAUm.js.map +1 -0
- package/public/assets/cose-bilkent-S5V4N54A-BOimuZ77.js +2 -0
- package/public/assets/cose-bilkent-S5V4N54A-BOimuZ77.js.map +1 -0
- package/public/assets/cytoscape.esm-CyJtwmzi.js +332 -0
- package/public/assets/cytoscape.esm-CyJtwmzi.js.map +1 -0
- package/public/assets/dagre-6UL2VRFP-DYyliwSQ.js +5 -0
- package/public/assets/dagre-6UL2VRFP-DYyliwSQ.js.map +1 -0
- package/public/assets/diagram-PSM6KHXK-BLc04vxi.js +25 -0
- package/public/assets/diagram-PSM6KHXK-BLc04vxi.js.map +1 -0
- package/public/assets/diagram-QEK2KX5R-ukB6kMmO.js +44 -0
- package/public/assets/diagram-QEK2KX5R-ukB6kMmO.js.map +1 -0
- package/public/assets/diagram-S2PKOQOG-DaX2mZca.js +25 -0
- package/public/assets/diagram-S2PKOQOG-DaX2mZca.js.map +1 -0
- package/public/assets/erDiagram-Q2GNP2WA-DL9LpaEF.js +61 -0
- package/public/assets/erDiagram-Q2GNP2WA-DL9LpaEF.js.map +1 -0
- package/public/assets/flowDiagram-NV44I4VS-CIstAb2z.js +163 -0
- package/public/assets/flowDiagram-NV44I4VS-CIstAb2z.js.map +1 -0
- package/public/assets/ganttDiagram-JELNMOA3-CNSqBTtR.js +268 -0
- package/public/assets/ganttDiagram-JELNMOA3-CNSqBTtR.js.map +1 -0
- package/public/assets/gitGraphDiagram-NY62KEGX-DxG2NOZV.js +66 -0
- package/public/assets/gitGraphDiagram-NY62KEGX-DxG2NOZV.js.map +1 -0
- package/public/assets/graph-CDNE6afq.js +2 -0
- package/public/assets/graph-CDNE6afq.js.map +1 -0
- package/public/assets/image-blob-reduce.esm-B6b2_-a4.js +8 -0
- package/public/assets/image-blob-reduce.esm-B6b2_-a4.js.map +1 -0
- package/public/assets/index-BqdqoSDd.css +1 -0
- package/public/assets/index-ChGp7972.js +2 -0
- package/public/assets/index-ChGp7972.js.map +1 -0
- package/public/assets/index-DPcDil7M.js +310 -0
- package/public/assets/index-DPcDil7M.js.map +1 -0
- package/public/assets/infoDiagram-WHAUD3N6-B_GahSu_.js +3 -0
- package/public/assets/infoDiagram-WHAUD3N6-B_GahSu_.js.map +1 -0
- package/public/assets/journeyDiagram-XKPGCS4Q-BpcUsKNT.js +140 -0
- package/public/assets/journeyDiagram-XKPGCS4Q-BpcUsKNT.js.map +1 -0
- package/public/assets/kanban-definition-3W4ZIXB7-BbuWO2gE.js +90 -0
- package/public/assets/kanban-definition-3W4ZIXB7-BbuWO2gE.js.map +1 -0
- package/public/assets/katex-Cu_Erd72.js +262 -0
- package/public/assets/katex-Cu_Erd72.js.map +1 -0
- package/public/assets/layout-DQkrSs1j.js +2 -0
- package/public/assets/layout-DQkrSs1j.js.map +1 -0
- package/public/assets/locales/ar-SA.json-B0e8d-qe.js +9 -0
- package/public/assets/locales/ar-SA.json-B0e8d-qe.js.map +1 -0
- package/public/assets/locales/az-AZ.json-DtyjPp_C.js +2 -0
- package/public/assets/locales/az-AZ.json-DtyjPp_C.js.map +1 -0
- package/public/assets/locales/bg-BG.json-CqhOM8G4.js +6 -0
- package/public/assets/locales/bg-BG.json-CqhOM8G4.js.map +1 -0
- package/public/assets/locales/bn-BD.json-CarEu6to.js +4 -0
- package/public/assets/locales/bn-BD.json-CarEu6to.js.map +1 -0
- package/public/assets/locales/bn-IN.json-vhiIjuiP.js +4 -0
- package/public/assets/locales/bn-IN.json-vhiIjuiP.js.map +1 -0
- package/public/assets/locales/ca-ES.json-DDTuZiJG.js +9 -0
- package/public/assets/locales/ca-ES.json-DDTuZiJG.js.map +1 -0
- package/public/assets/locales/cs-CZ.json-GJzW7TSE.js +8 -0
- package/public/assets/locales/cs-CZ.json-GJzW7TSE.js.map +1 -0
- package/public/assets/locales/da-DK.json-Be0TzPzl.js +3 -0
- package/public/assets/locales/da-DK.json-Be0TzPzl.js.map +1 -0
- package/public/assets/locales/de-CH.json-D69230kg.js +8 -0
- package/public/assets/locales/de-CH.json-D69230kg.js.map +1 -0
- package/public/assets/locales/de-DE.json-D69230kg.js +8 -0
- package/public/assets/locales/de-DE.json-D69230kg.js.map +1 -0
- package/public/assets/locales/el-GR.json-CHr149cq.js +8 -0
- package/public/assets/locales/el-GR.json-CHr149cq.js.map +1 -0
- package/public/assets/locales/es-ES.json-mElEeZ2D.js +8 -0
- package/public/assets/locales/es-ES.json-mElEeZ2D.js.map +1 -0
- package/public/assets/locales/eu-ES.json-CNw2jJEU.js +8 -0
- package/public/assets/locales/eu-ES.json-CNw2jJEU.js.map +1 -0
- package/public/assets/locales/fa-IR.json-92JiA0KN.js +10 -0
- package/public/assets/locales/fa-IR.json-92JiA0KN.js.map +1 -0
- package/public/assets/locales/fi-FI.json-CdOAdcjo.js +7 -0
- package/public/assets/locales/fi-FI.json-CdOAdcjo.js.map +1 -0
- package/public/assets/locales/fr-FR.json-Cl7dF38g.js +13 -0
- package/public/assets/locales/fr-FR.json-Cl7dF38g.js.map +1 -0
- package/public/assets/locales/gl-ES.json-fzzZLZQ9.js +7 -0
- package/public/assets/locales/gl-ES.json-fzzZLZQ9.js.map +1 -0
- package/public/assets/locales/he-IL.json-BAKkfUWM.js +9 -0
- package/public/assets/locales/he-IL.json-BAKkfUWM.js.map +1 -0
- package/public/assets/locales/hi-IN.json-CUCyTyWo.js +4 -0
- package/public/assets/locales/hi-IN.json-CUCyTyWo.js.map +1 -0
- package/public/assets/locales/hu-HU.json-CV3SA8ex.js +4 -0
- package/public/assets/locales/hu-HU.json-CV3SA8ex.js.map +1 -0
- package/public/assets/locales/id-ID.json-DE2Cqq5b.js +9 -0
- package/public/assets/locales/id-ID.json-DE2Cqq5b.js.map +1 -0
- package/public/assets/locales/it-IT.json-2PLJraya.js +13 -0
- package/public/assets/locales/it-IT.json-2PLJraya.js.map +1 -0
- package/public/assets/locales/ja-JP.json-CQMoyVLC.js +8 -0
- package/public/assets/locales/ja-JP.json-CQMoyVLC.js.map +1 -0
- package/public/assets/locales/kaa.json-Dh-4QROb.js +2 -0
- package/public/assets/locales/kaa.json-Dh-4QROb.js.map +1 -0
- package/public/assets/locales/kab-KAB.json-B6YUps6Z.js +5 -0
- package/public/assets/locales/kab-KAB.json-B6YUps6Z.js.map +1 -0
- package/public/assets/locales/kk-KZ.json-1lyZ103-.js +2 -0
- package/public/assets/locales/kk-KZ.json-1lyZ103-.js.map +1 -0
- package/public/assets/locales/km-KH.json-YG2La45k.js +8 -0
- package/public/assets/locales/km-KH.json-YG2La45k.js.map +1 -0
- package/public/assets/locales/ko-KR.json-DQzg7NpQ.js +6 -0
- package/public/assets/locales/ko-KR.json-DQzg7NpQ.js.map +1 -0
- package/public/assets/locales/ku-TR.json-DulXJuPf.js +7 -0
- package/public/assets/locales/ku-TR.json-DulXJuPf.js.map +1 -0
- package/public/assets/locales/lt-LT.json-BI5PGxiE.js +4 -0
- package/public/assets/locales/lt-LT.json-BI5PGxiE.js.map +1 -0
- package/public/assets/locales/lv-LV.json-Dd3uiNAK.js +5 -0
- package/public/assets/locales/lv-LV.json-Dd3uiNAK.js.map +1 -0
- package/public/assets/locales/mr-IN.json-CE3us3Fi.js +10 -0
- package/public/assets/locales/mr-IN.json-CE3us3Fi.js.map +1 -0
- package/public/assets/locales/my-MM.json-B-uNC5oj.js +2 -0
- package/public/assets/locales/my-MM.json-B-uNC5oj.js.map +1 -0
- package/public/assets/locales/nb-NO.json-B2a_ll4z.js +9 -0
- package/public/assets/locales/nb-NO.json-B2a_ll4z.js.map +1 -0
- package/public/assets/locales/nl-NL.json-CfAX9f-w.js +14 -0
- package/public/assets/locales/nl-NL.json-CfAX9f-w.js.map +1 -0
- package/public/assets/locales/nn-NO.json-CIGsfoKm.js +5 -0
- package/public/assets/locales/nn-NO.json-CIGsfoKm.js.map +1 -0
- package/public/assets/locales/oc-FR.json-DfxVss9i.js +5 -0
- package/public/assets/locales/oc-FR.json-DfxVss9i.js.map +1 -0
- package/public/assets/locales/pa-IN.json-Cyd9VJab.js +5 -0
- package/public/assets/locales/pa-IN.json-Cyd9VJab.js.map +1 -0
- package/public/assets/locales/pl-PL.json-CB5UbRiG.js +13 -0
- package/public/assets/locales/pl-PL.json-CB5UbRiG.js.map +1 -0
- package/public/assets/locales/pt-BR.json-GPJR67js.js +7 -0
- package/public/assets/locales/pt-BR.json-GPJR67js.js.map +1 -0
- package/public/assets/locales/pt-PT.json-Cyhb98dc.js +9 -0
- package/public/assets/locales/pt-PT.json-Cyhb98dc.js.map +1 -0
- package/public/assets/locales/ro-RO.json-DtuisOGY.js +13 -0
- package/public/assets/locales/ro-RO.json-DtuisOGY.js.map +1 -0
- package/public/assets/locales/ru-RU.json-C9d6W5vW.js +11 -0
- package/public/assets/locales/ru-RU.json-C9d6W5vW.js.map +1 -0
- package/public/assets/locales/si-LK.json-DWhqtTpr.js +2 -0
- package/public/assets/locales/si-LK.json-DWhqtTpr.js.map +1 -0
- package/public/assets/locales/sk-SK.json-Dp16EYYR.js +8 -0
- package/public/assets/locales/sk-SK.json-Dp16EYYR.js.map +1 -0
- package/public/assets/locales/sl-SI.json-CXPYOnbI.js +7 -0
- package/public/assets/locales/sl-SI.json-CXPYOnbI.js.map +1 -0
- package/public/assets/locales/sv-SE.json-DECpv7fU.js +9 -0
- package/public/assets/locales/sv-SE.json-DECpv7fU.js.map +1 -0
- package/public/assets/locales/ta-IN.json-5HNGLlpx.js +7 -0
- package/public/assets/locales/ta-IN.json-5HNGLlpx.js.map +1 -0
- package/public/assets/locales/th-TH.json-t8UcrCT-.js +2 -0
- package/public/assets/locales/th-TH.json-t8UcrCT-.js.map +1 -0
- package/public/assets/locales/tr-TR.json-DClzbz6u.js +5 -0
- package/public/assets/locales/tr-TR.json-DClzbz6u.js.map +1 -0
- package/public/assets/locales/uk-UA.json-DD2kmKOm.js +7 -0
- package/public/assets/locales/uk-UA.json-DD2kmKOm.js.map +1 -0
- package/public/assets/locales/uz-UZ.json-D78i0hec.js +2 -0
- package/public/assets/locales/uz-UZ.json-D78i0hec.js.map +1 -0
- package/public/assets/locales/vi-VN.json-DbtrA-ar.js +8 -0
- package/public/assets/locales/vi-VN.json-DbtrA-ar.js.map +1 -0
- package/public/assets/locales/zh-CN.json-D8B0Xgmh.js +12 -0
- package/public/assets/locales/zh-CN.json-D8B0Xgmh.js.map +1 -0
- package/public/assets/locales/zh-HK.json-Bv007uRw.js +2 -0
- package/public/assets/locales/zh-HK.json-Bv007uRw.js.map +1 -0
- package/public/assets/locales/zh-TW.json-BvenwCxf.js +10 -0
- package/public/assets/locales/zh-TW.json-BvenwCxf.js.map +1 -0
- package/public/assets/mermaid-to-excalidraw-D-aVQaad.js +280 -0
- package/public/assets/mermaid-to-excalidraw-D-aVQaad.js.map +1 -0
- package/public/assets/mindmap-definition-VGOIOE7T-mFLCToYA.js +69 -0
- package/public/assets/mindmap-definition-VGOIOE7T-mFLCToYA.js.map +1 -0
- package/public/assets/pica-fTKOVOgy.js +8 -0
- package/public/assets/pica-fTKOVOgy.js.map +1 -0
- package/public/assets/pieDiagram-ADFJNKIX-tDTRGJE3.js +31 -0
- package/public/assets/pieDiagram-ADFJNKIX-tDTRGJE3.js.map +1 -0
- package/public/assets/qrcode.chunk-DRz-_p9I.js +2 -0
- package/public/assets/qrcode.chunk-DRz-_p9I.js.map +1 -0
- package/public/assets/quadrantDiagram-AYHSOK5B-Y6TmIak2.js +8 -0
- package/public/assets/quadrantDiagram-AYHSOK5B-Y6TmIak2.js.map +1 -0
- package/public/assets/random-username.esm-__vdrxyo.js +2 -0
- package/public/assets/random-username.esm-__vdrxyo.js.map +1 -0
- package/public/assets/requirementDiagram-UZGBJVZJ-D7lgxClk.js +65 -0
- package/public/assets/requirementDiagram-UZGBJVZJ-D7lgxClk.js.map +1 -0
- package/public/assets/roundRect-0PYZxl1G.js +2 -0
- package/public/assets/roundRect-0PYZxl1G.js.map +1 -0
- package/public/assets/sankeyDiagram-TZEHDZUN-DeN5o3Zo.js +11 -0
- package/public/assets/sankeyDiagram-TZEHDZUN-DeN5o3Zo.js.map +1 -0
- package/public/assets/sequenceDiagram-WL72ISMW-A2jXBx54.js +146 -0
- package/public/assets/sequenceDiagram-WL72ISMW-A2jXBx54.js.map +1 -0
- package/public/assets/stateDiagram-FKZM4ZOC-tI2s18Rq.js +2 -0
- package/public/assets/stateDiagram-FKZM4ZOC-tI2s18Rq.js.map +1 -0
- package/public/assets/stateDiagram-v2-4FDKWEC3-BxhL9Cgi.js +2 -0
- package/public/assets/stateDiagram-v2-4FDKWEC3-BxhL9Cgi.js.map +1 -0
- package/public/assets/subset-shared.chunk-D3ioWSie.js +85 -0
- package/public/assets/subset-shared.chunk-D3ioWSie.js.map +1 -0
- package/public/assets/subset-worker.chunk-CVR6pt27.js +2 -0
- package/public/assets/subset-worker.chunk-CVR6pt27.js.map +1 -0
- package/public/assets/timeline-definition-IT6M3QCI-Bth-_zy2.js +62 -0
- package/public/assets/timeline-definition-IT6M3QCI-Bth-_zy2.js.map +1 -0
- package/public/assets/treemap-KMMF4GRG-CNTnVawn.js +135 -0
- package/public/assets/treemap-KMMF4GRG-CNTnVawn.js.map +1 -0
- package/public/assets/workbox-window.prod.es5-B9K5rw8f.js +3 -0
- package/public/assets/workbox-window.prod.es5-B9K5rw8f.js.map +1 -0
- package/public/assets/xychartDiagram-PRI3JC2R-C0zuH6pP.js +8 -0
- package/public/assets/xychartDiagram-PRI3JC2R-C0zuH6pP.js.map +1 -0
- package/public/favicon-16x16.png +0 -0
- package/public/favicon-32x32.png +0 -0
- package/public/favicon.ico +0 -0
- package/public/favicon.svg +7 -0
- package/public/fonts/CascadiaCode/CascadiaCode-Regular.woff2 +0 -0
- package/public/fonts/ComicShanns/ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2 +0 -0
- package/public/fonts/ComicShanns/ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2 +0 -0
- package/public/fonts/ComicShanns/ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2 +0 -0
- package/public/fonts/ComicShanns/ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2 +0 -0
- package/public/fonts/Excalifont/Excalifont-Regular-349fac6ca4700ffec595a7150a0d1e1d.woff2 +0 -0
- package/public/fonts/Excalifont/Excalifont-Regular-3f2c5db56cc93c5a6873b1361d730c16.woff2 +0 -0
- package/public/fonts/Excalifont/Excalifont-Regular-41b173a47b57366892116a575a43e2b6.woff2 +0 -0
- package/public/fonts/Excalifont/Excalifont-Regular-623ccf21b21ef6b3a0d87738f77eb071.woff2 +0 -0
- package/public/fonts/Excalifont/Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2 +0 -0
- package/public/fonts/Excalifont/Excalifont-Regular-b9dcf9d2e50a1eaf42fc664b50a3fd0d.woff2 +0 -0
- package/public/fonts/Excalifont/Excalifont-Regular-be310b9bcd4f1a43f571c46df7809174.woff2 +0 -0
- package/public/fonts/LiberationSans/LiberationSans-Regular.woff2 +0 -0
- package/public/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYE98RXi4EwSsbg.woff2 +0 -0
- package/public/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYEF8RXi4EwQ.woff2 +0 -0
- package/public/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTA3j6zbXWjgevT5.woff2 +0 -0
- package/public/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTQ3j6zbXWjgeg.woff2 +0 -0
- package/public/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTk3j6zbXWjgevT5.woff2 +0 -0
- package/public/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTo3j6zbXWjgevT5.woff2 +0 -0
- package/public/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTs3j6zbXWjgevT5.woff2 +0 -0
- package/public/fonts/Virgil/Virgil-Regular.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-019d66dcad46dc156b162d267f981c20.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-04b718e5623574919c8b0dea5f301444.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-069e77aac84590e2e991d0a0176d34f2.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-06c77b8c66e51ed6c63ccb502dd8b8af.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-08e0dc436ad0ad61ba5558db0674d762.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-093b9ef39a46ceae95a1df18a0a3a326.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-095c169f3314805276f603a362766abd.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-09850c4077f3fffe707905872e0e2460.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-0986d134c05864f5025962eef9f994a0.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-0b5d723fdc4e249c140f0909e87d03b4.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-0f626226ba1272e832aea87bafd9720e.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-0f7fb1e0d5015bb1371343153ecf7ce3.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-0fa55a080fcd0f9dc2e0b0058b793df8.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-0facdf1ea213ba40261022f5d5ed4493.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-10a7ae9a371830a80c3d844acf1c02d7.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-112c051027b2d766c19a519f6ee1f4f7.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-11c345711937f0ba4b8f7b6b919c8440.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-12b52b58eb3df36804b9a654ec9ee194.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-13ae07ed2e272d26d59bc0691cd7117a.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-13d2887ec8ee73c43acdabc52a05af7b.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-145aa02cdd91946e67dc934e1acffe75.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-15dc6d811c9cd078f9086a740d5a1038.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-173945821411c09f70c95f98d590e697.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-1b611157cd46bb184d4fa4dae2d6a2b8.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-1e6fd68f1f3902ce48ce8c69df385622.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-1ee544f0f1dac422545c505baa788992.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-1fdc0c67ed57263a80fd108c1f6ccf24.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-203b0e569e3b14aac86a003dc3fa523e.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-20cc1bbf50e7efb442756cb605672c1f.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-20e7bf72fa05de9adf7dbcc7bf51dde6.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-21430ee05a1248901da8d0de08744d47.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-23686f7f29da6e8008c36dd3a80c83d6.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-23ad2d71b280f00b1363b95b7bea94eb.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-23f228f3999c01983860012330e4be08.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-24476a126f129212beb33f66853ea151.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-24a21c1e4449222e8d1898d69ff3a404.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-25b7f38e18f035f96cb5e547bd2bd08c.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-29cec36cd205b211da97acabaa62f055.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-2a26d20a23b00898ce82f09d2ee47c3f.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-2adbc89c11e65905393d3dfc468b9d5b.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-2b7441d46298788ac94e610ffcc709b6.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-2b77e8ebfb2367ab2662396a60e7d320.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-2cf96d082d35ea3d8106851223ad0d16.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-2d43040e86ff03ba677f6f9c04cd0805.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-2e33e8dc771ef5e1d9127d60a6b73679.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-33432927cd87d40cfe393c7482bf221f.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-353f33792a8f60dc69323ddf635a269e.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-36925dfe329a45086cbb7fc5c20d45ac.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-3717077e38f98d89eae729b6c14e56dc.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-3756e81d3e149cf6099163ee79944fec.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-395c35dd584b56b0789f58a0559beaf1.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-3c9de2ae0ea4bc91a510942dfa4be8d2.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-3cc70dbb64df5b21f1326cc24dee2195.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-3e1f8f654357353bf0e04ba5c34b5f7f.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-3e63ed8162808a9e425ed80a8bc79114.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-3eaa538115d76932653c21d8dc28f207.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-4095eb84ef3874e2600247bee0b04026.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-41521fade99856108931b4768b1b2648.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-450da755d5bcb70906e1295e559b9602.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-452225341522a7942f0f6aab1a5c91a3.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-4535823663ad81405188a528d8f2b1a2.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-4806e761d750087c2d734fc64596eaff.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-4a0fdb40036e87b40aa08dd30584cb85.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-4a38cc3e9cf104e69ba246d37f8cf135.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-4aca6a43e59aceee2166b0c7e4e85ef1.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-4bfaa8ffa64c5ee560aa2daba7c9cbd3.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-4dc6d5f188d5c96d44815cd1e81aa885.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-4ddc14ed3eb0c3e46364317dfc0144a3.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-4ee10ae43505e2e0bc62656ced49c0fa.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-4f50e5136e136527280bc902c5817561.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-51502f1206be09c565f1547c406e9558.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-51a0e808bbc8361236ac521a119758a3.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-52a84a22fd1369bffeaf21da2d6158dc.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-5330a2119a716e4e7224ed108b085dac.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-543fa46ace099a7099dad69123399400.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-544fc28abe2c5c30e62383fd4dac255f.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-54acdfc2166ad7fcbd074f75fd4a56ba.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-5572b3513ba8df57a3d5d7303ee6b11b.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-56467a5c8840c4d23a60b2f935114848.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-56a32a7689abd0326e57c10c6c069bb4.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-57862b464a55b18c7bf234ce22907d73.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-583d166e56ba0de4b77eabb47ef67839.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-5882ffa04f32584d26109137e2da4352.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-58fd02350d0bc52cf1ca3bb32ce9766e.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-5935a5775af3d5c6307ac667bd9ae74e.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-59e9ff77b0efaf684bc09274fb6908c9.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-5a1ce3117cfe90c48e8fb4a9a00f694d.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-5a45d991244d4c7140217e1e5f5ca4f4.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-5a7fac4b8b23a6e4e5ba0c9bf1756c91.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-5b0ed6971aaab9c8ad563230bd5471a7.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-5d2898fbc097a7e24c6f38d80587621e.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-603aefd23e350ba7eb124273e3c9bcf1.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-60a3089806700d379f11827ee9843b6b.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-60a41c7e1c68f22424e6d22df544bc82.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-642b26e2e5f5fb780b51b593dbc8c851.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-66493ba5a8367f2928812f446f47b56a.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-670ba603758d94268e8606f240a42e12.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-671a2c20b1eb9e4ef8a192833940e319.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-684d65f1793cac449dde5d59cb3c47fb.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-69c09cc5fa3e55c74fc4821f76909cc3.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-6ae5b42180ad70b971c91e7eefb8eba2.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-6e092f71c1e634059ada0e52abadce67.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-6f3256af8454371776bc46670d33cc65.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-6fe5c5973cc06f74b2387a631ea36b88.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-70c2eb8d64e71a42a834eb857ea9df51.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-70e811fd7994e61f408c923de6ddd078.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-7197d6fda6cba7c3874c53d6381ca239.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-72252d73220fa3cd856677888cee1635.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-72536a3d71b694a0d53dd90ddceae41e.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-726303e0774b4e678bff8c2deb6ca603.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-733171b4ffcd17ea1fe1c0ba627173bf.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-739bc1a567439c7cffcd1614644593d2.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-73e309718fd16cea44b4d54a33581811.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-7494dc504ae00ee9cd0505f990f88c5d.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-74e2263a91439c25b91d5132ce9f4d62.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-761d05e3cd968cf574166867998ef06a.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-7718fe60986d8b42b1be9c5ace5ccf25.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-774d4f764a1299da5d28ec2f2ffe0d69.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-79d494361ae093b69e74ee9dbe65bfd4.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-79f007c1c6d07557120982951ea67998.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-7a07ddc0f0c0f5f4a9bad6ee3dda66b5.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-7ab2bed91166a9dca83a5ebfbe2a7f38.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-7ccce86603f80a099ddb0cb21d4ae3e3.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-7e4bde7e9c7f84cd34d8a845e384c746.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-7e929f262f30c8ee78bf398150b1a7cd.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-7eb9fffd1aa890d07d0f88cc82e6cfe4.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-7f855356ab893b0d2b9c1c83b8116f0e.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-829615148e6357d826b9242eb7fbbd1e.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-866fa7613df6b3fd272bcfd4530c0bb9.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-87599f94b6cc129d505b375798d0d751.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-8c2f33cee3993174f7e87c28e4bf42ee.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-8d3bcabb847b56243b16afe62adaaf21.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-8de5b863cb50dfefdd07cb11c774d579.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-8e9f97f01034820170065b2921b4fb5e.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-8f476c4c99813d57cbe6eca4727388ad.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-903bb6865f3452e2fda42e3a25547bc5.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-91ddb2969bf2d31ba02ad82998d1314c.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-938d90c10ff8c20386af7f242c05d6b0.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-93fc8f28a33234bcadf1527cafabd502.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-95429962233afd82db1c27df1500a28c.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-9544732d2e62d1a429674f8ee41b5d3a.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-9592bfc861f07bcb8d75c196b370e548.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-95bfd249da4902577b4b7d76ebdd0b44.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-968cffdc8ee679da094e77ebf50f58ef.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-97f7f48ce90c9429bf32ae51469db74d.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-982b630266d87db93d2539affb1275c6.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-98f2ad84457de7f3740d9920b8fa8667.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-99a16ef6a64934d5781933dbd9c46b2e.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-9cfb2a77a4e45025105ad29a1748b90d.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-9d81066dd2b337c938df6e90380a00dc.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-9eb5a99df4e76ac3363453ac9ca288b1.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-a004ddfcb26e67bd6e678c8ed19e25ce.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-a0ca5df4258213d7fc9fce80f65ce760.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-a1f916d6039285c4ffb900cd654e418f.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-a203b91dad570bf05a58c3c3ddb529bf.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-a365e82ed54697a52f27adcea1315fe8.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-a4c34be6d42152e64b0df90bc4607f64.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-a7accba310e821da5505f71c03b76bdb.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-aa0d470430e6391eca720c7cfa44446f.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-aa5c9ca6cf4fba00433b7aa3fa10671a.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-ac9ceb44437becc3e9c4dbfebab7fc2d.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-b1220a3c61f85cc0408deedb4c5f57a2.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-b358f7a51ece39a3247942b1feabdb29.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-b57aaedfd8ebdf3931f25119dc6a5eb2.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-b5c1596551c256e0e9cf02028595b092.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-b6d128682ee29e471486354d486a1b90.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-b6fd38ca30869792244804b04bc058da.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-b7d203b051eff504ff59ddca7576b6a9.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-b96d9226ce77ec94ceca043d712182e6.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-ba3de316d63c7e339987b16f41a0b879.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-bafff7a14c27403dcc6cf1432e8ea836.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-bd77e3c7f9e0b072d96af37f73d1aa32.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-be549ab72f0719d606a5c01e2c0219b6.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-c16ed9740b85badf16e86ea782a3062f.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-c1f94158256bb1f3bf665b053d895af9.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-c40533fdf4cc57177b12803598af7e59.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-c4a687ac4f0c2766eefc9f77ed99cddf.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-c69f61a4ab18d0488c8d1fc12e7028e8.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-c8b71798409ccc126ee264a00aadcf21.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-c99eda15fc26a2941579560f76c3a5cf.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-cb17fc3db95f6d139afc9d31a8e93293.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-cbaaefaaf326668277aa24dfa93c4d28.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-cd145ce4a0ea18469358df53c207bc1b.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-cdbce89e82cc1ab53a2decbf5819278f.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-ce4884f96f11589608b76b726a755803.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-cf2cc71752631e579e35b0e423bf2638.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-cf6ff4e0f491ca0cf3038187a997b9b4.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-cfb211578629b7e8153b37240de6a9d5.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-d0cf73942fea1c74edbdf0b3011f4656.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-d2666cbed13462c5dc36fa2f15c202ca.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-d3716376641d615e2995605b29bca7b6.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-dac48066b5883d8b4551fc584f0c2a3e.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-dbea1af6dcd9860be40c3d18254338f5.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-e11567fd2accf9957cd0d3c2be937d87.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-e2ead7ea7da0437f085f42ffc05f8d13.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-e3fcf5180fd466c8915c4e8069491054.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-e480d9c614742d05f0e78f274f1e69e6.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-e4bca6cfa53e499cae0a6be4894a90e9.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-e51ef413167c6e14e0c0fdcc585f2fc9.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-e5f453bb04da18eed01675eeebd88bf8.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-e656f091b9dc4709722c9f4b84d3c797.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-ec181b795ac1fb5a50d700b6e996d745.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-ee8bae97908d5147b423f77ad0d3c1bb.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-f0f13b5c60e0af5553bd359f5513be1b.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-f2b54d4e7be0eaefe1c2c56836fa5368.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-f56414bf9bced67990def8660e306759.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-f5d079153c99a25b9be5b8583c4cc8a7.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-f6032fc06eb20480f096199713f70885.woff2 +0 -0
- package/public/fonts/Xiaolai/Xiaolai-Regular-f8ee5d36068a42b51d0e4a1116cfcec1.woff2 +0 -0
- package/public/index.html +30 -0
- package/public/manifest.webmanifest +1 -0
- package/public/maskable_icon_x192.png +0 -0
- package/public/maskable_icon_x512.png +0 -0
- package/public/og-image-3.png +0 -0
- package/public/oss_promo_comments_dark.jpg +0 -0
- package/public/oss_promo_comments_light.jpg +0 -0
- package/public/oss_promo_presentations_dark.svg +1 -0
- package/public/oss_promo_presentations_light.svg +1 -0
- package/public/robots.txt +13 -0
- package/public/screenshots/collaboration.png +0 -0
- package/public/screenshots/export.png +0 -0
- package/public/screenshots/illustration.png +0 -0
- package/public/screenshots/shapes.png +0 -0
- package/public/screenshots/virtual-whiteboard.png +0 -0
- package/public/screenshots/wireframe.png +0 -0
- package/public/service-worker.js +20 -0
- package/public/sitemap.xml +1 -0
- package/public/sw.js +2 -0
- package/public/sw.js.map +1 -0
- package/public/version.json +3 -0
- package/public/workbox-3631b453.js +2 -0
- package/public/workbox-3631b453.js.map +1 -0
- package/routes/auth.js +24 -0
- package/routes/collab.js +52 -0
- package/routes/drawings.js +49 -0
- package/routes/library.js +15 -0
- package/routes/users.js +32 -0
- package/server.js +109 -0
- package/storage.js +171 -0
package/routes/collab.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const express = require("express");
|
|
2
|
+
const storage = require("../storage");
|
|
3
|
+
|
|
4
|
+
const router = express.Router();
|
|
5
|
+
|
|
6
|
+
// GET /api/v1/collab/:roomId — load encrypted scene
|
|
7
|
+
router.get("/:roomId", (req, res) => {
|
|
8
|
+
const scene = storage.getCollabScene(req.params.roomId);
|
|
9
|
+
if (!scene) return res.status(404).json({ error: "Not found" });
|
|
10
|
+
res.json(scene);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
// PUT /api/v1/collab/:roomId — save encrypted scene
|
|
14
|
+
router.put("/:roomId", (req, res) => {
|
|
15
|
+
const { sceneVersion, ciphertext, iv } = req.body;
|
|
16
|
+
if (!ciphertext || !iv) return res.status(400).json({ error: "Missing data" });
|
|
17
|
+
storage.saveCollabScene(req.params.roomId, { sceneVersion, ciphertext, iv });
|
|
18
|
+
res.json({ ok: true });
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// GET /api/v1/collab/:roomId/files/:fileId — load a collab file
|
|
22
|
+
router.get("/:roomId/files/:fileId", (req, res) => {
|
|
23
|
+
const buf = storage.getCollabFile(req.params.roomId, req.params.fileId);
|
|
24
|
+
if (!buf) return res.status(404).json({ error: "Not found" });
|
|
25
|
+
res.set("Content-Type", "application/octet-stream");
|
|
26
|
+
res.set("Cache-Control", "public, max-age=31536000");
|
|
27
|
+
res.send(buf);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// POST /api/v1/collab/:roomId/files — save collab files (array of {id, buffer})
|
|
31
|
+
router.post("/:roomId/files", express.raw({ type: "*/*", limit: "50mb" }), (req, res) => {
|
|
32
|
+
// files arrive as JSON array: [{ id, buffer: base64 }]
|
|
33
|
+
try {
|
|
34
|
+
const files = req.body; // already parsed by outer json middleware
|
|
35
|
+
const saved = [];
|
|
36
|
+
const errored = [];
|
|
37
|
+
for (const { id, buffer } of files) {
|
|
38
|
+
try {
|
|
39
|
+
const buf = Buffer.from(buffer, "base64");
|
|
40
|
+
storage.saveCollabFile(req.params.roomId, id, buf);
|
|
41
|
+
saved.push(id);
|
|
42
|
+
} catch {
|
|
43
|
+
errored.push(id);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
res.json({ saved, errored });
|
|
47
|
+
} catch (err) {
|
|
48
|
+
res.status(500).json({ error: err.message });
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
module.exports = router;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const router = require("express").Router();
|
|
2
|
+
const storage = require("../storage");
|
|
3
|
+
|
|
4
|
+
// GET /api/v1/drawings/shared/:shareId — must come before /:id
|
|
5
|
+
router.get("/shared/:shareId", (req, res) => {
|
|
6
|
+
const drawing = storage.getSharedDrawing(req.params.shareId);
|
|
7
|
+
if (!drawing) return res.status(404).json({ status: "fail", message: "Drawing not found" });
|
|
8
|
+
res.json({ status: "success", data: { drawing } });
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
// GET /api/v1/drawings
|
|
12
|
+
router.get("/", (_req, res) => {
|
|
13
|
+
res.json({ status: "success", data: { drawings: storage.listDrawings() } });
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// POST /api/v1/drawings
|
|
17
|
+
router.post("/", (req, res) => {
|
|
18
|
+
const drawing = storage.createDrawing(req.body);
|
|
19
|
+
res.status(201).json({ status: "success", data: { drawing } });
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// GET /api/v1/drawings/:id
|
|
23
|
+
router.get("/:id", (req, res) => {
|
|
24
|
+
const drawing = storage.readDrawing(req.params.id);
|
|
25
|
+
if (!drawing) return res.status(404).json({ status: "fail", message: "Drawing not found" });
|
|
26
|
+
res.json({ status: "success", data: { drawing } });
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// PUT /api/v1/drawings/:id
|
|
30
|
+
router.put("/:id", (req, res) => {
|
|
31
|
+
const drawing = storage.updateDrawing(req.params.id, req.body);
|
|
32
|
+
if (!drawing) return res.status(404).json({ status: "fail", message: "Drawing not found" });
|
|
33
|
+
res.json({ status: "success", data: { drawing } });
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// DELETE /api/v1/drawings/:id
|
|
37
|
+
router.delete("/:id", (req, res) => {
|
|
38
|
+
storage.deleteDrawing(req.params.id);
|
|
39
|
+
res.json({ status: "success", data: { message: "Drawing deleted" } });
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// PATCH /api/v1/drawings/:id/share
|
|
43
|
+
router.patch("/:id/share", (req, res) => {
|
|
44
|
+
const result = storage.toggleShare(req.params.id);
|
|
45
|
+
if (!result) return res.status(404).json({ status: "fail", message: "Drawing not found" });
|
|
46
|
+
res.json({ status: "success", data: result });
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
module.exports = router;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const router = require("express").Router();
|
|
2
|
+
const storage = require("../storage");
|
|
3
|
+
|
|
4
|
+
// GET /api/v1/library
|
|
5
|
+
router.get("/", (_req, res) => {
|
|
6
|
+
res.json({ status: "success", data: { items: storage.getLibrary() } });
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
// PUT /api/v1/library
|
|
10
|
+
router.put("/", (req, res) => {
|
|
11
|
+
const items = storage.saveLibrary(Array.isArray(req.body.items) ? req.body.items : []);
|
|
12
|
+
res.json({ status: "success", data: { items } });
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
module.exports = router;
|
package/routes/users.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const router = require("express").Router();
|
|
2
|
+
const { body } = require("express-validator");
|
|
3
|
+
const { getProfile, updateProfile, changePassword, getStats } = require("../controllers/userController");
|
|
4
|
+
const { protect } = require("../middleware/auth");
|
|
5
|
+
const validate = require("../middleware/validate");
|
|
6
|
+
|
|
7
|
+
router.use(protect);
|
|
8
|
+
|
|
9
|
+
router.get ("/me", getProfile);
|
|
10
|
+
router.get ("/me/stats", getStats);
|
|
11
|
+
|
|
12
|
+
router.put(
|
|
13
|
+
"/me",
|
|
14
|
+
[
|
|
15
|
+
body("name").optional().trim().notEmpty().withMessage("Name cannot be empty").isLength({ max: 80 }).withMessage("Name too long"),
|
|
16
|
+
body("avatar").optional({ nullable: true }),
|
|
17
|
+
],
|
|
18
|
+
validate,
|
|
19
|
+
updateProfile,
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
router.put(
|
|
23
|
+
"/me/password",
|
|
24
|
+
[
|
|
25
|
+
body("currentPassword").notEmpty().withMessage("Current password is required"),
|
|
26
|
+
body("newPassword").isLength({ min: 6 }).withMessage("New password must be at least 6 characters"),
|
|
27
|
+
],
|
|
28
|
+
validate,
|
|
29
|
+
changePassword,
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
module.exports = router;
|
package/server.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
require("dotenv").config();
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const http = require("http");
|
|
5
|
+
const express = require("express");
|
|
6
|
+
const cors = require("cors");
|
|
7
|
+
const helmet = require("helmet");
|
|
8
|
+
const morgan = require("morgan");
|
|
9
|
+
const compression = require("compression");
|
|
10
|
+
const { Server } = require("socket.io");
|
|
11
|
+
|
|
12
|
+
const app = express();
|
|
13
|
+
const httpServer = http.createServer(app);
|
|
14
|
+
|
|
15
|
+
const CLIENT_URL = process.env.CLIENT_URL || "http://localhost:3001";
|
|
16
|
+
|
|
17
|
+
// ── Socket.io ─────────────────────────────────────────────────────────────────
|
|
18
|
+
const io = new Server(httpServer, {
|
|
19
|
+
cors: { origin: CLIENT_URL, methods: ["GET", "POST"] },
|
|
20
|
+
maxHttpBufferSize: 50 * 1024 * 1024, // 50 MB for large scenes
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
io.on("connection", (socket) => {
|
|
24
|
+
socket.emit("init-room");
|
|
25
|
+
|
|
26
|
+
socket.on("join-room", (roomId) => {
|
|
27
|
+
socket.join(roomId);
|
|
28
|
+
const room = io.sockets.adapter.rooms.get(roomId);
|
|
29
|
+
const clients = room ? [...room] : [];
|
|
30
|
+
|
|
31
|
+
if (clients.length === 1) {
|
|
32
|
+
socket.emit("first-in-room");
|
|
33
|
+
} else {
|
|
34
|
+
socket.broadcast.to(roomId).emit("new-user", socket.id);
|
|
35
|
+
}
|
|
36
|
+
io.to(roomId).emit("room-user-change", clients);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
socket.on("server-broadcast", (roomId, encryptedData, iv) => {
|
|
40
|
+
socket.broadcast.to(roomId).emit("client-broadcast", encryptedData, iv);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
socket.on("server-volatile-broadcast", (roomId, encryptedData, iv) => {
|
|
44
|
+
socket.volatile.broadcast.to(roomId).emit("client-broadcast", encryptedData, iv);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
socket.on("user-follow", (payload) => {
|
|
48
|
+
const rooms = [...socket.rooms].filter((r) => r !== socket.id);
|
|
49
|
+
rooms.forEach((roomId) => {
|
|
50
|
+
socket.broadcast.to(roomId).emit("user-follow", payload);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
socket.on("disconnecting", () => {
|
|
55
|
+
[...socket.rooms]
|
|
56
|
+
.filter((r) => r !== socket.id)
|
|
57
|
+
.forEach((roomId) => {
|
|
58
|
+
const room = io.sockets.adapter.rooms.get(roomId);
|
|
59
|
+
const remaining = room ? [...room].filter((id) => id !== socket.id) : [];
|
|
60
|
+
socket.broadcast.to(roomId).emit("room-user-change", remaining);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// ── HTTP middleware ───────────────────────────────────────────────────────────
|
|
66
|
+
app.use(helmet());
|
|
67
|
+
app.use(compression());
|
|
68
|
+
app.use(morgan(process.env.NODE_ENV === "production" ? "combined" : "dev"));
|
|
69
|
+
|
|
70
|
+
app.use(
|
|
71
|
+
cors({
|
|
72
|
+
origin: CLIENT_URL,
|
|
73
|
+
methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
|
|
74
|
+
allowedHeaders: ["Content-Type"],
|
|
75
|
+
}),
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
app.use(express.json({ limit: "25mb" }));
|
|
79
|
+
|
|
80
|
+
// ── Routes ────────────────────────────────────────────────────────────────────
|
|
81
|
+
app.use("/api/v1/drawings", require("./routes/drawings"));
|
|
82
|
+
app.use("/api/v1/library", require("./routes/library"));
|
|
83
|
+
app.use("/api/v1/collab", require("./routes/collab"));
|
|
84
|
+
|
|
85
|
+
// ── Health ────────────────────────────────────────────────────────────────────
|
|
86
|
+
app.get("/health", (_req, res) =>
|
|
87
|
+
res.json({ status: "ok", env: process.env.NODE_ENV || "development" }),
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
// ── Static frontend (npm package mode) ───────────────────────────────────────
|
|
91
|
+
const STATIC_DIR = process.env.STATIC_DIR;
|
|
92
|
+
if (STATIC_DIR && fs.existsSync(STATIC_DIR)) {
|
|
93
|
+
app.use(express.static(STATIC_DIR));
|
|
94
|
+
// SPA fallback — all non-API routes serve index.html
|
|
95
|
+
app.get("*", (req, res) => {
|
|
96
|
+
res.sendFile(require("path").join(STATIC_DIR, "index.html"));
|
|
97
|
+
});
|
|
98
|
+
} else {
|
|
99
|
+
// ── 404 (dev mode — frontend served separately by Vite) ──────────────────
|
|
100
|
+
app.all("*", (req, res) =>
|
|
101
|
+
res.status(404).json({ status: "fail", message: `Cannot ${req.method} ${req.originalUrl}` }),
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ── Start ─────────────────────────────────────────────────────────────────────
|
|
106
|
+
const PORT = process.env.PORT || 5000;
|
|
107
|
+
httpServer.listen(PORT, () =>
|
|
108
|
+
console.log(`SketchBoard server running on port ${PORT} [${process.env.NODE_ENV || "development"}]`),
|
|
109
|
+
);
|
package/storage.js
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const { v4: uuidv4 } = require("uuid");
|
|
4
|
+
|
|
5
|
+
const os = require("os");
|
|
6
|
+
const DATA_DIR = process.env.DATA_DIR || path.join(os.homedir(), ".sketchboard");
|
|
7
|
+
const DRAWINGS_DIR = path.join(DATA_DIR, "drawings");
|
|
8
|
+
const LIBRARY_FILE = path.join(DATA_DIR, "library.json");
|
|
9
|
+
const COLLAB_DIR = path.join(DATA_DIR, "collab");
|
|
10
|
+
const COLLAB_FILES_DIR = path.join(DATA_DIR, "collab-files");
|
|
11
|
+
|
|
12
|
+
fs.mkdirSync(DRAWINGS_DIR, { recursive: true });
|
|
13
|
+
fs.mkdirSync(COLLAB_DIR, { recursive: true });
|
|
14
|
+
fs.mkdirSync(COLLAB_FILES_DIR, { recursive: true });
|
|
15
|
+
|
|
16
|
+
// ── Internal helpers ──────────────────────────────────────────────────────────
|
|
17
|
+
|
|
18
|
+
function drawingPath(id) {
|
|
19
|
+
return path.join(DRAWINGS_DIR, `${id}.json`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function readFile(id) {
|
|
23
|
+
const p = drawingPath(id);
|
|
24
|
+
if (!fs.existsSync(p)) return null;
|
|
25
|
+
try { return JSON.parse(fs.readFileSync(p, "utf8")); } catch { return null; }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function writeFile(drawing) {
|
|
29
|
+
fs.writeFileSync(drawingPath(drawing._id), JSON.stringify(drawing, null, 2), "utf8");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ── Drawings ──────────────────────────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
function listDrawings() {
|
|
35
|
+
return fs
|
|
36
|
+
.readdirSync(DRAWINGS_DIR)
|
|
37
|
+
.filter((f) => f.endsWith(".json"))
|
|
38
|
+
.map((f) => {
|
|
39
|
+
try {
|
|
40
|
+
const d = JSON.parse(fs.readFileSync(path.join(DRAWINGS_DIR, f), "utf8"));
|
|
41
|
+
return {
|
|
42
|
+
_id: d._id,
|
|
43
|
+
title: d.title,
|
|
44
|
+
thumbnail: d.thumbnail || null,
|
|
45
|
+
isPublic: d.isPublic || false,
|
|
46
|
+
shareId: d.shareId || null,
|
|
47
|
+
tags: d.tags || [],
|
|
48
|
+
updatedAt: d.updatedAt,
|
|
49
|
+
createdAt: d.createdAt,
|
|
50
|
+
};
|
|
51
|
+
} catch { return null; }
|
|
52
|
+
})
|
|
53
|
+
.filter(Boolean)
|
|
54
|
+
.sort((a, b) => new Date(b.updatedAt) - new Date(a.updatedAt));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function createDrawing({ title, elements, appState, files, thumbnail, tags } = {}) {
|
|
58
|
+
const now = new Date().toISOString();
|
|
59
|
+
const drawing = {
|
|
60
|
+
_id: uuidv4(),
|
|
61
|
+
title: title || "Untitled Drawing",
|
|
62
|
+
elements: elements || [],
|
|
63
|
+
appState: appState || {},
|
|
64
|
+
files: files || {},
|
|
65
|
+
thumbnail: thumbnail || null,
|
|
66
|
+
isPublic: false,
|
|
67
|
+
shareId: uuidv4(),
|
|
68
|
+
tags: tags || [],
|
|
69
|
+
createdAt: now,
|
|
70
|
+
updatedAt: now,
|
|
71
|
+
};
|
|
72
|
+
writeFile(drawing);
|
|
73
|
+
return drawing;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function readDrawing(id) {
|
|
77
|
+
return readFile(id);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function updateDrawing(id, updates) {
|
|
81
|
+
const drawing = readFile(id);
|
|
82
|
+
if (!drawing) return null;
|
|
83
|
+
const ALLOWED = ["title", "elements", "appState", "files", "isPublic", "thumbnail", "tags"];
|
|
84
|
+
ALLOWED.forEach((k) => { if (updates[k] !== undefined) drawing[k] = updates[k]; });
|
|
85
|
+
drawing.updatedAt = new Date().toISOString();
|
|
86
|
+
writeFile(drawing);
|
|
87
|
+
return drawing;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function deleteDrawing(id) {
|
|
91
|
+
const p = drawingPath(id);
|
|
92
|
+
if (fs.existsSync(p)) fs.unlinkSync(p);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function toggleShare(id) {
|
|
96
|
+
const drawing = readFile(id);
|
|
97
|
+
if (!drawing) return null;
|
|
98
|
+
drawing.isPublic = !drawing.isPublic;
|
|
99
|
+
drawing.updatedAt = new Date().toISOString();
|
|
100
|
+
writeFile(drawing);
|
|
101
|
+
return { isPublic: drawing.isPublic, shareId: drawing.shareId };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function getSharedDrawing(shareId) {
|
|
105
|
+
const files = fs.readdirSync(DRAWINGS_DIR).filter((f) => f.endsWith(".json"));
|
|
106
|
+
for (const f of files) {
|
|
107
|
+
try {
|
|
108
|
+
const d = JSON.parse(fs.readFileSync(path.join(DRAWINGS_DIR, f), "utf8"));
|
|
109
|
+
if (d.shareId === shareId && d.isPublic) {
|
|
110
|
+
return { _id: d._id, title: d.title, elements: d.elements,
|
|
111
|
+
appState: d.appState, files: d.files,
|
|
112
|
+
shareId: d.shareId, updatedAt: d.updatedAt };
|
|
113
|
+
}
|
|
114
|
+
} catch { /* skip corrupt files */ }
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ── Library ───────────────────────────────────────────────────────────────────
|
|
120
|
+
|
|
121
|
+
function getLibrary() {
|
|
122
|
+
if (!fs.existsSync(LIBRARY_FILE)) return [];
|
|
123
|
+
try { return JSON.parse(fs.readFileSync(LIBRARY_FILE, "utf8")); } catch { return []; }
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function saveLibrary(items) {
|
|
127
|
+
fs.writeFileSync(LIBRARY_FILE, JSON.stringify(items, null, 2), "utf8");
|
|
128
|
+
return items;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ── Collab scenes ─────────────────────────────────────────────────────────────
|
|
132
|
+
|
|
133
|
+
function collabScenePath(roomId) {
|
|
134
|
+
return path.join(COLLAB_DIR, `${roomId}.json`);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function getCollabScene(roomId) {
|
|
138
|
+
const p = collabScenePath(roomId);
|
|
139
|
+
if (!fs.existsSync(p)) return null;
|
|
140
|
+
try { return JSON.parse(fs.readFileSync(p, "utf8")); } catch { return null; }
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function saveCollabScene(roomId, scene) {
|
|
144
|
+
fs.writeFileSync(collabScenePath(roomId), JSON.stringify(scene), "utf8");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// ── Collab files ──────────────────────────────────────────────────────────────
|
|
148
|
+
|
|
149
|
+
function collabFilePath(roomId, fileId) {
|
|
150
|
+
const dir = path.join(COLLAB_FILES_DIR, roomId);
|
|
151
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
152
|
+
return path.join(dir, fileId);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function getCollabFile(roomId, fileId) {
|
|
156
|
+
const p = collabFilePath(roomId, fileId);
|
|
157
|
+
if (!fs.existsSync(p)) return null;
|
|
158
|
+
return fs.readFileSync(p); // returns Buffer
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function saveCollabFile(roomId, fileId, buffer) {
|
|
162
|
+
fs.writeFileSync(collabFilePath(roomId, fileId), buffer);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
module.exports = {
|
|
166
|
+
listDrawings, createDrawing, readDrawing,
|
|
167
|
+
updateDrawing, deleteDrawing, toggleShare,
|
|
168
|
+
getSharedDrawing, getLibrary, saveLibrary,
|
|
169
|
+
getCollabScene, saveCollabScene,
|
|
170
|
+
getCollabFile, saveCollabFile,
|
|
171
|
+
};
|