collabmd 0.1.29 → 0.1.31

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 (445) hide show
  1. package/README.md +5 -0
  2. package/dist/client/assets/{CodeMirrorEditor-UCMRAMCV-9k1Shd4H.js → CodeMirrorEditor-UCMRAMCV-Bg0dawOb.js} +1 -1
  3. package/dist/client/assets/{_basePickBy-B6kIfhzj.js → _basePickBy-Dv0sK1l7.js} +1 -1
  4. package/dist/client/assets/{_baseUniq-Bbn0_sHS.js → _baseUniq-DKYX57ji.js} +1 -1
  5. package/dist/client/assets/{ar-SA-NXDWD63E-BWO5oYxe.js → ar-SA-NXDWD63E-WivLHHDW.js} +1 -1
  6. package/dist/client/assets/{arc-BIqum3oD.js → arc-DrfYGhWk.js} +1 -1
  7. package/dist/client/assets/architecture-PBZL5I3N-DiglIZi9.js +1 -0
  8. package/dist/client/assets/architectureDiagram-2XIMDMQ5-kYbOThe4.js +36 -0
  9. package/dist/client/assets/{az-AZ-MXSORGZV-Cfw6Z5oY.js → az-AZ-MXSORGZV-DOdq1TKC.js} +1 -1
  10. package/dist/client/assets/base-CaIEJUF9.css +1 -0
  11. package/dist/client/assets/{bg-BG-O6MV2KSF-CQmG3YpD.js → bg-BG-O6MV2KSF-CYucKuDS.js} +1 -1
  12. package/dist/client/assets/{blockDiagram-WCTKOSBZ-0rR9ivwb.js → blockDiagram-WCTKOSBZ-GIgTqnhk.js} +1 -1
  13. package/dist/client/assets/{bn-IN-MMW2ORAC-DZKVshfk.js → bn-BD-T2VJNT7N-2OKWLCYa.js} +1 -1
  14. package/dist/client/assets/{bn-BD-T2VJNT7N-C4S6DZ6o.js → bn-IN-MMW2ORAC-DYr8kqNL.js} +1 -1
  15. package/dist/client/assets/{c4Diagram-IC4MRINW-DHwxcDlQ.js → c4Diagram-IC4MRINW-CkHO1i_L.js} +1 -1
  16. package/dist/client/assets/{ca-ES-MKBCGNOG-Do3aMgyu.js → ca-ES-MKBCGNOG-B9Aeb43I.js} +1 -1
  17. package/dist/client/assets/channel-CgsU9TSN.js +1 -0
  18. package/dist/client/assets/{chunk-4BX2VUAB-BqEY6cCE.js → chunk-4BX2VUAB-2e7V-uuE.js} +1 -1
  19. package/dist/client/assets/{chunk-55IACEB6-039iVf6v.js → chunk-55IACEB6-CpncB3ru.js} +1 -1
  20. package/dist/client/assets/{chunk-7E7YKBS2-BreG0gYL.js → chunk-7E7YKBS2-TdU92i9i.js} +1 -1
  21. package/dist/client/assets/{chunk-7R4GIKGN-BMrp52Pk.js → chunk-7R4GIKGN-mqd2GwMg.js} +2 -2
  22. package/dist/client/assets/{chunk-ETSVUAFD-CN-gPl_j.js → chunk-AXZTUZBK-DuMiJYO9.js} +1 -1
  23. package/dist/client/assets/{chunk-C72U2L5F-BLB26v5d.js → chunk-C72U2L5F-CJKQWBtz.js} +1 -1
  24. package/dist/client/assets/{chunk-EGIJ26TM-fG-0Yh0k.js → chunk-EGIJ26TM-C4nq20om.js} +1 -1
  25. package/dist/client/assets/{chunk-FMBD7UC4-EWK5Pt4D.js → chunk-FMBD7UC4-CMahlBa_.js} +1 -1
  26. package/dist/client/assets/{chunk-GEFDOKGD-DYHmaq-c.js → chunk-GEFDOKGD-Bs7FmFox.js} +1 -1
  27. package/dist/client/assets/chunk-GLR3WWYH-qQe2O5VQ.js +2 -0
  28. package/dist/client/assets/chunk-HHEYEP7N-DlevL8bq.js +1 -0
  29. package/dist/client/assets/{chunk-JSJVCQXG-B69YGtcQ.js → chunk-JSJVCQXG-DPQ9cPJt.js} +1 -1
  30. package/dist/client/assets/{chunk-KX2RTZJC-tuEC7hg1.js → chunk-KX2RTZJC-BTiOJb7N.js} +1 -1
  31. package/dist/client/assets/{chunk-KYZI473N-D4r5eMJZ.js → chunk-KYZI473N-CTSCuqRb.js} +1 -1
  32. package/dist/client/assets/{chunk-L3YUKLVL-CD9nJYL8.js → chunk-L3YUKLVL-CJZMBtKF.js} +1 -1
  33. package/dist/client/assets/{chunk-MX3YWQON-DqN0TF5Q.js → chunk-MX3YWQON-DQpSwRf6.js} +1 -1
  34. package/dist/client/assets/{chunk-NQ4KR5QH-BCjGNd0g.js → chunk-NQ4KR5QH-CMJKI6Oj.js} +1 -1
  35. package/dist/client/assets/chunk-NU2UP6EN-DlUENSHU.js +35 -0
  36. package/dist/client/assets/{chunk-O4XLMI2P-DaS3COAu.js → chunk-O4XLMI2P-CcVxZh41.js} +1 -1
  37. package/dist/client/assets/{chunk-OZEHJAEY-BaBXI-8x.js → chunk-OZEHJAEY-DjBZbgu0.js} +1 -1
  38. package/dist/client/assets/{chunk-PQ6SQG4A-BY9_Srs_.js → chunk-PQ6SQG4A-D1AbThjy.js} +1 -1
  39. package/dist/client/assets/{chunk-PU5JKC2W-t0zUh6E3.js → chunk-PU5JKC2W-D_6N6t8f.js} +1 -1
  40. package/dist/client/assets/chunk-QZHKN3VN-CgLPFSk5.js +1 -0
  41. package/dist/client/assets/{chunk-R5LLSJPH-BjSMFnTi.js → chunk-R5LLSJPH-CkjKXM73.js} +1 -1
  42. package/dist/client/assets/{chunk-WL4C6EOR-OuH0lN6M.js → chunk-WL4C6EOR-axcuKSup.js} +1 -1
  43. package/dist/client/assets/{chunk-XIRO2GV7-2tirYN5A.js → chunk-XIRO2GV7-4wqVHjs_.js} +1 -1
  44. package/dist/client/assets/{chunk-XPW4576I-C0GpOUHf.js → chunk-XPW4576I-DJr4_4Yy.js} +1 -1
  45. package/dist/client/assets/{chunk-XZSTWKYB-DDkpyNVE.js → chunk-XZSTWKYB-C8Y_hIKZ.js} +1 -1
  46. package/dist/client/assets/{chunk-YBOYWFTD-CzyyfGQX.js → chunk-YBOYWFTD-CKg4ymFF.js} +1 -1
  47. package/dist/client/assets/{chunk-Z5NKEFVG-Dgem5v98.js → chunk-Z5NKEFVG-HOkYqaKa.js} +1 -1
  48. package/dist/client/assets/classDiagram-VBA2DB6C-BHZpvOxK.js +1 -0
  49. package/dist/client/assets/classDiagram-v2-RAHNMMFH-DA7HMUUs.js +1 -0
  50. package/dist/client/assets/clone-Dgi8Z4IL.js +1 -0
  51. package/dist/client/assets/{cose-bilkent-S5V4N54A-jZzFUguD.js → cose-bilkent-S5V4N54A-DASO2hrk.js} +1 -1
  52. package/dist/client/assets/{cs-CZ-V77HGUP7-DmZRJ2UO.js → cs-CZ-V77HGUP7-BDg-F0CJ.js} +1 -1
  53. package/dist/client/assets/{da-DK-I5RFNTM4-CRIiLQ-G.js → da-DK-I5RFNTM4-wtSQ0Jxa.js} +1 -1
  54. package/dist/client/assets/{dagre-fvYjRtTE.js → dagre-CfB3Fw33.js} +1 -1
  55. package/dist/client/assets/dagre-KLK3FWXG-CC7tq2Ky.js +4 -0
  56. package/dist/client/assets/{de-DE-DTI4WUSC-MFge9MC3.js → de-CH-WLRDEVBV-C1swvmZy.js} +1 -1
  57. package/dist/client/assets/{de-CH-WLRDEVBV-k728UA4j.js → de-DE-DTI4WUSC-C0L6Nz8X.js} +1 -1
  58. package/dist/client/assets/diagram-E7M64L7V-CMt7BN5M.js +24 -0
  59. package/dist/client/assets/diagram-IFDJBPK2-BFMBUGpd.js +43 -0
  60. package/dist/client/assets/diagram-P4PSJMXO-CviA1xXr.js +24 -0
  61. package/dist/client/assets/dist-3bQB_we3.js +1 -0
  62. package/dist/client/assets/dist-3uAMa5w5.js +1 -0
  63. package/dist/client/assets/dist-8Igu3Ee_2.js +1 -0
  64. package/dist/client/assets/{dist-D9c0A4Uh.js → dist-B-02vKOA.js} +1 -1
  65. package/dist/client/assets/dist-B4uQVR_X.js +1 -0
  66. package/dist/client/assets/{dist-A0eSMIyy.js → dist-BLAlZer_.js} +1 -1
  67. package/dist/client/assets/dist-BU8uusJX.js +1 -0
  68. package/dist/client/assets/dist-BVB8rn7o.js +1 -0
  69. package/dist/client/assets/{dist-DveOCUUJ.js → dist-Bc2ND6i3.js} +1 -1
  70. package/dist/client/assets/{dist-Bay3vk5z.js → dist-BtnXjRx0.js} +1 -1
  71. package/dist/client/assets/{dist-CEYpWxod.js → dist-BzbYwa8m.js} +1 -1
  72. package/dist/client/assets/{dist-Ct1bmQnL.js → dist-BzpfHRaE.js} +1 -1
  73. package/dist/client/assets/{dist-BbKpzsTB.js → dist-CGV1S_as.js} +1 -1
  74. package/dist/client/assets/dist-CL-jjdvG.js +1 -0
  75. package/dist/client/assets/{dist-D0e6Qsad.js → dist-CXpKYW9s.js} +1 -1
  76. package/dist/client/assets/{dist-BchrxlnW.js → dist-CjII8VDS.js} +1 -1
  77. package/dist/client/assets/{dist-DnrO-JZd.js → dist-CxfohGIV.js} +1 -1
  78. package/dist/client/assets/{dist-CMHIjMVe.js → dist-D5QOYy7y.js} +1 -1
  79. package/dist/client/assets/{dist-CEtbxXlI.js → dist-DIi0uqLJ.js} +1 -1
  80. package/dist/client/assets/dist-DJ16N7ol.js +1 -0
  81. package/dist/client/assets/dist-DUvaQ-Bj.js +1 -0
  82. package/dist/client/assets/{dist-DnxPQ0-w.js → dist-DWJL3_bF.js} +6 -6
  83. package/dist/client/assets/dist-DsL7sqZR.js +1 -0
  84. package/dist/client/assets/{dist-DbhQ5ANS.js → dist-Dyt7n5Ui.js} +1 -1
  85. package/dist/client/assets/{dist-BOrlJDrR.js → dist-E_jPb93e.js} +1 -1
  86. package/dist/client/assets/{dist-D-gRgZ6e.js → dist-O1z0Ayg0.js} +1 -1
  87. package/dist/client/assets/dist-OQE68wIX.js +1 -0
  88. package/dist/client/assets/dist-k47-Io7D.js +1 -0
  89. package/dist/client/assets/{dist-Cdzvi8cf.js → dist-lDhnP-K1.js} +1 -1
  90. package/dist/client/assets/{dist-DS6mEQYy.js → dist-rMhng5DK.js} +1 -1
  91. package/dist/client/assets/{dockerfile-C0qQqxf9.js → dockerfile-D8_6_FRV.js} +1 -1
  92. package/dist/client/assets/{drawio-editor-CgbaOvpF.js → drawio-editor-B4sHHwWJ.js} +1 -1
  93. package/dist/client/assets/drawioEditor-DGpo2hcx.js +2 -0
  94. package/dist/client/assets/editor-session-BKHEYkbY.js +16 -0
  95. package/dist/client/assets/{el-GR-ZXDJ2OS4-Bbz93mrG.js → el-GR-ZXDJ2OS4-BH0saXds.js} +1 -1
  96. package/dist/client/assets/{embedded-editor-base-DXRHYz6R.css → embedded-editor-base-DgmRcsR8.css} +1 -1
  97. package/dist/client/assets/{en-CTDJDZ6K-BHbXrqU0.js → en-IQZW2TQM-CzlcEpq3.js} +1 -1
  98. package/dist/client/assets/{erDiagram-INFDFZHY-DP3f20BF.js → erDiagram-INFDFZHY-DlIf-fb7.js} +1 -1
  99. package/dist/client/assets/{es-ES-DYQHAD43-CReXU-Nn.js → es-ES-DYQHAD43-CyzL9Mni.js} +1 -1
  100. package/dist/client/assets/{eu-ES-QDSYU5Y3-jRpcaWwz.js → eu-ES-QDSYU5Y3-D2-x316S.js} +1 -1
  101. package/dist/client/assets/{excalidraw-editor-Dj0c0PO6.js → excalidraw-editor-CHbeNZu6.js} +2 -2
  102. package/dist/client/assets/excalidraw-editor-Dj3i59LW.css +1 -0
  103. package/dist/client/assets/{excalidraw-mermaid-stub-efoh2lJm.js → excalidraw-mermaid-stub-Bwe-bKcT.js} +1 -1
  104. package/dist/client/assets/excalidraw-scene-BF_bT1OL.js +176 -0
  105. package/dist/client/assets/excalidrawEditor-BhaTX2Ko.js +2 -0
  106. package/dist/client/assets/export-page-PeexH2QK.js +39 -0
  107. package/dist/client/assets/exportDocument-CtZKWE2c.js +2 -0
  108. package/dist/client/assets/{exportDocument-CLPYN_gg.css → exportDocument-DmV7Gngb.css} +1 -1
  109. package/dist/client/assets/{fa-IR-26LZG4PM-DP8pJ8e3.js → fa-IR-26LZG4PM-D8-trU2x.js} +1 -1
  110. package/dist/client/assets/{factor-2uy-lXe_.js → factor-Cz-hzBGH.js} +1 -1
  111. package/dist/client/assets/{fi-FI-6YS4KDE4-BLUDpNOj.js → fi-FI-6YS4KDE4-CCdRVFDQ.js} +1 -1
  112. package/dist/client/assets/file-kind-DBptLlF_.js +1 -0
  113. package/dist/client/assets/{flowDiagram-PKNHOUZH-CRbK5_5h.js → flowDiagram-PKNHOUZH-C_t-mkwb.js} +1 -1
  114. package/dist/client/assets/{fr-FR-BRLLPTZC-BoZz3Pi8.js → fr-FR-BRLLPTZC-Dqq-O5T_.js} +1 -1
  115. package/dist/client/assets/ganttDiagram-A5KZAMGK-BtK9Tb--.js +292 -0
  116. package/dist/client/assets/gitGraph-HDMCJU4V-CT7YfbD3.js +1 -0
  117. package/dist/client/assets/gitGraphDiagram-K3NZZRJ6-DULDLGiJ.js +65 -0
  118. package/dist/client/assets/{gl-ES-OKUZTLYG-CaEvhjDi.js → gl-ES-OKUZTLYG-BK7pbLbm.js} +1 -1
  119. package/dist/client/assets/{graphlib-DSzYgMXB.js → graphlib-BgRST-Qg.js} +1 -1
  120. package/dist/client/assets/{he-IL-26MGYIU7-DYOchgy9.js → he-IL-26MGYIU7-C3BuYKyY.js} +1 -1
  121. package/dist/client/assets/{hi-IN-Q4ZOGTP2-yRs8g46n.js → hi-IN-Q4ZOGTP2-BEvXWXnH.js} +1 -1
  122. package/dist/client/assets/{hu-HU-P2OXPSN5-1skPmtgc.js → hu-HU-P2OXPSN5-BWWZeJNp.js} +1 -1
  123. package/dist/client/assets/{id-ID-2EIKXYN6-iUugQJd9.js → id-ID-2EIKXYN6-DxSKi_aJ.js} +1 -1
  124. package/dist/client/assets/image-XLNPCCAD-CFiKwiWK.js +1 -0
  125. package/dist/client/assets/index-D69HOZHr.css +1 -0
  126. package/dist/client/assets/{index-CVgVzuh6.js → index-kPgEYvEX.js} +2 -2
  127. package/dist/client/assets/info-3K5VOQVL-DUpNyDC-.js +1 -0
  128. package/dist/client/assets/infoDiagram-LFFYTUFH-DFTI0nfs.js +2 -0
  129. package/dist/client/assets/{isEmpty-C7iPDOO3.js → isEmpty-CVvRj8fj.js} +1 -1
  130. package/dist/client/assets/{ishikawaDiagram-PHBUUO56-BDVPgkv4.js → ishikawaDiagram-PHBUUO56-DpBuDpC6.js} +1 -1
  131. package/dist/client/assets/{it-IT-4CFKVXI2-a5DFhzuI.js → it-IT-4CFKVXI2-BmA8wW6q.js} +1 -1
  132. package/dist/client/assets/{ja-JP-MAND2Z4V-DwogHVKd.js → ja-JP-MAND2Z4V-CLS1jI9o.js} +1 -1
  133. package/dist/client/assets/javascript-UJe68_xi.js +1 -0
  134. package/dist/client/assets/{journeyDiagram-4ABVD52K-DtNnwL48.js → journeyDiagram-4ABVD52K-DDur6iHm.js} +1 -1
  135. package/dist/client/assets/{jsx-runtime-B8dyIONw.js → jsx-runtime-C2p7wRmT.js} +1 -1
  136. package/dist/client/assets/{kaa-HQRTCXTJ-p81XNRfH.js → kaa-HQRTCXTJ-W15DEDPz.js} +1 -1
  137. package/dist/client/assets/{kab-KAB-JKIKKTGH-mV5VzQZc.js → kab-KAB-JKIKKTGH-MLh1inqS.js} +1 -1
  138. package/dist/client/assets/{kanban-definition-K7BYSVSG-C565sUNo.js → kanban-definition-K7BYSVSG-dA6NPLsg.js} +1 -1
  139. package/dist/client/assets/{kk-KZ-HXQ63ZFC-IIPX0GQv.js → kk-KZ-HXQ63ZFC-BtFrPeLs.js} +1 -1
  140. package/dist/client/assets/{km-KH-PKL3LSGX-D7WQFJuZ.js → km-KH-PKL3LSGX-xO5FyM9T.js} +1 -1
  141. package/dist/client/assets/{ko-KR-KXLREZX3-Bs1oLtJs.js → ko-KR-KXLREZX3-NZFoRybS.js} +1 -1
  142. package/dist/client/assets/{ku-TR-MJ4IER3X-DlxOs6aZ.js → ku-TR-MJ4IER3X-B5eVPIpK.js} +1 -1
  143. package/dist/client/assets/{line-D57TbKb7.js → line-B2GMovaI.js} +1 -1
  144. package/dist/client/assets/{linear-BIf852wI.js → linear-B2dOdA24.js} +1 -1
  145. package/dist/client/assets/{lt-LT-H6WFQ6FJ-xuo-3zKH.js → lt-LT-H6WFQ6FJ-D_7_OeJD.js} +1 -1
  146. package/dist/client/assets/{lv-LV-GOCK6SJW-C7S3M1nr.js → lv-LV-GOCK6SJW-CnpKr0oQ.js} +1 -1
  147. package/dist/client/assets/main-DSxNTtD-.js +1243 -0
  148. package/dist/client/assets/mermaid-parser.core-B1ogGcR8.js +4 -0
  149. package/dist/client/assets/{mermaid-runtime-DqncQoYK.js → mermaid-runtime-Bn8A6DGx.js} +3 -3
  150. package/dist/client/assets/{mindmap-definition-YRQLILUH-BbYzGfTD.js → mindmap-definition-YRQLILUH-DjQcsPoe.js} +1 -1
  151. package/dist/client/assets/{mr-IN-IXVLDMEQ-BsoowyZT.js → mr-IN-IXVLDMEQ-Pht2X_GK.js} +1 -1
  152. package/dist/client/assets/{my-MM-YG6MYTTD-DCqwN_K_.js → my-MM-YG6MYTTD-Cgq4HhPO.js} +1 -1
  153. package/dist/client/assets/{nb-NO-XGWJISD2-CZ5ytLgj.js → nb-NO-XGWJISD2-Bn_Bk2un.js} +1 -1
  154. package/dist/client/assets/{nl-NL-XVDVCPNC-wADsdb-h.js → nl-NL-XVDVCPNC-YkWSJS94.js} +1 -1
  155. package/dist/client/assets/{nn-NO-EMX5MJX5-D9zIKTL2.js → nn-NO-EMX5MJX5-DhP5eZJ7.js} +1 -1
  156. package/dist/client/assets/{nsis-CUd4RnvJ.js → nsis-QPGhLAeY.js} +1 -1
  157. package/dist/client/assets/{oc-FR-ROEINTVO-BSbBugJB.js → oc-FR-ROEINTVO-D3udMPnr.js} +1 -1
  158. package/dist/client/assets/{ordinal-B0PAtOQ6.js → ordinal-Dz3y_j0K.js} +1 -1
  159. package/dist/client/assets/{pa-IN-ZYN6SUDY-1pFA_3Pb.js → pa-IN-ZYN6SUDY-CR5YzFig.js} +1 -1
  160. package/dist/client/assets/packet-RMMSAZCW-DEwNbIrA.js +1 -0
  161. package/dist/client/assets/percentages-5DKR754L-D7n4T776.js +1 -0
  162. package/dist/client/assets/pie-UPGHQEXC-D5M_lSjo.js +1 -0
  163. package/dist/client/assets/pieDiagram-SKSYHLDU-jhHouFpk.js +30 -0
  164. package/dist/client/assets/{pl-PL-6VTG7PHC-DyYw0u_z.js → pl-PL-6VTG7PHC-_wZuoIDM.js} +1 -1
  165. package/dist/client/assets/preview-render-compiler-BjLlHmiQ.js +35 -0
  166. package/dist/client/assets/preview-render-compiler-Duy_3IcP.js +1 -0
  167. package/dist/client/assets/preview-render-worker-B4dH2yxj.js +59 -0
  168. package/dist/client/assets/{pt-BR-5YFKRR5G-DJCCBBDl.js → pt-BR-5YFKRR5G-M7gIm2Hi.js} +1 -1
  169. package/dist/client/assets/{pt-PT-GEIXXZ67-BPJd09Ax.js → pt-PT-GEIXXZ67-CcxWpkGj.js} +1 -1
  170. package/dist/client/assets/{pug-BqBF8qF7.js → pug-DkUcLYWt.js} +1 -1
  171. package/dist/client/assets/{quadrantDiagram-337W2JSQ-DhlKLozd.js → quadrantDiagram-337W2JSQ-CYKgdx7K.js} +1 -1
  172. package/dist/client/assets/quick-switcher-controller-DcyllYpm.js +5 -0
  173. package/dist/client/assets/radar-KQ55EAFF-AU1qh3Bw.js +1 -0
  174. package/dist/client/assets/{requirementDiagram-Z7DCOOCP-B7ZOMsIb.js → requirementDiagram-Z7DCOOCP-D9SHxoW7.js} +1 -1
  175. package/dist/client/assets/{ro-RO-E2P6TFZI-DWVyTV7V.js → ro-RO-E2P6TFZI-qR9noVzP.js} +1 -1
  176. package/dist/client/assets/{room-B0UGbzQj.js → room-yJaBAoEU.js} +1 -1
  177. package/dist/client/assets/{ru-RU-YBIIY43T-Dyar7CYM.js → ru-RU-YBIIY43T-CE4S_RX8.js} +1 -1
  178. package/dist/client/assets/{sankeyDiagram-WA2Y5GQK-CXRga6Op.js → sankeyDiagram-WA2Y5GQK-CfHe3D6R.js} +1 -1
  179. package/dist/client/assets/{sequenceDiagram-2WXFIKYE-CeSFlFx5.js → sequenceDiagram-2WXFIKYE-CZsMMqAJ.js} +1 -1
  180. package/dist/client/assets/{si-LK-673C2CI2-C61aLrIy.js → si-LK-673C2CI2-Bv6Avh3z.js} +1 -1
  181. package/dist/client/assets/{sk-SK-CKZHQ4AP-BlFwOxRD.js → sk-SK-CKZHQ4AP-Cnlpp55z.js} +1 -1
  182. package/dist/client/assets/{sl-SI-557H2GWM-DcAVW-_t.js → sl-SI-557H2GWM-BfGq7AQF.js} +1 -1
  183. package/dist/client/assets/stateDiagram-RAJIS63D-CoNZjTYV.js +1 -0
  184. package/dist/client/assets/stateDiagram-v2-FVOUBMTO-1zOw6NmQ.js +1 -0
  185. package/dist/client/assets/subset-shared.chunk-C9HjwTXy.js +1 -0
  186. package/dist/client/assets/{subset-worker.chunk-DVGT6bvR.js → subset-worker.chunk-BSCP6IiC.js} +1 -1
  187. package/dist/client/assets/{sv-SE-XOPKKDWS-BkhfOHzh.js → sv-SE-XOPKKDWS-B2_Vk-sp.js} +1 -1
  188. package/dist/client/assets/{ta-IN-XBH7DQI3-BIfwglZa.js → ta-IN-XBH7DQI3-BXQMZZIx.js} +1 -1
  189. package/dist/client/assets/{th-TH-TOCWH3R4-CkrxqVkf.js → th-TH-TOCWH3R4-C-ZIYMfH.js} +1 -1
  190. package/dist/client/assets/{timeline-definition-YZTLITO2-BXBHNWLQ.js → timeline-definition-YZTLITO2-DSe2mrG8.js} +1 -1
  191. package/dist/client/assets/{tr-TR-GXW6CYY5-CDdvG9rD.js → tr-TR-GXW6CYY5-dl702PMA.js} +1 -1
  192. package/dist/client/assets/treemap-KZPCXAKY-C9UI2fwP.js +1 -0
  193. package/dist/client/assets/{uk-UA-IJKTNUDG-DRHp0lWp.js → uk-UA-IJKTNUDG-CUYQvSSF.js} +1 -1
  194. package/dist/client/assets/{uz-UZ-TBZZEA4V-BIn-VE3Y.js → uz-UZ-TBZZEA4V-B9qw0PXX.js} +1 -1
  195. package/dist/client/assets/{vault-api-client-DIaCC56H.js → vault-api-client-BzHQseMN.js} +1 -1
  196. package/dist/client/assets/vault-utils-5Xr0MXCb.js +1 -0
  197. package/dist/client/assets/{vennDiagram-LZ73GAT5-Cs9aQmVM.js → vennDiagram-LZ73GAT5-xSzaIpy1.js} +1 -1
  198. package/dist/client/assets/{vi-VN-MULSGNVB-Du7t5I0v.js → vi-VN-MULSGNVB-DqxZ_sVc.js} +1 -1
  199. package/dist/client/assets/{xychartDiagram-JWTSCODW-B40ybbzC.js → xychartDiagram-JWTSCODW-C3vA70iJ.js} +1 -1
  200. package/dist/client/assets/{yjs-provider-reset-guard-DUP9XupO.js → yjs-provider-reset-guard-CtERLBID.js} +1 -1
  201. package/dist/client/assets/{zh-CN-MVX3E32U-RcjS3rjt.js → zh-CN-MVX3E32U-BM0aLuGc.js} +1 -1
  202. package/dist/client/assets/{zh-HK-JNU5RLIE-g8UeEw5v.js → zh-HK-JNU5RLIE-dmG_YD0d.js} +1 -1
  203. package/dist/client/assets/{zh-TW-LENVCA6T-DwV25BqC.js → zh-TW-LENVCA6T-LFgbiOi3.js} +1 -1
  204. package/dist/client/drawio-editor.html +1 -1
  205. package/dist/client/excalidraw-editor.html +1 -1
  206. package/dist/client/export-document.html +5 -5
  207. package/dist/client/index.html +4 -4
  208. package/docker-compose.yml +1 -0
  209. package/package.json +24 -21
  210. package/src/client/app/export-document.html +1 -1
  211. package/src/client/application/app-shell/ui-feature-shell.js +47 -1
  212. package/src/client/application/app-shell/ui-feature-toolbar.js +25 -3
  213. package/src/client/application/app-shell/workspace-feature.js +9 -0
  214. package/src/client/application/app-shell-elements.js +3 -0
  215. package/src/client/application/diagram-preview-hydrator.js +1 -1
  216. package/src/client/application/markdown-frontmatter.js +97 -0
  217. package/src/client/application/preview-render-compiler.js +60 -7
  218. package/src/client/application/preview-render-executor.js +8 -1
  219. package/src/client/application/preview-render-worker.js +4 -0
  220. package/src/client/application/preview-renderer.js +51 -1
  221. package/src/client/application/workspace-chrome-controller.js +25 -19
  222. package/src/client/application/workspace-coordinator.js +9 -0
  223. package/src/client/application/workspace-preview-controller.js +49 -3
  224. package/src/client/bootstrap/collabmd-app-shell.js +31 -2
  225. package/src/client/domain/markdown-formatting.js +1 -1
  226. package/src/client/domain/markdown-toolbar-actions.js +36 -0
  227. package/src/client/domain/vault-paths.js +19 -0
  228. package/src/client/export/export-page.js +11 -3
  229. package/src/client/export/export-pipeline.js +80 -3
  230. package/src/client/infrastructure/editor-session.js +4 -0
  231. package/src/client/infrastructure/editor-view-adapter.js +44 -7
  232. package/src/client/infrastructure/excalidraw-room-client.js +12 -4
  233. package/src/client/infrastructure/vault-api-client.js +54 -0
  234. package/src/client/presentation/app-shell-template.js +27 -0
  235. package/src/client/presentation/backlinks-panel.js +37 -11
  236. package/src/client/presentation/bases-preview-controller.js +444 -0
  237. package/src/client/presentation/file-action-controller.js +44 -2
  238. package/src/client/presentation/file-explorer-view.js +10 -2
  239. package/src/client/presentation/file-tree-state.js +9 -1
  240. package/src/client/presentation/git-diff-view-controller.js +7 -10
  241. package/src/client/presentation/quick-switcher-controller.js +54 -13
  242. package/src/client/styles/base.css +5 -0
  243. package/src/client/styles/export-document.css +12 -0
  244. package/src/client/styles/features/backlinks.css +65 -3
  245. package/src/client/styles/features/preview-markdown.css +347 -0
  246. package/src/client/styles/layout/editor-page.css +6 -0
  247. package/src/client/styles/layout/responsive.css +89 -0
  248. package/src/client/styles/layout/shell.css +14 -1
  249. package/src/client/styles/layout/view-modes.css +5 -0
  250. package/src/client/styles/overrides/codemirror.css +74 -0
  251. package/src/domain/file-kind.js +17 -2
  252. package/src/domain/wiki-link-resolver.js +41 -23
  253. package/src/domain/yaml-frontmatter.js +59 -0
  254. package/src/server/auth/create-auth-service.js +32 -6
  255. package/src/server/config/env.js +27 -0
  256. package/src/server/config/perf-logging.js +39 -0
  257. package/src/server/create-app-server.js +113 -7
  258. package/src/server/domain/backlink-index.js +129 -19
  259. package/src/server/domain/bases/base-query-service.js +2101 -0
  260. package/src/server/domain/collaboration/collaboration-document-store.js +13 -2
  261. package/src/server/domain/collaboration/collaboration-room.js +28 -5
  262. package/src/server/domain/workspace-state.js +52 -0
  263. package/src/server/infrastructure/git/history-service.js +1 -1
  264. package/src/server/infrastructure/http/create-request-handler.js +2 -0
  265. package/src/server/infrastructure/http/create-vault-api-command-handler.js +5 -0
  266. package/src/server/infrastructure/http/create-vault-api-handler.js +2 -0
  267. package/src/server/infrastructure/http/create-vault-api-query-handler.js +66 -0
  268. package/src/server/infrastructure/persistence/path-utils.js +1 -1
  269. package/src/server/infrastructure/persistence/pull-backup-store.js +1 -1
  270. package/src/server/infrastructure/persistence/vault-content-adapter.js +6 -0
  271. package/src/server/infrastructure/persistence/vault-file-store.js +88 -31
  272. package/src/server/infrastructure/workspace/file-system-sync-service.js +156 -31
  273. package/src/server/infrastructure/workspace/workspace-mutation-coordinator.js +47 -51
  274. package/src/server/shared/async-utils.js +25 -0
  275. package/dist/client/assets/architecture-PBZL5I3N-iRyVT2GQ.js +0 -1
  276. package/dist/client/assets/architectureDiagram-2XIMDMQ5-Bhh8YQHn.js +0 -36
  277. package/dist/client/assets/base-B5gONpJK.css +0 -1
  278. package/dist/client/assets/channel-s0w88EQN.js +0 -1
  279. package/dist/client/assets/chunk-27N2SPOM-DbHKsQ_j.js +0 -34
  280. package/dist/client/assets/chunk-GLR3WWYH-ZnuaBvXp.js +0 -2
  281. package/dist/client/assets/chunk-HHEYEP7N-DOQ0PCdH.js +0 -1
  282. package/dist/client/assets/chunk-QZHKN3VN-B0v4d-CS.js +0 -1
  283. package/dist/client/assets/classDiagram-VBA2DB6C-Bpdym3dj.js +0 -1
  284. package/dist/client/assets/classDiagram-v2-RAHNMMFH-CRAsdVDB.js +0 -1
  285. package/dist/client/assets/clone-C-n46MFF.js +0 -1
  286. package/dist/client/assets/dagre-KLK3FWXG-CXSnjrX-.js +0 -4
  287. package/dist/client/assets/diagram-E7M64L7V-De0StFef.js +0 -24
  288. package/dist/client/assets/diagram-IFDJBPK2-B2m6AJbU.js +0 -43
  289. package/dist/client/assets/diagram-P4PSJMXO-YBWLVENw.js +0 -24
  290. package/dist/client/assets/dist-BNcU46Ik.js +0 -1
  291. package/dist/client/assets/dist-BUEzOS23.js +0 -1
  292. package/dist/client/assets/dist-BflL-_8D.js +0 -1
  293. package/dist/client/assets/dist-CI_qEj5K.js +0 -1
  294. package/dist/client/assets/dist-CtFNDttZ.js +0 -1
  295. package/dist/client/assets/dist-DS_4VpEd.js +0 -1
  296. package/dist/client/assets/dist-DwsFUbuB.js +0 -1
  297. package/dist/client/assets/dist-VCYAp958.js +0 -1
  298. package/dist/client/assets/dist-Yxt8txtM.js +0 -1
  299. package/dist/client/assets/dist-npxgF_6V.js +0 -1
  300. package/dist/client/assets/dist-u0zDRMQt.js +0 -1
  301. package/dist/client/assets/drawioEditor-Eb2yYhjE.js +0 -2
  302. package/dist/client/assets/editor-session-DFzBn4RY.js +0 -16
  303. package/dist/client/assets/excalidraw-editor-Bat1FRoT.css +0 -1
  304. package/dist/client/assets/excalidraw-scene-CixfM-jL.js +0 -174
  305. package/dist/client/assets/excalidrawEditor-diK4VITg.js +0 -2
  306. package/dist/client/assets/export-page-CUOMczdp.js +0 -39
  307. package/dist/client/assets/exportDocument-BM4_f2n8.js +0 -2
  308. package/dist/client/assets/ganttDiagram-A5KZAMGK-R-AMIgxR.js +0 -292
  309. package/dist/client/assets/gitGraph-HDMCJU4V-kkuqHGSM.js +0 -1
  310. package/dist/client/assets/gitGraphDiagram-K3NZZRJ6-CIPit_Sh.js +0 -65
  311. package/dist/client/assets/image-32MOCVDX-BB6utPzr.js +0 -1
  312. package/dist/client/assets/index-BOOhEiLo.css +0 -1
  313. package/dist/client/assets/info-3K5VOQVL-DPN78whf.js +0 -1
  314. package/dist/client/assets/infoDiagram-LFFYTUFH-CF8jXFTm.js +0 -2
  315. package/dist/client/assets/javascript-8DvdgifH.js +0 -1
  316. package/dist/client/assets/main-C8adLQnt.js +0 -1174
  317. package/dist/client/assets/mermaid-parser.core-By_5k2SF.js +0 -4
  318. package/dist/client/assets/packet-RMMSAZCW-BymvQ5cQ.js +0 -1
  319. package/dist/client/assets/percentages-5DKR754L-CiI2D7zA.js +0 -1
  320. package/dist/client/assets/pie-UPGHQEXC-MmzJzWOE.js +0 -1
  321. package/dist/client/assets/pieDiagram-SKSYHLDU-CAU_gC7U.js +0 -30
  322. package/dist/client/assets/preview-render-compiler-CVfDHnqM.js +0 -1
  323. package/dist/client/assets/preview-render-compiler-CapHJDHT.js +0 -1
  324. package/dist/client/assets/preview-render-worker-wMS710Bv.js +0 -23
  325. package/dist/client/assets/quick-switcher-controller-DplOTsT3.js +0 -5
  326. package/dist/client/assets/radar-KQ55EAFF-CCohASSY.js +0 -1
  327. package/dist/client/assets/stateDiagram-RAJIS63D-CPoSrNwn.js +0 -1
  328. package/dist/client/assets/stateDiagram-v2-FVOUBMTO-5GW0Y21a.js +0 -1
  329. package/dist/client/assets/subset-shared.chunk-CC_u8ICU.js +0 -1
  330. package/dist/client/assets/treemap-KZPCXAKY-9kxB0uNY.js +0 -1
  331. package/dist/client/assets/vault-utils-BW53lKl1.js +0 -1
  332. /package/dist/client/assets/{apl-QJCYYBkj.js → apl-C1JYSI8J.js} +0 -0
  333. /package/dist/client/assets/{array-DwdVlTkF.js → array-B3agRrCs.js} +0 -0
  334. /package/dist/client/assets/{asciiarmor-DNy0UPqh.js → asciiarmor-DHW75j1s.js} +0 -0
  335. /package/dist/client/assets/{asn1-CNPXj-s7.js → asn1-CQiG40kG.js} +0 -0
  336. /package/dist/client/assets/{asterisk-BwMdLpT2.js → asterisk-BWExh0n4.js} +0 -0
  337. /package/dist/client/assets/{base-r5Zg2n3k.js → base-h1uscjTi.js} +0 -0
  338. /package/dist/client/assets/{brainfuck-C2gHT8aA.js → brainfuck-CTNFyOLg.js} +0 -0
  339. /package/dist/client/assets/{chunk-3PELD44J-CL87tpFo.js → chunk-3PELD44J-DymL2rGq.js} +0 -0
  340. /package/dist/client/assets/{chunk-A66AFZZU-DuceaGnc.js → chunk-A66AFZZU-BFHL744F.js} +0 -0
  341. /package/dist/client/assets/{chunk-SRAX5OIU-CC2mobFL.js → chunk-SRAX5OIU-CLVBQRWC.js} +0 -0
  342. /package/dist/client/assets/{clike-D5X7HJpo.js → clike-1_ZsiVV8.js} +0 -0
  343. /package/dist/client/assets/{clojure-BEDKZv_5.js → clojure-D-DYVqu7.js} +0 -0
  344. /package/dist/client/assets/{cmake-Y3shE7av.js → cmake-DtGL-Unu.js} +0 -0
  345. /package/dist/client/assets/{cobol-f-3TLk62.js → cobol-DP4QggbL.js} +0 -0
  346. /package/dist/client/assets/{coffeescript-C0XA9-xa.js → coffeescript-B_7eyHAa.js} +0 -0
  347. /package/dist/client/assets/{commonlisp-BOB6sIEu.js → commonlisp-COlJYiQT.js} +0 -0
  348. /package/dist/client/assets/{crystal-ByNgE_My.js → crystal-I_dE9xG-.js} +0 -0
  349. /package/dist/client/assets/{css-eaI-ENiR.js → css-CmhPNxBE.js} +0 -0
  350. /package/dist/client/assets/{cypher-CQ-dGGSi.js → cypher-DE6I2lIA.js} +0 -0
  351. /package/dist/client/assets/{cytoscape.esm-DBDRhUia.js → cytoscape.esm-Czjc507F.js} +0 -0
  352. /package/dist/client/assets/{d-D9pnu4Cr.js → d-BNkKjn0o.js} +0 -0
  353. /package/dist/client/assets/{defaultLocale-BWgun1yJ.js → defaultLocale-B_FbTTbl.js} +0 -0
  354. /package/dist/client/assets/{diff-z9q33Lo6.js → diff-BWuPUsEo.js} +0 -0
  355. /package/dist/client/assets/{dist-CsYRf4AV.js → dist-x7PIEmJu.js} +0 -0
  356. /package/dist/client/assets/{drawio-room-C592VDk7.js → drawio-room-DEivFyNV.js} +0 -0
  357. /package/dist/client/assets/{dtd-BDizf_te.js → dtd-C6brJFPg.js} +0 -0
  358. /package/dist/client/assets/{dylan-Bk__XCKW.js → dylan-Bft86ZSB.js} +0 -0
  359. /package/dist/client/assets/{ebnf-SzN4Kxtp.js → ebnf-D6ifG44A.js} +0 -0
  360. /package/dist/client/assets/{ecl-5ulxiKbt.js → ecl-M7Iek4lq.js} +0 -0
  361. /package/dist/client/assets/{eiffel-Bhoaqbb6.js → eiffel-DwxtewZF.js} +0 -0
  362. /package/dist/client/assets/{elm-C3je846J.js → elm-B1TncobV.js} +0 -0
  363. /package/dist/client/assets/{erlang-Cgk9SIAz.js → erlang-BDJZNtt8.js} +0 -0
  364. /package/dist/client/assets/{excalidraw-mermaid-stub-B_2dv3Ll.js → excalidraw-mermaid-stub-BZPU4ZhU.js} +0 -0
  365. /package/dist/client/assets/{fcl-dvkZwp9p.js → fcl-BWKK0S4-.js} +0 -0
  366. /package/dist/client/assets/{forth-DmfSa3jN.js → forth-nvhcMz63.js} +0 -0
  367. /package/dist/client/assets/{fortran-BsZAiNnN.js → fortran-BZID-z10.js} +0 -0
  368. /package/dist/client/assets/{gas-DBpKE9ut.js → gas-DjQsZDGE.js} +0 -0
  369. /package/dist/client/assets/{gherkin-CceEbBs7.js → gherkin-S0kHlzux.js} +0 -0
  370. /package/dist/client/assets/{groovy-CxJnDvES.js → groovy-BEKazBrO.js} +0 -0
  371. /package/dist/client/assets/{haskell-CUSb34Xy.js → haskell-C6qH3-aI.js} +0 -0
  372. /package/dist/client/assets/{haxe-6EHO_h-N.js → haxe-BY9d_5nB.js} +0 -0
  373. /package/dist/client/assets/{http-C3qcBpvG.js → http-DG1Y9fpK.js} +0 -0
  374. /package/dist/client/assets/{idl-C95wIO2I.js → idl-B64p3NTJ.js} +0 -0
  375. /package/dist/client/assets/{image-blob-reduce.esm-BaW4gpT9.js → image-blob-reduce.esm-DriR2zT9.js} +0 -0
  376. /package/dist/client/assets/{init-Bjj5fg68.js → init-DtLQcSuO.js} +0 -0
  377. /package/dist/client/assets/{isArrayLikeObject-Cmt1CYnI.js → isArrayLikeObject-BId_dPHM.js} +0 -0
  378. /package/dist/client/assets/{javascript-aWB87b1w.js → javascript-CdiVhQeA.js} +0 -0
  379. /package/dist/client/assets/{julia-DF9PPAXG.js → julia-B22G9Bym.js} +0 -0
  380. /package/dist/client/assets/{katex-BPsFnA3D.js → katex-CXYULLWy.js} +0 -0
  381. /package/dist/client/assets/{livescript-CnOyWwUY.js → livescript-CkcuHqeS.js} +0 -0
  382. /package/dist/client/assets/{lua-a0rEq19C.js → lua-kutgyRGY.js} +0 -0
  383. /package/dist/client/assets/{math-BaavbII8.js → math-B-LMBwub.js} +0 -0
  384. /package/dist/client/assets/{mathematica-CKUq0Ojc.js → mathematica-CKVhKnoY.js} +0 -0
  385. /package/dist/client/assets/{mbox-a-u2PLog.js → mbox-DANyzFJ2.js} +0 -0
  386. /package/dist/client/assets/{mirc-BOd43sOX.js → mirc-BVG2S5rO.js} +0 -0
  387. /package/dist/client/assets/{mllike-fHruGivh.js → mllike-C0p7lv48.js} +0 -0
  388. /package/dist/client/assets/{modelica-B0NJqf1C.js → modelica-vJ-Qa9jV.js} +0 -0
  389. /package/dist/client/assets/{mscgen-DJZ33SrF.js → mscgen-vUD-SWGJ.js} +0 -0
  390. /package/dist/client/assets/{mumps-DvMvHTxU.js → mumps-D0KfUTSd.js} +0 -0
  391. /package/dist/client/assets/{nginx-BVAs8laz.js → nginx-DkVceJrH.js} +0 -0
  392. /package/dist/client/assets/{ntriples-DrdyAZU1.js → ntriples-BBuCIfS0.js} +0 -0
  393. /package/dist/client/assets/{octave-_YqJ0g7E.js → octave-BTv2CqSQ.js} +0 -0
  394. /package/dist/client/assets/{oz-k7T3LoMr.js → oz-D8SjVDNU.js} +0 -0
  395. /package/dist/client/assets/{pascal-CftsTvte.js → pascal-T-tfhVyx.js} +0 -0
  396. /package/dist/client/assets/{path-BUmMWM1-.js → path-DIlZIGue.js} +0 -0
  397. /package/dist/client/assets/{perl-CbsLFc7A.js → perl-BDrCkHRd.js} +0 -0
  398. /package/dist/client/assets/{pica-By-YDy_B.js → pica-C1TdTz-C.js} +0 -0
  399. /package/dist/client/assets/{pig-C-jTwMS-.js → pig-BEyI4fPq.js} +0 -0
  400. /package/dist/client/assets/{powershell-DqXLgSHX.js → powershell-DtnFc6GG.js} +0 -0
  401. /package/dist/client/assets/{preview-diagram-utils-Dc83ucbv.js → preview-diagram-utils-COt-IYMD.js} +0 -0
  402. /package/dist/client/assets/{preview-render-profile-DPzmho7I.js → preview-render-profile-CR4dJZrp.js} +0 -0
  403. /package/dist/client/assets/{properties-05jaw55P.js → properties-DWUvbxV9.js} +0 -0
  404. /package/dist/client/assets/{protobuf-DThTsZQN.js → protobuf-CQGoYyfE.js} +0 -0
  405. /package/dist/client/assets/{puppet-DuHxMpoj.js → puppet-Dd-qWO3p.js} +0 -0
  406. /package/dist/client/assets/{python-BiE2VHJI.js → python-CZtTmYkS.js} +0 -0
  407. /package/dist/client/assets/{q-DH46YfNw.js → q-I27iQntV.js} +0 -0
  408. /package/dist/client/assets/{r-DmEm46kJ.js → r-DN_EydfL.js} +0 -0
  409. /package/dist/client/assets/{rough.esm-jZQkcmER.js → rough.esm-DE_lJ5Ge.js} +0 -0
  410. /package/dist/client/assets/{roundRect-CI6UmGg6.js → roundRect-BzEouiv_.js} +0 -0
  411. /package/dist/client/assets/{rpm-DILIIbRB.js → rpm-CjWxLM68.js} +0 -0
  412. /package/dist/client/assets/{ruby-2LcnHEMS.js → ruby-CB34f2Gf.js} +0 -0
  413. /package/dist/client/assets/{runtime-config-CqX_f_Q4.js → runtime-config-CqhchMC4.js} +0 -0
  414. /package/dist/client/assets/{sas-Bn81MKuB.js → sas-Bji4HDQq.js} +0 -0
  415. /package/dist/client/assets/{scheme-B8kPNbgd.js → scheme-C3elI80V.js} +0 -0
  416. /package/dist/client/assets/{shell-CGj6v8kb.js → shell-DUveK2Hb.js} +0 -0
  417. /package/dist/client/assets/{sieve-CfVNFN1K.js → sieve-2ogwMVx4.js} +0 -0
  418. /package/dist/client/assets/{simple-mode-_FSHdiXs.js → simple-mode-pOKc0mfx.js} +0 -0
  419. /package/dist/client/assets/{smalltalk-BpIFyCPt.js → smalltalk-BuGhc6lW.js} +0 -0
  420. /package/dist/client/assets/{solr-B7iFaetn.js → solr-DTxshpm8.js} +0 -0
  421. /package/dist/client/assets/{sparql-COhgMTFK.js → sparql-BOvq0dv7.js} +0 -0
  422. /package/dist/client/assets/{spreadsheet-BzuffEeg.js → spreadsheet-C6Vbtl9-.js} +0 -0
  423. /package/dist/client/assets/{sql-13lT5zDl.js → sql-DDFeQNTK.js} +0 -0
  424. /package/dist/client/assets/{src-E3c2cohN.js → src-Pgt9Gp65.js} +0 -0
  425. /package/dist/client/assets/{stex-BRSfZZYG.js → stex-CEwW0Q_0.js} +0 -0
  426. /package/dist/client/assets/{stylus-fFo0QRk_.js → stylus-D1SZIMDs.js} +0 -0
  427. /package/dist/client/assets/{swift-wb5gyb6a.js → swift-BCxe4-cw.js} +0 -0
  428. /package/dist/client/assets/{tcl-BJA7GgWY.js → tcl-SPk7uiDB.js} +0 -0
  429. /package/dist/client/assets/{textile-BQjiYu-x.js → textile-C48beRus.js} +0 -0
  430. /package/dist/client/assets/{tiddlywiki-D2vUXB6n.js → tiddlywiki-CiImjFLN.js} +0 -0
  431. /package/dist/client/assets/{tiki-BFhpdznG.js → tiki-HkXZ4BIW.js} +0 -0
  432. /package/dist/client/assets/{toml-DN06iQUw.js → toml-BmfpMy1_.js} +0 -0
  433. /package/dist/client/assets/{troff-DuQfjhPH.js → troff-BjbEOT5E.js} +0 -0
  434. /package/dist/client/assets/{ttcn-BCTy6d50.js → ttcn-NA-V4KnY.js} +0 -0
  435. /package/dist/client/assets/{ttcn-cfg-BYnZQqGa.js → ttcn-cfg-TPHncdGN.js} +0 -0
  436. /package/dist/client/assets/{turtle-BvN-Me9x.js → turtle-GBz_E4RG.js} +0 -0
  437. /package/dist/client/assets/{vb-DYk3wW9u.js → vb-C19AQWqO.js} +0 -0
  438. /package/dist/client/assets/{vbscript-BKI61VS6.js → vbscript-CHJk3s95.js} +0 -0
  439. /package/dist/client/assets/{velocity-BrtitHHA.js → velocity-Ya0P4sQU.js} +0 -0
  440. /package/dist/client/assets/{verilog-CjUx3yiL.js → verilog-C4wTycyo.js} +0 -0
  441. /package/dist/client/assets/{vhdl-CPWwYF4V.js → vhdl-Bwndeg44.js} +0 -0
  442. /package/dist/client/assets/{webidl-PiVOzma8.js → webidl-DttrYZRT.js} +0 -0
  443. /package/dist/client/assets/{xquery-CiTzM_oK.js → xquery-CEDTd8qs.js} +0 -0
  444. /package/dist/client/assets/{yacas-4QS9CntY.js → yacas-C7dxlPB0.js} +0 -0
  445. /package/dist/client/assets/{z80-BxidrTKR.js → z80-BqEfFSnA.js} +0 -0
@@ -0,0 +1,2101 @@
1
+ import { basename, dirname, extname } from 'node:path';
2
+
3
+ import yaml from 'js-yaml';
4
+
5
+ import { createWikiTargetIndex, resolveWikiTargetWithIndex } from '../../../domain/wiki-link-resolver.js';
6
+ import {
7
+ getVaultFileExtension,
8
+ isImageAttachmentFilePath,
9
+ isMarkdownFilePath,
10
+ stripVaultFileExtension,
11
+ } from '../../../domain/file-kind.js';
12
+ import { extractYamlFrontmatter } from '../../../domain/yaml-frontmatter.js';
13
+ import { mapWithConcurrency } from '../../shared/async-utils.js';
14
+
15
+ const INTERNAL_LINK_RE = /(!)?\[\[([^\]|#]+)(?:#[^\]|]+)?(?:\|[^\]]+)?\]\]/g;
16
+ const INLINE_TAG_RE = /(^|[\s(])#([A-Za-z0-9/_-]+)/g;
17
+ const SUPPORTED_VIEW_TYPES = new Set(['cards', 'list', 'table']);
18
+ const INDEX_READ_CONCURRENCY = 8;
19
+
20
+ function isPlainObject(value) {
21
+ return Object.prototype.toString.call(value) === '[object Object]';
22
+ }
23
+
24
+ function capitalize(value = '') {
25
+ const normalized = String(value ?? '').trim();
26
+ if (!normalized) {
27
+ return '';
28
+ }
29
+
30
+ return `${normalized.charAt(0).toUpperCase()}${normalized.slice(1)}`;
31
+ }
32
+
33
+ function normalizeTags(value) {
34
+ if (Array.isArray(value)) {
35
+ return value
36
+ .map((entry) => String(entry ?? '').trim().replace(/^#/u, ''))
37
+ .filter(Boolean);
38
+ }
39
+
40
+ const normalized = String(value ?? '').trim().replace(/^#/u, '');
41
+ return normalized ? [normalized] : [];
42
+ }
43
+
44
+ function normalizeVaultPathSegments(pathValue = '') {
45
+ return String(pathValue ?? '')
46
+ .replace(/\\/g, '/')
47
+ .split('/')
48
+ .filter(Boolean);
49
+ }
50
+
51
+ function resolveVaultRelativePath(fromFilePath, relativePath) {
52
+ const sourceSegments = normalizeVaultPathSegments(fromFilePath);
53
+ const targetSegments = String(relativePath ?? '')
54
+ .split('/')
55
+ .map((segment) => {
56
+ try {
57
+ return decodeURIComponent(segment);
58
+ } catch {
59
+ return segment;
60
+ }
61
+ });
62
+
63
+ if (targetSegments.length === 0) {
64
+ return '';
65
+ }
66
+
67
+ sourceSegments.pop();
68
+ const resolvedSegments = [...sourceSegments];
69
+
70
+ for (const rawSegment of targetSegments) {
71
+ const segment = String(rawSegment ?? '').trim();
72
+ if (!segment || segment === '.') {
73
+ continue;
74
+ }
75
+
76
+ if (segment === '..') {
77
+ if (resolvedSegments.length === 0) {
78
+ return '';
79
+ }
80
+ resolvedSegments.pop();
81
+ continue;
82
+ }
83
+
84
+ resolvedSegments.push(segment);
85
+ }
86
+
87
+ return resolvedSegments.join('/');
88
+ }
89
+
90
+ function extractInlineTags(markdownText = '') {
91
+ const tags = new Set();
92
+ let match;
93
+ while ((match = INLINE_TAG_RE.exec(String(markdownText ?? ''))) !== null) {
94
+ tags.add(match[2]);
95
+ }
96
+ return [...tags];
97
+ }
98
+
99
+ function extractReferences(markdownText = '', wikiTargetIndex) {
100
+ const links = [];
101
+ const embeds = [];
102
+ let match;
103
+ while ((match = INTERNAL_LINK_RE.exec(String(markdownText ?? ''))) !== null) {
104
+ const isEmbed = Boolean(match[1]);
105
+ const rawTarget = String(match[2] ?? '').trim();
106
+ if (!rawTarget) {
107
+ continue;
108
+ }
109
+
110
+ const resolvedPath = resolveWikiTargetWithIndex(rawTarget, wikiTargetIndex);
111
+ const linkValue = createLinkValue(resolvedPath || rawTarget, {
112
+ exists: Boolean(resolvedPath),
113
+ rawTarget,
114
+ });
115
+ links.push(linkValue);
116
+ if (isEmbed) {
117
+ embeds.push(linkValue);
118
+ }
119
+ }
120
+ return { embeds, links };
121
+ }
122
+
123
+ function dedupeLinkValues(values = []) {
124
+ const seen = new Set();
125
+ return values.filter((value) => {
126
+ const key = value?.external
127
+ ? `external:${value.url || value.rawTarget || value.display || ''}`
128
+ : `path:${value.path || value.rawTarget || value.display || ''}`;
129
+ if (!key || seen.has(key)) {
130
+ return false;
131
+ }
132
+ seen.add(key);
133
+ return true;
134
+ });
135
+ }
136
+
137
+ function createLinkValue(target, {
138
+ display = '',
139
+ exists = false,
140
+ external = false,
141
+ rawTarget = '',
142
+ } = {}) {
143
+ return {
144
+ __baseType: 'link',
145
+ display: display ? String(display) : '',
146
+ exists: Boolean(exists),
147
+ external: Boolean(external),
148
+ path: external ? '' : String(target ?? ''),
149
+ rawTarget: String(rawTarget || target || ''),
150
+ url: external ? String(target ?? '') : '',
151
+ };
152
+ }
153
+
154
+ function createFormulaNamespace(row, evaluationState) {
155
+ return {
156
+ __baseType: 'formula-namespace',
157
+ evaluationState,
158
+ row,
159
+ };
160
+ }
161
+
162
+ function createContextFileValue(fileValue) {
163
+ return fileValue ?? null;
164
+ }
165
+
166
+ function compareVaultPaths(left = '', right = '') {
167
+ return String(left).localeCompare(String(right), undefined, { sensitivity: 'base' });
168
+ }
169
+
170
+ function isWorkspaceFileEntry(entry = {}) {
171
+ return entry?.nodeType === 'file' || entry?.type !== 'directory';
172
+ }
173
+
174
+ function listWorkspaceFilePaths(workspaceState = {}) {
175
+ if (Array.isArray(workspaceState?.filePaths)) {
176
+ return [...workspaceState.filePaths].sort(compareVaultPaths);
177
+ }
178
+
179
+ return Array.from(workspaceState?.entries?.values?.() ?? [])
180
+ .filter((entry) => isWorkspaceFileEntry(entry))
181
+ .map((entry) => entry.path)
182
+ .sort(compareVaultPaths);
183
+ }
184
+
185
+ function normalizeWikiTargetKey(target = '') {
186
+ const normalizedTarget = String(target ?? '').trim();
187
+ if (!normalizedTarget) {
188
+ return '';
189
+ }
190
+
191
+ return getVaultFileExtension(normalizedTarget)
192
+ ? normalizedTarget
193
+ : `${normalizedTarget}.md`;
194
+ }
195
+
196
+ function collectWikiTargetKeysForFilePath(filePath = '') {
197
+ const normalizedPath = String(filePath ?? '').trim();
198
+ if (!normalizedPath) {
199
+ return [];
200
+ }
201
+
202
+ const segments = normalizedPath.split('/').filter(Boolean);
203
+ const keys = [];
204
+ for (let index = 0; index < segments.length; index += 1) {
205
+ keys.push(segments.slice(index).join('/'));
206
+ }
207
+
208
+ if (isMarkdownFilePath(normalizedPath)) {
209
+ const rawSegments = normalizedPath.replace(/\.md$/i, '').split('/').filter(Boolean);
210
+ for (let index = 0; index < rawSegments.length; index += 1) {
211
+ keys.push(rawSegments.slice(index).join('/'));
212
+ }
213
+ }
214
+
215
+ return [...new Set(keys)];
216
+ }
217
+
218
+ function normalizeBaseDefinition(source = '') {
219
+ const raw = yaml.load(String(source ?? '')) ?? {};
220
+ const rawObject = isPlainObject(raw) ? raw : {};
221
+ const rawProperties = isPlainObject(rawObject.properties) ? rawObject.properties : {};
222
+ const properties = Object.entries(rawProperties).reduce((acc, [id, config]) => {
223
+ const normalizedConfig = isPlainObject(config) ? { ...config } : {};
224
+ acc[id] = {
225
+ displayName: typeof normalizedConfig.displayName === 'string' ? normalizedConfig.displayName : null,
226
+ formula: typeof normalizedConfig.formula === 'string' ? normalizedConfig.formula : null,
227
+ id,
228
+ raw: normalizedConfig,
229
+ };
230
+ return acc;
231
+ }, {});
232
+
233
+ const rawViews = Array.isArray(rawObject.views) ? rawObject.views : [];
234
+ const views = rawViews.map((rawView, index) => normalizeBaseView(rawView, index));
235
+ if (views.length === 0) {
236
+ views.push(normalizeBaseView({ name: 'Table', type: 'table' }, 0));
237
+ }
238
+
239
+ return {
240
+ filters: rawObject.filters ?? null,
241
+ properties,
242
+ raw: rawObject,
243
+ views,
244
+ };
245
+ }
246
+
247
+ function normalizeBaseView(rawView, index) {
248
+ const view = isPlainObject(rawView) ? rawView : {};
249
+ const type = typeof view.type === 'string' ? view.type : 'table';
250
+ const name = typeof view.name === 'string' && view.name.trim()
251
+ ? view.name.trim()
252
+ : `${capitalize(type)} ${index + 1}`;
253
+ return {
254
+ extra: Object.entries(view).reduce((acc, [key, value]) => {
255
+ if ([
256
+ 'filters',
257
+ 'groupBy',
258
+ 'group_by',
259
+ 'image',
260
+ 'limit',
261
+ 'name',
262
+ 'order',
263
+ 'properties',
264
+ 'sort',
265
+ 'sorts',
266
+ 'summaries',
267
+ 'type',
268
+ ].includes(key)) {
269
+ return acc;
270
+ }
271
+ acc[key] = value;
272
+ return acc;
273
+ }, {}),
274
+ filters: view.filters ?? null,
275
+ groupBy: typeof view.groupBy === 'string'
276
+ ? view.groupBy
277
+ : (typeof view.group_by === 'string' ? view.group_by : null),
278
+ id: `view-${index}`,
279
+ image: typeof view.image === 'string' ? view.image : null,
280
+ limit: Number.isFinite(Number(view.limit)) ? Math.max(0, Number(view.limit)) : null,
281
+ name,
282
+ order: normalizeViewOrder(view.order ?? view.properties),
283
+ sort: normalizeViewSort(view.sort ?? view.sorts),
284
+ summaries: normalizeSummaries(view.summaries),
285
+ supported: SUPPORTED_VIEW_TYPES.has(type),
286
+ type,
287
+ };
288
+ }
289
+
290
+ function normalizeViewOrder(value) {
291
+ if (Array.isArray(value)) {
292
+ return value
293
+ .map((entry) => {
294
+ if (typeof entry === 'string') {
295
+ return entry;
296
+ }
297
+ if (isPlainObject(entry)) {
298
+ return entry.id ?? entry.property ?? entry.name ?? null;
299
+ }
300
+ return null;
301
+ })
302
+ .filter(Boolean);
303
+ }
304
+
305
+ if (typeof value === 'string' && value.trim()) {
306
+ return [value.trim()];
307
+ }
308
+
309
+ return [];
310
+ }
311
+
312
+ function normalizeViewSort(value) {
313
+ if (typeof value === 'string' && value.trim()) {
314
+ return [{ direction: 'asc', property: value.trim() }];
315
+ }
316
+
317
+ if (!Array.isArray(value)) {
318
+ return [];
319
+ }
320
+
321
+ return value
322
+ .map((entry) => {
323
+ if (typeof entry === 'string') {
324
+ return { direction: 'asc', property: entry };
325
+ }
326
+ if (!isPlainObject(entry)) {
327
+ return null;
328
+ }
329
+
330
+ const property = entry.property ?? entry.id ?? entry.name ?? null;
331
+ if (typeof property !== 'string' || !property.trim()) {
332
+ return null;
333
+ }
334
+
335
+ const direction = String(entry.direction ?? entry.order ?? 'asc').toLowerCase() === 'desc'
336
+ ? 'desc'
337
+ : 'asc';
338
+ return { direction, property: property.trim() };
339
+ })
340
+ .filter(Boolean);
341
+ }
342
+
343
+ function normalizeSummaries(value) {
344
+ if (!value) {
345
+ return [];
346
+ }
347
+
348
+ if (Array.isArray(value)) {
349
+ return value
350
+ .map((entry, index) => normalizeSummary(entry, index))
351
+ .filter(Boolean);
352
+ }
353
+
354
+ if (isPlainObject(value)) {
355
+ const entries = [];
356
+ Object.entries(value).forEach(([property, propertySummaries]) => {
357
+ if (Array.isArray(propertySummaries)) {
358
+ propertySummaries.forEach((entry, index) => {
359
+ const normalized = normalizeSummary(entry, index, property);
360
+ if (normalized) {
361
+ entries.push(normalized);
362
+ }
363
+ });
364
+ return;
365
+ }
366
+
367
+ const normalized = normalizeSummary(propertySummaries, entries.length, property);
368
+ if (normalized) {
369
+ entries.push(normalized);
370
+ }
371
+ });
372
+ return entries;
373
+ }
374
+
375
+ return [];
376
+ }
377
+
378
+ function normalizeSummary(entry, index, property = null) {
379
+ if (typeof entry === 'string') {
380
+ return {
381
+ id: `summary-${index}`,
382
+ label: capitalize(entry),
383
+ property,
384
+ type: entry.toLowerCase(),
385
+ };
386
+ }
387
+
388
+ if (!isPlainObject(entry)) {
389
+ return null;
390
+ }
391
+
392
+ const summaryProperty = typeof (entry.property ?? property) === 'string'
393
+ ? String(entry.property ?? property).trim()
394
+ : null;
395
+ const formula = typeof entry.formula === 'string' ? entry.formula : null;
396
+ const type = typeof entry.type === 'string' ? entry.type.toLowerCase() : (formula ? 'custom' : null);
397
+ if (!summaryProperty) {
398
+ return null;
399
+ }
400
+
401
+ return {
402
+ formula,
403
+ id: `summary-${index}`,
404
+ label: typeof entry.name === 'string' ? entry.name : capitalize(type || 'Summary'),
405
+ property: summaryProperty,
406
+ type,
407
+ };
408
+ }
409
+
410
+ function tokenizeExpression(source = '') {
411
+ const tokens = [];
412
+ const text = String(source ?? '');
413
+ let index = 0;
414
+
415
+ while (index < text.length) {
416
+ const character = text[index];
417
+ if (/\s/u.test(character)) {
418
+ index += 1;
419
+ continue;
420
+ }
421
+
422
+ const twoChar = text.slice(index, index + 2);
423
+ const threeChar = text.slice(index, index + 3);
424
+ if (['&&', '||', '==', '!=', '<=', '>='].includes(twoChar)) {
425
+ tokens.push({ type: 'operator', value: twoChar });
426
+ index += 2;
427
+ continue;
428
+ }
429
+ if (threeChar === '...') {
430
+ tokens.push({ type: 'operator', value: threeChar });
431
+ index += 3;
432
+ continue;
433
+ }
434
+ if ('+-*/%!<>()[]{}.,:'.includes(character)) {
435
+ tokens.push({
436
+ type: '()[]{}.,:'.includes(character) ? 'punctuation' : 'operator',
437
+ value: character,
438
+ });
439
+ index += 1;
440
+ continue;
441
+ }
442
+ if (character === '"' || character === '\'') {
443
+ let value = '';
444
+ let cursor = index + 1;
445
+ while (cursor < text.length) {
446
+ const nextCharacter = text[cursor];
447
+ if (nextCharacter === '\\') {
448
+ const escaped = text[cursor + 1] ?? '';
449
+ value += escaped;
450
+ cursor += 2;
451
+ continue;
452
+ }
453
+ if (nextCharacter === character) {
454
+ break;
455
+ }
456
+ value += nextCharacter;
457
+ cursor += 1;
458
+ }
459
+ if (text[cursor] !== character) {
460
+ throw new Error(`Unterminated string in expression: ${source}`);
461
+ }
462
+ tokens.push({ type: 'string', value });
463
+ index = cursor + 1;
464
+ continue;
465
+ }
466
+ if (/\d/u.test(character)) {
467
+ let cursor = index + 1;
468
+ while (cursor < text.length && /[\d.]/u.test(text[cursor])) {
469
+ cursor += 1;
470
+ }
471
+ tokens.push({ type: 'number', value: text.slice(index, cursor) });
472
+ index = cursor;
473
+ continue;
474
+ }
475
+ if (/[A-Za-z_$]/u.test(character)) {
476
+ let cursor = index + 1;
477
+ while (cursor < text.length && /[A-Za-z0-9_$]/u.test(text[cursor])) {
478
+ cursor += 1;
479
+ }
480
+ tokens.push({ type: 'identifier', value: text.slice(index, cursor) });
481
+ index = cursor;
482
+ continue;
483
+ }
484
+
485
+ throw new Error(`Unexpected token "${character}" in expression: ${source}`);
486
+ }
487
+
488
+ return tokens;
489
+ }
490
+
491
+ const BINARY_PRECEDENCE = {
492
+ '||': 1,
493
+ '&&': 2,
494
+ '==': 3,
495
+ '!=': 3,
496
+ '<': 4,
497
+ '<=': 4,
498
+ '>': 4,
499
+ '>=': 4,
500
+ '+': 5,
501
+ '-': 5,
502
+ '*': 6,
503
+ '/': 6,
504
+ '%': 6,
505
+ };
506
+
507
+ function parseExpression(source = '') {
508
+ const tokens = tokenizeExpression(source);
509
+ let index = 0;
510
+
511
+ const peek = () => tokens[index] ?? null;
512
+ const consume = (expectedValue = null) => {
513
+ const token = tokens[index] ?? null;
514
+ if (!token) {
515
+ throw new Error(`Unexpected end of expression: ${source}`);
516
+ }
517
+ if (expectedValue !== null && token.value !== expectedValue) {
518
+ throw new Error(`Expected "${expectedValue}" in expression: ${source}`);
519
+ }
520
+ index += 1;
521
+ return token;
522
+ };
523
+
524
+ const parsePrimary = () => {
525
+ const token = peek();
526
+ if (!token) {
527
+ throw new Error(`Unexpected end of expression: ${source}`);
528
+ }
529
+
530
+ if (token.type === 'number') {
531
+ consume();
532
+ return { type: 'Literal', value: Number(token.value) };
533
+ }
534
+
535
+ if (token.type === 'string') {
536
+ consume();
537
+ return { type: 'Literal', value: token.value };
538
+ }
539
+
540
+ if (token.type === 'identifier') {
541
+ consume();
542
+ if (token.value === 'true') return { type: 'Literal', value: true };
543
+ if (token.value === 'false') return { type: 'Literal', value: false };
544
+ if (token.value === 'null') return { type: 'Literal', value: null };
545
+ return { name: token.value, type: 'Identifier' };
546
+ }
547
+
548
+ if (token.value === '(') {
549
+ consume('(');
550
+ const expression = parseBinaryExpression(0);
551
+ consume(')');
552
+ return expression;
553
+ }
554
+
555
+ if (token.value === '[') {
556
+ consume('[');
557
+ const elements = [];
558
+ while (peek() && peek().value !== ']') {
559
+ elements.push(parseBinaryExpression(0));
560
+ if (peek()?.value === ',') {
561
+ consume(',');
562
+ }
563
+ }
564
+ consume(']');
565
+ return { elements, type: 'ArrayExpression' };
566
+ }
567
+
568
+ if (token.value === '{') {
569
+ consume('{');
570
+ const properties = [];
571
+ while (peek() && peek().value !== '}') {
572
+ const keyToken = consume();
573
+ const key = keyToken.type === 'identifier' ? keyToken.value : String(keyToken.value ?? '');
574
+ consume(':');
575
+ properties.push({ key, value: parseBinaryExpression(0) });
576
+ if (peek()?.value === ',') {
577
+ consume(',');
578
+ }
579
+ }
580
+ consume('}');
581
+ return { properties, type: 'ObjectExpression' };
582
+ }
583
+
584
+ throw new Error(`Unexpected token "${token.value}" in expression: ${source}`);
585
+ };
586
+
587
+ const parsePostfix = (baseNode) => {
588
+ let node = baseNode;
589
+ while (peek()) {
590
+ if (peek().value === '.') {
591
+ consume('.');
592
+ const property = consume();
593
+ if (property.type !== 'identifier') {
594
+ throw new Error(`Expected property name in expression: ${source}`);
595
+ }
596
+ node = {
597
+ computed: false,
598
+ object: node,
599
+ property: { name: property.value, type: 'Identifier' },
600
+ type: 'MemberExpression',
601
+ };
602
+ continue;
603
+ }
604
+
605
+ if (peek().value === '[') {
606
+ consume('[');
607
+ const property = parseBinaryExpression(0);
608
+ consume(']');
609
+ node = {
610
+ computed: true,
611
+ object: node,
612
+ property,
613
+ type: 'MemberExpression',
614
+ };
615
+ continue;
616
+ }
617
+
618
+ if (peek().value === '(') {
619
+ consume('(');
620
+ const args = [];
621
+ while (peek() && peek().value !== ')') {
622
+ args.push(parseBinaryExpression(0));
623
+ if (peek()?.value === ',') {
624
+ consume(',');
625
+ }
626
+ }
627
+ consume(')');
628
+ node = {
629
+ arguments: args,
630
+ callee: node,
631
+ type: 'CallExpression',
632
+ };
633
+ continue;
634
+ }
635
+
636
+ break;
637
+ }
638
+ return node;
639
+ };
640
+
641
+ const parseUnary = () => {
642
+ const token = peek();
643
+ if (token?.type === 'operator' && ['!', '-'].includes(token.value)) {
644
+ consume();
645
+ return {
646
+ argument: parseUnary(),
647
+ operator: token.value,
648
+ type: 'UnaryExpression',
649
+ };
650
+ }
651
+
652
+ return parsePostfix(parsePrimary());
653
+ };
654
+
655
+ const parseBinaryExpression = (minimumPrecedence) => {
656
+ let left = parseUnary();
657
+ while (true) {
658
+ const operator = peek();
659
+ const precedence = operator ? BINARY_PRECEDENCE[operator.value] : null;
660
+ if (!precedence || precedence < minimumPrecedence) {
661
+ break;
662
+ }
663
+
664
+ consume();
665
+ const right = parseBinaryExpression(precedence + 1);
666
+ left = {
667
+ left,
668
+ operator: operator.value,
669
+ right,
670
+ type: 'BinaryExpression',
671
+ };
672
+ }
673
+ return left;
674
+ };
675
+
676
+ const ast = parseBinaryExpression(0);
677
+ if (index < tokens.length) {
678
+ throw new Error(`Unexpected token "${tokens[index].value}" in expression: ${source}`);
679
+ }
680
+ return ast;
681
+ }
682
+
683
+ class ExpressionScope {
684
+ constructor({ locals = {}, parent = null, rootContext }) {
685
+ this.locals = locals;
686
+ this.parent = parent;
687
+ this.rootContext = rootContext;
688
+ }
689
+
690
+ child(locals = {}) {
691
+ return new ExpressionScope({
692
+ locals,
693
+ parent: this,
694
+ rootContext: this.rootContext,
695
+ });
696
+ }
697
+
698
+ has(name) {
699
+ if (Object.hasOwn(this.locals, name)) {
700
+ return true;
701
+ }
702
+ return this.parent?.has(name) ?? false;
703
+ }
704
+
705
+ get(name) {
706
+ if (Object.hasOwn(this.locals, name)) {
707
+ return this.locals[name];
708
+ }
709
+ if (this.parent) {
710
+ return this.parent.get(name);
711
+ }
712
+ return this.rootContext.resolveIdentifier(name);
713
+ }
714
+ }
715
+
716
+ function normalizeDuration(duration) {
717
+ const match = String(duration ?? '').trim().match(/^(-?\d+)\s*([smhdw])$/iu);
718
+ if (!match) {
719
+ return null;
720
+ }
721
+
722
+ const amount = Number(match[1]);
723
+ const unit = match[2].toLowerCase();
724
+ const multiplier = {
725
+ d: 86_400_000,
726
+ h: 3_600_000,
727
+ m: 60_000,
728
+ s: 1_000,
729
+ w: 604_800_000,
730
+ }[unit];
731
+ return Number.isFinite(amount) && multiplier ? amount * multiplier : null;
732
+ }
733
+
734
+ function parseDateValue(value) {
735
+ if (value instanceof Date) {
736
+ return Number.isFinite(value.getTime()) ? value : null;
737
+ }
738
+ if (typeof value === 'number') {
739
+ const date = new Date(value);
740
+ return Number.isFinite(date.getTime()) ? date : null;
741
+ }
742
+ if (typeof value !== 'string') {
743
+ return null;
744
+ }
745
+
746
+ const normalized = value.trim();
747
+ if (!normalized) {
748
+ return null;
749
+ }
750
+
751
+ if (/^\d{8}$/u.test(normalized)) {
752
+ return new Date(`${normalized.slice(0, 4)}-${normalized.slice(4, 6)}-${normalized.slice(6, 8)}T00:00:00`);
753
+ }
754
+
755
+ if (/^\d{8}\d{4}$/u.test(normalized)) {
756
+ return new Date(`${normalized.slice(0, 4)}-${normalized.slice(4, 6)}-${normalized.slice(6, 8)}T${normalized.slice(8, 10)}:${normalized.slice(10, 12)}:00`);
757
+ }
758
+
759
+ const date = new Date(normalized);
760
+ return Number.isFinite(date.getTime()) ? date : null;
761
+ }
762
+
763
+ function isDateLikeString(value) {
764
+ if (typeof value !== 'string') {
765
+ return false;
766
+ }
767
+
768
+ const normalized = value.trim();
769
+ if (!normalized) {
770
+ return false;
771
+ }
772
+
773
+ return (
774
+ /^\d{8}(?:\d{4})?$/u.test(normalized)
775
+ || /^\d{4}-\d{2}-\d{2}(?:[T\s]\d{2}:\d{2}(?::\d{2}(?:\.\d{1,3})?)?(?:Z|[+-]\d{2}:\d{2})?)?$/u.test(normalized)
776
+ );
777
+ }
778
+
779
+ function coerceDateComparable(value) {
780
+ if (!isDateLikeString(value)) {
781
+ return value;
782
+ }
783
+
784
+ return parseDateValue(value) ?? value;
785
+ }
786
+
787
+ function normalizeComparablePair(left, right) {
788
+ if (left instanceof Date || right instanceof Date) {
789
+ return [
790
+ left instanceof Date ? left : coerceDateComparable(left),
791
+ right instanceof Date ? right : coerceDateComparable(right),
792
+ ];
793
+ }
794
+
795
+ if (typeof left === 'string' && typeof right === 'string' && isDateLikeString(left) && isDateLikeString(right)) {
796
+ return [
797
+ parseDateValue(left) ?? left,
798
+ parseDateValue(right) ?? right,
799
+ ];
800
+ }
801
+
802
+ return [left, right];
803
+ }
804
+
805
+ function formatDateValue(value, format = 'YYYY-MM-DD') {
806
+ const date = parseDateValue(value);
807
+ if (!date) {
808
+ return '';
809
+ }
810
+
811
+ const padded = (number) => String(number).padStart(2, '0');
812
+ return String(format ?? 'YYYY-MM-DD')
813
+ .replace(/YYYY/g, String(date.getFullYear()))
814
+ .replace(/MM/g, padded(date.getMonth() + 1))
815
+ .replace(/DD/g, padded(date.getDate()))
816
+ .replace(/HH/g, padded(date.getHours()))
817
+ .replace(/mm/g, padded(date.getMinutes()))
818
+ .replace(/ss/g, padded(date.getSeconds()));
819
+ }
820
+
821
+ function toComparableValue(value) {
822
+ if (value instanceof Date) {
823
+ return value.getTime();
824
+ }
825
+ return value;
826
+ }
827
+
828
+ function toDisplayText(value) {
829
+ if (value == null) {
830
+ return '';
831
+ }
832
+ if (value instanceof Date) {
833
+ return formatDateValue(value, 'YYYY-MM-DD HH:mm:ss');
834
+ }
835
+ if (Array.isArray(value)) {
836
+ return value.map((entry) => toDisplayText(entry)).join(', ');
837
+ }
838
+ if (typeof value === 'boolean') {
839
+ return value ? 'true' : 'false';
840
+ }
841
+ if (typeof value === 'number') {
842
+ return Number.isFinite(value) ? String(value) : '';
843
+ }
844
+ if (value?.__baseType === 'file') {
845
+ return value.path || value.name || '';
846
+ }
847
+ if (value?.__baseType === 'link') {
848
+ return value.display || value.path || value.url || '';
849
+ }
850
+ if (isPlainObject(value)) {
851
+ try {
852
+ return JSON.stringify(value);
853
+ } catch {
854
+ return '[object Object]';
855
+ }
856
+ }
857
+ return String(value);
858
+ }
859
+
860
+ function valuesEqual(left, right) {
861
+ const [normalizedLeft, normalizedRight] = normalizeComparablePair(left, right);
862
+
863
+ left = normalizedLeft;
864
+ right = normalizedRight;
865
+
866
+ if (left?.__baseType === 'file' && right?.__baseType === 'file') {
867
+ return left.path === right.path;
868
+ }
869
+ if (left?.__baseType === 'link' && right?.__baseType === 'link') {
870
+ return left.url === right.url && left.path === right.path;
871
+ }
872
+ if (left instanceof Date || right instanceof Date) {
873
+ return toComparableValue(left) === toComparableValue(right);
874
+ }
875
+ return left === right;
876
+ }
877
+
878
+ function resolveImageAttachmentPath(value, {
879
+ rowFilePath = '',
880
+ snapshot = null,
881
+ sourcePath = '',
882
+ } = {}) {
883
+ const text = String(value ?? '').trim();
884
+ const rowsByPath = snapshot?.rowsByPath;
885
+ if (!text || !rowsByPath) {
886
+ return null;
887
+ }
888
+
889
+ const candidates = [];
890
+ const seen = new Set();
891
+ const appendCandidate = (candidate) => {
892
+ const normalized = String(candidate ?? '').trim().replace(/\\/g, '/');
893
+ if (!normalized || seen.has(normalized)) {
894
+ return;
895
+ }
896
+ seen.add(normalized);
897
+ candidates.push(normalized);
898
+ };
899
+
900
+ if (rowFilePath) {
901
+ appendCandidate(resolveVaultRelativePath(rowFilePath, text));
902
+ }
903
+ if (sourcePath) {
904
+ appendCandidate(resolveVaultRelativePath(sourcePath, text));
905
+ }
906
+ appendCandidate(text);
907
+
908
+ return candidates.find((candidate) => (
909
+ isImageAttachmentFilePath(candidate)
910
+ && rowsByPath.has(candidate)
911
+ )) ?? null;
912
+ }
913
+
914
+ function serializeBaseValue(value, options = {}) {
915
+ if (value == null || value === '') {
916
+ return { text: '', type: 'empty', value: null };
917
+ }
918
+ if (value instanceof Date) {
919
+ return {
920
+ iso: value.toISOString(),
921
+ text: formatDateValue(value, 'YYYY-MM-DD HH:mm:ss'),
922
+ type: 'date',
923
+ value: value.toISOString(),
924
+ };
925
+ }
926
+ if (Array.isArray(value)) {
927
+ return {
928
+ items: value.map((entry) => serializeBaseValue(entry, options)),
929
+ text: toDisplayText(value),
930
+ type: 'list',
931
+ value: value.map((entry) => toDisplayText(entry)),
932
+ };
933
+ }
934
+ if (value?.__baseType === 'file') {
935
+ return {
936
+ path: value.path,
937
+ text: value.path,
938
+ type: 'file',
939
+ value: value.path,
940
+ };
941
+ }
942
+ if (value?.__baseType === 'link') {
943
+ return {
944
+ external: value.external,
945
+ path: value.path,
946
+ text: value.display || value.path || value.url,
947
+ type: 'link',
948
+ url: value.url,
949
+ value: value.display || value.path || value.url,
950
+ };
951
+ }
952
+ if (typeof value === 'boolean') {
953
+ return { text: value ? 'true' : 'false', type: 'boolean', value };
954
+ }
955
+ if (typeof value === 'number') {
956
+ return { text: Number.isFinite(value) ? String(value) : '', type: 'number', value };
957
+ }
958
+ if (typeof value === 'string') {
959
+ const imagePath = resolveImageAttachmentPath(value, options);
960
+ if (imagePath) {
961
+ return {
962
+ path: imagePath,
963
+ text: value,
964
+ type: 'image',
965
+ value: imagePath,
966
+ };
967
+ }
968
+ return { text: value, type: 'string', value };
969
+ }
970
+ return {
971
+ text: toDisplayText(value),
972
+ type: 'object',
973
+ value,
974
+ };
975
+ }
976
+
977
+ function compareValues(left, right) {
978
+ const [normalizedLeft, normalizedRight] = normalizeComparablePair(left, right);
979
+ left = normalizedLeft;
980
+ right = normalizedRight;
981
+
982
+ const comparableLeft = toComparableValue(left);
983
+ const comparableRight = toComparableValue(right);
984
+ if (comparableLeft == null && comparableRight == null) return 0;
985
+ if (comparableLeft == null) return 1;
986
+ if (comparableRight == null) return -1;
987
+ if (typeof comparableLeft === 'number' && typeof comparableRight === 'number') {
988
+ return comparableLeft - comparableRight;
989
+ }
990
+ return String(toDisplayText(comparableLeft)).localeCompare(String(toDisplayText(comparableRight)), undefined, { sensitivity: 'base' });
991
+ }
992
+
993
+ function applyBinaryOperator(operator, left, right) {
994
+ if (operator === '&&') {
995
+ return Boolean(left) && Boolean(right);
996
+ }
997
+ if (operator === '||') {
998
+ return Boolean(left) || Boolean(right);
999
+ }
1000
+ if (operator === '==') {
1001
+ return valuesEqual(left, right);
1002
+ }
1003
+ if (operator === '!=') {
1004
+ return !valuesEqual(left, right);
1005
+ }
1006
+ if (operator === '<') {
1007
+ return compareValues(left, right) < 0;
1008
+ }
1009
+ if (operator === '<=') {
1010
+ return compareValues(left, right) <= 0;
1011
+ }
1012
+ if (operator === '>') {
1013
+ return compareValues(left, right) > 0;
1014
+ }
1015
+ if (operator === '>=') {
1016
+ return compareValues(left, right) >= 0;
1017
+ }
1018
+ if (operator === '+') {
1019
+ if (left instanceof Date && typeof right === 'string') {
1020
+ const duration = normalizeDuration(right);
1021
+ return duration == null ? left : new Date(left.getTime() + duration);
1022
+ }
1023
+ if (typeof left === 'string' || typeof right === 'string') {
1024
+ return `${toDisplayText(left)}${toDisplayText(right)}`;
1025
+ }
1026
+ return Number(left ?? 0) + Number(right ?? 0);
1027
+ }
1028
+ if (operator === '-') {
1029
+ if (left instanceof Date && typeof right === 'string') {
1030
+ const duration = normalizeDuration(right);
1031
+ return duration == null ? left : new Date(left.getTime() - duration);
1032
+ }
1033
+ if (left instanceof Date && right instanceof Date) {
1034
+ return left.getTime() - right.getTime();
1035
+ }
1036
+ return Number(left ?? 0) - Number(right ?? 0);
1037
+ }
1038
+ if (operator === '*') {
1039
+ return Number(left ?? 0) * Number(right ?? 0);
1040
+ }
1041
+ if (operator === '/') {
1042
+ return Number(right ?? 0) === 0 ? null : Number(left ?? 0) / Number(right ?? 0);
1043
+ }
1044
+ if (operator === '%') {
1045
+ return Number(right ?? 0) === 0 ? null : Number(left ?? 0) % Number(right ?? 0);
1046
+ }
1047
+
1048
+ throw new Error(`Unsupported operator: ${operator}`);
1049
+ }
1050
+
1051
+ function invokeGlobalFunction(name, argNodes, scope, evaluate) {
1052
+ if (name === 'if') {
1053
+ const condition = evaluate(argNodes[0], scope);
1054
+ return condition ? evaluate(argNodes[1], scope) : evaluate(argNodes[2], scope);
1055
+ }
1056
+
1057
+ const args = argNodes.map((node) => evaluate(node, scope));
1058
+ switch (name) {
1059
+ case 'date':
1060
+ return parseDateValue(args[0]);
1061
+ case 'link': {
1062
+ const target = String(args[0] ?? '').trim();
1063
+ if (!target) {
1064
+ return null;
1065
+ }
1066
+ const external = /^[a-z]+:/iu.test(target);
1067
+ return createLinkValue(target, {
1068
+ display: typeof args[1] === 'string' ? args[1] : '',
1069
+ exists: external,
1070
+ external,
1071
+ });
1072
+ }
1073
+ case 'list':
1074
+ return args;
1075
+ case 'max':
1076
+ return args.flat().reduce((acc, value) => (acc == null || compareValues(value, acc) > 0 ? value : acc), null);
1077
+ case 'min':
1078
+ return args.flat().reduce((acc, value) => (acc == null || compareValues(value, acc) < 0 ? value : acc), null);
1079
+ case 'now':
1080
+ return new Date();
1081
+ case 'today': {
1082
+ const date = new Date();
1083
+ date.setHours(0, 0, 0, 0);
1084
+ return date;
1085
+ }
1086
+ default:
1087
+ throw new Error(`Unknown function: ${name}`);
1088
+ }
1089
+ }
1090
+
1091
+ function invokeMethod(target, name, argNodes, scope, evaluate, rootContext) {
1092
+ if (target?.__baseType === 'formula-namespace') {
1093
+ if (argNodes.length > 0) {
1094
+ throw new Error(`Formula namespace property "${name}" is not callable`);
1095
+ }
1096
+ return rootContext.resolveFormulaValue(name, target.row, target.evaluationState);
1097
+ }
1098
+
1099
+ if (Array.isArray(target)) {
1100
+ if (name === 'contains') {
1101
+ const needle = evaluate(argNodes[0], scope);
1102
+ return target.some((entry) => valuesEqual(entry, needle));
1103
+ }
1104
+ if (name === 'containsAll') {
1105
+ return argNodes.every((node) => target.some((entry) => valuesEqual(entry, evaluate(node, scope))));
1106
+ }
1107
+ if (name === 'containsAny') {
1108
+ return argNodes.some((node) => target.some((entry) => valuesEqual(entry, evaluate(node, scope))));
1109
+ }
1110
+ if (name === 'filter') {
1111
+ const predicate = argNodes[0];
1112
+ return target.filter((value, index) => Boolean(evaluate(predicate, scope.child({ index, value }))));
1113
+ }
1114
+ if (name === 'flat') {
1115
+ return target.flat();
1116
+ }
1117
+ if (name === 'isEmpty') {
1118
+ return target.length === 0;
1119
+ }
1120
+ if (name === 'join') {
1121
+ return target.map((entry) => toDisplayText(entry)).join(String(evaluate(argNodes[0], scope) ?? ''));
1122
+ }
1123
+ if (name === 'map') {
1124
+ const mapper = argNodes[0];
1125
+ return target.map((value, index) => evaluate(mapper, scope.child({ index, value })));
1126
+ }
1127
+ if (name === 'reduce') {
1128
+ const reducer = argNodes[0];
1129
+ let accumulator = argNodes.length > 1 ? evaluate(argNodes[1], scope) : null;
1130
+ target.forEach((value, index) => {
1131
+ accumulator = evaluate(reducer, scope.child({ acc: accumulator, index, value }));
1132
+ });
1133
+ return accumulator;
1134
+ }
1135
+ if (name === 'reverse') {
1136
+ return [...target].reverse();
1137
+ }
1138
+ if (name === 'slice') {
1139
+ return target.slice(Number(evaluate(argNodes[0], scope) ?? 0), argNodes[1] ? Number(evaluate(argNodes[1], scope)) : undefined);
1140
+ }
1141
+ if (name === 'sort') {
1142
+ return [...target].sort(compareValues);
1143
+ }
1144
+ if (name === 'unique') {
1145
+ const uniqueValues = [];
1146
+ target.forEach((value) => {
1147
+ if (!uniqueValues.some((entry) => valuesEqual(entry, value))) {
1148
+ uniqueValues.push(value);
1149
+ }
1150
+ });
1151
+ return uniqueValues;
1152
+ }
1153
+ }
1154
+
1155
+ if (typeof target === 'string') {
1156
+ switch (name) {
1157
+ case 'contains':
1158
+ return target.toLowerCase().includes(String(evaluate(argNodes[0], scope) ?? '').toLowerCase());
1159
+ case 'endsWith':
1160
+ return target.endsWith(String(evaluate(argNodes[0], scope) ?? ''));
1161
+ case 'isEmpty':
1162
+ return target.length === 0;
1163
+ case 'lower':
1164
+ return target.toLowerCase();
1165
+ case 'replace':
1166
+ return target.replaceAll(String(evaluate(argNodes[0], scope) ?? ''), String(evaluate(argNodes[1], scope) ?? ''));
1167
+ case 'split':
1168
+ return target.split(String(evaluate(argNodes[0], scope) ?? ''));
1169
+ case 'startsWith':
1170
+ return target.startsWith(String(evaluate(argNodes[0], scope) ?? ''));
1171
+ case 'title':
1172
+ return target.replace(/\b\p{L}/gu, (match) => match.toUpperCase());
1173
+ case 'trim':
1174
+ return target.trim();
1175
+ case 'upper':
1176
+ return target.toUpperCase();
1177
+ default:
1178
+ break;
1179
+ }
1180
+ }
1181
+
1182
+ if (typeof target === 'number') {
1183
+ switch (name) {
1184
+ case 'ceil':
1185
+ return Math.ceil(target);
1186
+ case 'floor':
1187
+ return Math.floor(target);
1188
+ case 'isEmpty':
1189
+ return false;
1190
+ case 'round':
1191
+ return Number.isFinite(evaluate(argNodes[0], scope))
1192
+ ? Number(target.toFixed(Number(evaluate(argNodes[0], scope))))
1193
+ : Math.round(target);
1194
+ case 'toFixed':
1195
+ return target.toFixed(Number(evaluate(argNodes[0], scope) ?? 0));
1196
+ default:
1197
+ break;
1198
+ }
1199
+ }
1200
+
1201
+ const asDate = parseDateValue(target);
1202
+ if (asDate) {
1203
+ switch (name) {
1204
+ case 'format':
1205
+ return formatDateValue(asDate, String(evaluate(argNodes[0], scope) ?? 'YYYY-MM-DD'));
1206
+ case 'isEmpty':
1207
+ return false;
1208
+ default:
1209
+ break;
1210
+ }
1211
+ }
1212
+
1213
+ if (target?.__baseType === 'file') {
1214
+ switch (name) {
1215
+ case 'asLink':
1216
+ return createLinkValue(target.path, {
1217
+ display: typeof evaluate(argNodes[0], scope) === 'string' ? evaluate(argNodes[0], scope) : '',
1218
+ exists: true,
1219
+ });
1220
+ case 'hasLink': {
1221
+ const needle = evaluate(argNodes[0], scope);
1222
+ const needlePath = needle?.__baseType === 'file'
1223
+ ? needle.path
1224
+ : (needle?.__baseType === 'link' ? needle.path : String(needle ?? ''));
1225
+ return target.links.some((link) => link.path === needlePath || link.rawTarget === needlePath);
1226
+ }
1227
+ case 'hasProperty':
1228
+ return Object.hasOwn(target.properties, String(evaluate(argNodes[0], scope) ?? ''));
1229
+ case 'hasTag':
1230
+ return argNodes.some((node) => {
1231
+ const value = String(evaluate(node, scope) ?? '').replace(/^#/u, '');
1232
+ return target.tags.some((tag) => tag === value || tag.startsWith(`${value}/`));
1233
+ });
1234
+ case 'inFolder': {
1235
+ const folder = String(evaluate(argNodes[0], scope) ?? '').replace(/\/+$/u, '');
1236
+ return !folder || target.folder === folder || target.folder.startsWith(`${folder}/`);
1237
+ }
1238
+ default:
1239
+ break;
1240
+ }
1241
+ }
1242
+
1243
+ if (target?.__baseType === 'link') {
1244
+ switch (name) {
1245
+ case 'asFile':
1246
+ return target.path ? rootContext.snapshot.rowsByPath.get(target.path)?.file ?? null : null;
1247
+ case 'linksTo': {
1248
+ const other = evaluate(argNodes[0], scope);
1249
+ const otherPath = other?.__baseType === 'file'
1250
+ ? other.path
1251
+ : (other?.__baseType === 'link' ? other.path : String(other ?? ''));
1252
+ return target.path === otherPath;
1253
+ }
1254
+ default:
1255
+ break;
1256
+ }
1257
+ }
1258
+
1259
+ if (isPlainObject(target)) {
1260
+ switch (name) {
1261
+ case 'isEmpty':
1262
+ return Object.keys(target).length === 0;
1263
+ case 'keys':
1264
+ return Object.keys(target);
1265
+ case 'values':
1266
+ return Object.values(target);
1267
+ default:
1268
+ break;
1269
+ }
1270
+ }
1271
+
1272
+ throw new Error(`Unsupported method "${name}"`);
1273
+ }
1274
+
1275
+ function evaluateAst(ast, scope) {
1276
+ const rootContext = scope.rootContext;
1277
+ const evaluate = (node, nextScope = scope) => evaluateAst(node, nextScope);
1278
+
1279
+ switch (ast?.type) {
1280
+ case 'ArrayExpression':
1281
+ return ast.elements.map((element) => evaluate(element, scope));
1282
+ case 'BinaryExpression':
1283
+ return applyBinaryOperator(ast.operator, evaluate(ast.left, scope), evaluate(ast.right, scope));
1284
+ case 'CallExpression': {
1285
+ if (ast.callee?.type === 'Identifier') {
1286
+ return invokeGlobalFunction(ast.callee.name, ast.arguments, scope, evaluate);
1287
+ }
1288
+ if (ast.callee?.type === 'MemberExpression') {
1289
+ const target = evaluate(ast.callee.object, scope);
1290
+ const property = ast.callee.computed
1291
+ ? evaluate(ast.callee.property, scope)
1292
+ : ast.callee.property.name;
1293
+ return invokeMethod(target, String(property ?? ''), ast.arguments, scope, evaluate, rootContext);
1294
+ }
1295
+ throw new Error('Unsupported call target');
1296
+ }
1297
+ case 'Identifier':
1298
+ return scope.get(ast.name);
1299
+ case 'Literal':
1300
+ return ast.value;
1301
+ case 'MemberExpression': {
1302
+ const target = evaluate(ast.object, scope);
1303
+ const property = ast.computed ? evaluate(ast.property, scope) : ast.property.name;
1304
+ if (target?.__baseType === 'formula-namespace') {
1305
+ return rootContext.resolveFormulaValue(String(property ?? ''), target.row, target.evaluationState);
1306
+ }
1307
+ if (target == null) {
1308
+ return null;
1309
+ }
1310
+ return target[property];
1311
+ }
1312
+ case 'ObjectExpression':
1313
+ return ast.properties.reduce((acc, property) => {
1314
+ acc[property.key] = evaluate(property.value, scope);
1315
+ return acc;
1316
+ }, {});
1317
+ case 'UnaryExpression': {
1318
+ const value = evaluate(ast.argument, scope);
1319
+ return ast.operator === '!' ? !value : -Number(value ?? 0);
1320
+ }
1321
+ default:
1322
+ throw new Error(`Unsupported expression node "${ast?.type}"`);
1323
+ }
1324
+ }
1325
+
1326
+ function evaluateExpression(expressionSource, rootContext, locals = {}) {
1327
+ const cache = rootContext.astCache;
1328
+ let ast = cache.get(expressionSource);
1329
+ if (!ast) {
1330
+ ast = parseExpression(expressionSource);
1331
+ cache.set(expressionSource, ast);
1332
+ }
1333
+ const scope = new ExpressionScope({ locals, rootContext });
1334
+ return evaluateAst(ast, scope);
1335
+ }
1336
+
1337
+ function evaluateFilterNode(filterNode, rootContext) {
1338
+ if (!filterNode) {
1339
+ return true;
1340
+ }
1341
+ if (typeof filterNode === 'string') {
1342
+ return Boolean(evaluateExpression(filterNode, rootContext));
1343
+ }
1344
+ if (!isPlainObject(filterNode)) {
1345
+ return true;
1346
+ }
1347
+
1348
+ if (Array.isArray(filterNode.and)) {
1349
+ return filterNode.and.every((entry) => evaluateFilterNode(entry, rootContext));
1350
+ }
1351
+ if (Array.isArray(filterNode.or)) {
1352
+ return filterNode.or.some((entry) => evaluateFilterNode(entry, rootContext));
1353
+ }
1354
+ if (filterNode.not != null) {
1355
+ return !evaluateFilterNode(filterNode.not, rootContext);
1356
+ }
1357
+
1358
+ return true;
1359
+ }
1360
+
1361
+ function normalizeFormulaLookupName(name = '') {
1362
+ return String(name ?? '').replace(/^formula\./u, '');
1363
+ }
1364
+
1365
+ function createEvaluationRootContext({
1366
+ astCache = new Map(),
1367
+ currentRow,
1368
+ definition,
1369
+ evaluationState = null,
1370
+ identifierResolver = null,
1371
+ snapshot,
1372
+ thisFile,
1373
+ }) {
1374
+ const nextEvaluationState = evaluationState ?? {
1375
+ cache: new Map(),
1376
+ stack: new Set(),
1377
+ };
1378
+
1379
+ return {
1380
+ astCache,
1381
+ currentRow,
1382
+ definition,
1383
+ evaluationState: nextEvaluationState,
1384
+ resolveFormulaValue: (name, row, state = nextEvaluationState) => {
1385
+ const formulaName = normalizeFormulaLookupName(name);
1386
+ const formulaPropertyId = Object.keys(definition.properties).find((propertyId) => {
1387
+ const config = definition.properties[propertyId];
1388
+ return config?.formula && normalizeFormulaLookupName(propertyId) === formulaName;
1389
+ });
1390
+ if (!formulaPropertyId) {
1391
+ return null;
1392
+ }
1393
+
1394
+ const cacheKey = `${row.file.path}::${formulaPropertyId}`;
1395
+ if (state.cache.has(cacheKey)) {
1396
+ return state.cache.get(cacheKey);
1397
+ }
1398
+ if (state.stack.has(cacheKey)) {
1399
+ throw new Error(`Circular formula reference: ${formulaPropertyId}`);
1400
+ }
1401
+
1402
+ state.stack.add(cacheKey);
1403
+ const nextContext = createEvaluationRootContext({
1404
+ astCache,
1405
+ currentRow: row,
1406
+ definition,
1407
+ evaluationState: state,
1408
+ snapshot,
1409
+ thisFile,
1410
+ });
1411
+ const result = evaluateExpression(definition.properties[formulaPropertyId].formula, nextContext);
1412
+ state.stack.delete(cacheKey);
1413
+ state.cache.set(cacheKey, result);
1414
+ return result;
1415
+ },
1416
+ resolveIdentifier: (name) => {
1417
+ if (typeof identifierResolver === 'function') {
1418
+ const resolved = identifierResolver(name);
1419
+ if (resolved !== undefined) {
1420
+ return resolved;
1421
+ }
1422
+ }
1423
+ if (name === 'file') {
1424
+ return currentRow.file;
1425
+ }
1426
+ if (name === 'formula') {
1427
+ return createFormulaNamespace(currentRow, nextEvaluationState);
1428
+ }
1429
+ if (name === 'note') {
1430
+ return currentRow.noteProperties;
1431
+ }
1432
+ if (name === 'this') {
1433
+ return createContextFileValue(thisFile);
1434
+ }
1435
+ if (name === 'values') {
1436
+ return [];
1437
+ }
1438
+ if (Object.hasOwn(currentRow.noteProperties, name)) {
1439
+ return currentRow.noteProperties[name];
1440
+ }
1441
+ return null;
1442
+ },
1443
+ snapshot,
1444
+ thisFile,
1445
+ };
1446
+ }
1447
+
1448
+ function resolvePropertyLabel(propertyId, definition) {
1449
+ const config = definition.properties[propertyId];
1450
+ if (config?.displayName) {
1451
+ return config.displayName;
1452
+ }
1453
+ return propertyId.startsWith('file.')
1454
+ ? propertyId.slice(5)
1455
+ : propertyId.replace(/^note\./u, '');
1456
+ }
1457
+
1458
+ function getPropertyValue(propertyId, row, definition, snapshot, thisFile) {
1459
+ if (propertyId.startsWith('file.')) {
1460
+ return propertyId.split('.').slice(1).reduce((acc, segment) => acc?.[segment], row.file);
1461
+ }
1462
+
1463
+ if (propertyId.startsWith('note.')) {
1464
+ return row.noteProperties[propertyId.slice(5)] ?? null;
1465
+ }
1466
+
1467
+ const propertyConfig = definition.properties[propertyId];
1468
+ if (propertyConfig?.formula) {
1469
+ const context = createEvaluationRootContext({
1470
+ currentRow: row,
1471
+ definition,
1472
+ snapshot,
1473
+ thisFile,
1474
+ });
1475
+ return context.resolveFormulaValue(propertyId, row, context.evaluationState);
1476
+ }
1477
+
1478
+ const formulaConfig = definition.properties[`formula.${propertyId}`];
1479
+ if (formulaConfig?.formula) {
1480
+ const context = createEvaluationRootContext({
1481
+ currentRow: row,
1482
+ definition,
1483
+ snapshot,
1484
+ thisFile,
1485
+ });
1486
+ return context.resolveFormulaValue(propertyId, row, context.evaluationState);
1487
+ }
1488
+
1489
+ return row.noteProperties[propertyId] ?? null;
1490
+ }
1491
+
1492
+ function buildColumns(definition, view) {
1493
+ const order = view.order.length > 0
1494
+ ? view.order
1495
+ : ['file.name', ...Object.keys(definition.properties)];
1496
+ return order.map((propertyId) => ({
1497
+ id: propertyId,
1498
+ label: resolvePropertyLabel(propertyId, definition),
1499
+ }));
1500
+ }
1501
+
1502
+ function collectEvaluatedPropertyIds(columns, view) {
1503
+ const propertyIds = new Set(columns.map((column) => column.id));
1504
+
1505
+ if (view.groupBy) {
1506
+ propertyIds.add(view.groupBy);
1507
+ }
1508
+
1509
+ view.sort.forEach((sortConfig) => {
1510
+ if (sortConfig?.property) {
1511
+ propertyIds.add(sortConfig.property);
1512
+ }
1513
+ });
1514
+
1515
+ view.summaries.forEach((summary) => {
1516
+ if (summary?.property) {
1517
+ propertyIds.add(summary.property);
1518
+ }
1519
+ });
1520
+
1521
+ return [...propertyIds];
1522
+ }
1523
+
1524
+ function summarizeValues(values = [], summary, definition, snapshot, thisFile) {
1525
+ const meaningfulValues = values.filter((value) => value != null && value !== '');
1526
+ switch (summary.type) {
1527
+ case 'average': {
1528
+ const numbers = meaningfulValues.map(Number).filter(Number.isFinite);
1529
+ return numbers.length > 0 ? numbers.reduce((sum, value) => sum + value, 0) / numbers.length : null;
1530
+ }
1531
+ case 'checked':
1532
+ return values.filter(Boolean).length;
1533
+ case 'custom': {
1534
+ const context = createEvaluationRootContext({
1535
+ astCache: new Map(),
1536
+ currentRow: {
1537
+ file: thisFile,
1538
+ noteProperties: thisFile?.properties ?? {},
1539
+ },
1540
+ definition,
1541
+ identifierResolver: (name) => (name === 'values' ? values : undefined),
1542
+ snapshot,
1543
+ thisFile,
1544
+ });
1545
+ return evaluateExpression(summary.formula, context);
1546
+ }
1547
+ case 'earliest':
1548
+ return meaningfulValues.reduce((acc, value) => (acc == null || compareValues(value, acc) < 0 ? value : acc), null);
1549
+ case 'empty':
1550
+ return values.filter((value) => value == null || value === '').length;
1551
+ case 'filled':
1552
+ return meaningfulValues.length;
1553
+ case 'latest':
1554
+ return meaningfulValues.reduce((acc, value) => (acc == null || compareValues(value, acc) > 0 ? value : acc), null);
1555
+ case 'max':
1556
+ return meaningfulValues.reduce((acc, value) => (acc == null || compareValues(value, acc) > 0 ? value : acc), null);
1557
+ case 'median': {
1558
+ const numbers = meaningfulValues.map(Number).filter(Number.isFinite).sort((left, right) => left - right);
1559
+ if (numbers.length === 0) return null;
1560
+ const middle = Math.floor(numbers.length / 2);
1561
+ return numbers.length % 2 === 0 ? (numbers[middle - 1] + numbers[middle]) / 2 : numbers[middle];
1562
+ }
1563
+ case 'min':
1564
+ return meaningfulValues.reduce((acc, value) => (acc == null || compareValues(value, acc) < 0 ? value : acc), null);
1565
+ case 'range': {
1566
+ const sorted = meaningfulValues.slice().sort(compareValues);
1567
+ if (sorted.length === 0) return null;
1568
+ const first = sorted[0];
1569
+ const last = sorted[sorted.length - 1];
1570
+ if (first instanceof Date && last instanceof Date) {
1571
+ return last.getTime() - first.getTime();
1572
+ }
1573
+ return Number(last ?? 0) - Number(first ?? 0);
1574
+ }
1575
+ case 'stddev': {
1576
+ const numbers = meaningfulValues.map(Number).filter(Number.isFinite);
1577
+ if (numbers.length === 0) return null;
1578
+ const average = numbers.reduce((sum, value) => sum + value, 0) / numbers.length;
1579
+ const variance = numbers.reduce((sum, value) => sum + ((value - average) ** 2), 0) / numbers.length;
1580
+ return Math.sqrt(variance);
1581
+ }
1582
+ case 'sum':
1583
+ return meaningfulValues.map(Number).filter(Number.isFinite).reduce((sum, value) => sum + value, 0);
1584
+ case 'unchecked':
1585
+ return values.filter((value) => value === false || value == null).length;
1586
+ case 'unique': {
1587
+ const uniqueValues = [];
1588
+ meaningfulValues.forEach((value) => {
1589
+ if (!uniqueValues.some((entry) => valuesEqual(entry, value))) {
1590
+ uniqueValues.push(value);
1591
+ }
1592
+ });
1593
+ return uniqueValues.length;
1594
+ }
1595
+ default:
1596
+ return null;
1597
+ }
1598
+ }
1599
+
1600
+ function createSummaryPayload(columns, rows, summaries, definition, snapshot, thisFile) {
1601
+ return summaries.map((summary) => {
1602
+ const column = columns.find((entry) => entry.id === summary.property);
1603
+ const values = rows.map((row) => row.rawCells[summary.property]);
1604
+ const value = summarizeValues(values, summary, definition, snapshot, thisFile);
1605
+ return {
1606
+ id: summary.id,
1607
+ label: summary.label,
1608
+ property: summary.property,
1609
+ propertyLabel: column?.label ?? summary.property,
1610
+ value: serializeBaseValue(value, {
1611
+ snapshot,
1612
+ sourcePath: thisFile?.path ?? '',
1613
+ }),
1614
+ };
1615
+ });
1616
+ }
1617
+
1618
+ function rowMatchesSearch(row, columns, query) {
1619
+ const normalizedQuery = String(query ?? '').trim().toLowerCase();
1620
+ if (!normalizedQuery) {
1621
+ return true;
1622
+ }
1623
+
1624
+ const haystack = [
1625
+ row.file.path,
1626
+ ...columns.map((column) => toDisplayText(row.rawCells[column.id])),
1627
+ ].join('\n').toLowerCase();
1628
+ return haystack.includes(normalizedQuery);
1629
+ }
1630
+
1631
+ function createCsv(rows, columns) {
1632
+ const escapeCell = (value) => {
1633
+ const text = String(value ?? '');
1634
+ if (/[,"\n]/u.test(text)) {
1635
+ return `"${text.replace(/"/g, '""')}"`;
1636
+ }
1637
+ return text;
1638
+ };
1639
+
1640
+ const lines = [
1641
+ columns.map((column) => escapeCell(column.label)).join(','),
1642
+ ...rows.map((row) => columns.map((column) => escapeCell(toDisplayText(row.rawCells[column.id]))).join(',')),
1643
+ ];
1644
+ return `${lines.join('\n')}\n`;
1645
+ }
1646
+
1647
+ export function serializeBaseDefinition(definition) {
1648
+ const raw = definition?.raw ?? definition ?? {};
1649
+ return `${yaml.dump(raw, { lineWidth: -1, noRefs: true }).trim()}\n`;
1650
+ }
1651
+
1652
+ export class BaseQueryService {
1653
+ constructor({
1654
+ vaultFileStore,
1655
+ workspaceStateProvider = null,
1656
+ workspaceStateSynchronizer = null,
1657
+ }) {
1658
+ this.vaultFileStore = vaultFileStore;
1659
+ this.workspaceStateProvider = workspaceStateProvider;
1660
+ this.workspaceStateSynchronizer = workspaceStateSynchronizer;
1661
+ this.indexSnapshot = null;
1662
+ this.lastWorkspaceState = null;
1663
+ }
1664
+
1665
+ async getWorkspaceState() {
1666
+ const workspaceState = await this.workspaceStateProvider?.();
1667
+ if (workspaceState) {
1668
+ this.lastWorkspaceState = workspaceState;
1669
+ return workspaceState;
1670
+ }
1671
+
1672
+ if (this.lastWorkspaceState) {
1673
+ return this.lastWorkspaceState;
1674
+ }
1675
+
1676
+ const scannedWorkspaceState = await this.vaultFileStore.scanWorkspaceState();
1677
+ this.lastWorkspaceState = scannedWorkspaceState;
1678
+ return scannedWorkspaceState;
1679
+ }
1680
+
1681
+ createSnapshotRow(filePath, workspaceState, wikiTargetIndex, markdownContent = null) {
1682
+ const metadata = workspaceState.metadata.get(filePath) ?? null;
1683
+ const frontmatter = markdownContent ? extractYamlFrontmatter(markdownContent) : null;
1684
+ const noteProperties = isPlainObject(frontmatter?.data) ? frontmatter.data : {};
1685
+ const bodyMarkdown = frontmatter?.bodyMarkdown ?? markdownContent ?? '';
1686
+ const references = extractReferences(bodyMarkdown, wikiTargetIndex);
1687
+ const tags = [...new Set([
1688
+ ...normalizeTags(noteProperties.tags),
1689
+ ...extractInlineTags(bodyMarkdown),
1690
+ ])];
1691
+ const fileValue = {
1692
+ __baseType: 'file',
1693
+ backlinks: [],
1694
+ basename: stripVaultFileExtension(basename(filePath)),
1695
+ ctime: Number.isFinite(metadata?.ctimeMs) ? new Date(metadata.ctimeMs) : null,
1696
+ embeds: references.embeds,
1697
+ ext: extname(filePath).replace(/^\./u, ''),
1698
+ folder: dirname(filePath) === '.' ? '' : dirname(filePath).replace(/\\/g, '/'),
1699
+ links: references.links,
1700
+ mtime: Number.isFinite(metadata?.mtimeMs) ? new Date(metadata.mtimeMs) : null,
1701
+ name: basename(filePath),
1702
+ path: filePath,
1703
+ properties: noteProperties,
1704
+ size: Number(metadata?.size ?? 0) || 0,
1705
+ tags,
1706
+ };
1707
+
1708
+ return {
1709
+ forwardLinks: new Set(
1710
+ references.links
1711
+ .map((link) => link?.path)
1712
+ .filter((targetPath) => targetPath && targetPath !== filePath),
1713
+ ),
1714
+ row: {
1715
+ file: fileValue,
1716
+ noteProperties,
1717
+ path: filePath,
1718
+ },
1719
+ };
1720
+ }
1721
+
1722
+ rebuildBacklinks(snapshot) {
1723
+ const backlinksByTarget = new Map(snapshot.filePaths.map((filePath) => [filePath, []]));
1724
+
1725
+ snapshot.rowsByPath.forEach((row, filePath) => {
1726
+ const forwardLinks = snapshot.forwardLinksByPath.get(filePath) ?? new Set();
1727
+ forwardLinks.forEach((targetPath) => {
1728
+ if (!backlinksByTarget.has(targetPath) || targetPath === row.file.path) {
1729
+ return;
1730
+ }
1731
+
1732
+ backlinksByTarget.get(targetPath).push(createLinkValue(row.file.path, {
1733
+ display: basename(row.file.path),
1734
+ exists: true,
1735
+ }));
1736
+ });
1737
+ });
1738
+
1739
+ snapshot.backlinksByPath = backlinksByTarget;
1740
+ snapshot.rowsByPath.forEach((row, filePath) => {
1741
+ row.file.backlinks = dedupeLinkValues(backlinksByTarget.get(filePath) ?? []);
1742
+ });
1743
+ }
1744
+
1745
+ async buildIndexSnapshot(workspaceState = null) {
1746
+ const resolvedWorkspaceState = workspaceState ?? await this.getWorkspaceState();
1747
+ const fileEntries = listWorkspaceFilePaths(resolvedWorkspaceState);
1748
+ const wikiTargetIndex = createWikiTargetIndex(fileEntries);
1749
+ const markdownContents = new Map();
1750
+
1751
+ await mapWithConcurrency(resolvedWorkspaceState.markdownPaths ?? [], INDEX_READ_CONCURRENCY, async (filePath) => {
1752
+ markdownContents.set(filePath, await this.vaultFileStore.readMarkdownFile(filePath));
1753
+ });
1754
+
1755
+ const rowsByPath = new Map();
1756
+ const forwardLinksByPath = new Map();
1757
+ fileEntries.forEach((filePath) => {
1758
+ const markdownContent = markdownContents.get(filePath) ?? null;
1759
+ const rowRecord = this.createSnapshotRow(filePath, resolvedWorkspaceState, wikiTargetIndex, markdownContent);
1760
+ rowsByPath.set(filePath, rowRecord.row);
1761
+ forwardLinksByPath.set(filePath, rowRecord.forwardLinks);
1762
+ });
1763
+
1764
+ const snapshot = {
1765
+ backlinksByPath: new Map(),
1766
+ filePaths: fileEntries,
1767
+ forwardLinksByPath,
1768
+ rowsByPath,
1769
+ scannedAt: resolvedWorkspaceState.scannedAt,
1770
+ wikiTargetIndex,
1771
+ workspaceState: resolvedWorkspaceState,
1772
+ };
1773
+ this.rebuildBacklinks(snapshot);
1774
+ this.indexSnapshot = snapshot;
1775
+ this.lastWorkspaceState = resolvedWorkspaceState;
1776
+ return snapshot;
1777
+ }
1778
+
1779
+ async synchronizeWorkspaceState() {
1780
+ await this.workspaceStateSynchronizer?.();
1781
+ }
1782
+
1783
+ removeSnapshotPath(snapshot, filePath) {
1784
+ snapshot.rowsByPath.delete(filePath);
1785
+ snapshot.forwardLinksByPath.delete(filePath);
1786
+ snapshot.backlinksByPath.delete(filePath);
1787
+ snapshot.filePaths = snapshot.filePaths.filter((candidatePath) => candidatePath !== filePath);
1788
+ }
1789
+
1790
+ upsertSnapshotPath(snapshot, filePath) {
1791
+ if (snapshot.filePaths.includes(filePath)) {
1792
+ return;
1793
+ }
1794
+
1795
+ snapshot.filePaths.push(filePath);
1796
+ snapshot.filePaths.sort(compareVaultPaths);
1797
+ }
1798
+
1799
+ collectImpactedSourcesForMembershipChanges(snapshot, pathValues = []) {
1800
+ const affectedTargetKeys = new Set();
1801
+ pathValues.forEach((pathValue) => {
1802
+ collectWikiTargetKeysForFilePath(pathValue).forEach((targetKey) => {
1803
+ affectedTargetKeys.add(targetKey);
1804
+ });
1805
+ });
1806
+
1807
+ if (affectedTargetKeys.size === 0) {
1808
+ return new Set();
1809
+ }
1810
+
1811
+ const impactedPaths = new Set();
1812
+ snapshot.rowsByPath.forEach((row, filePath) => {
1813
+ const links = row?.file?.links ?? [];
1814
+ if (links.some((link) => affectedTargetKeys.has(normalizeWikiTargetKey(link?.rawTarget)))) {
1815
+ impactedPaths.add(filePath);
1816
+ }
1817
+ });
1818
+
1819
+ return impactedPaths;
1820
+ }
1821
+
1822
+ async refreshSnapshotRows(snapshot, workspaceState, pathValues = []) {
1823
+ const filePathsToRefresh = Array.from(new Set(pathValues))
1824
+ .filter((pathValue) => {
1825
+ const entry = workspaceState?.entries?.get(pathValue);
1826
+ return pathValue && isWorkspaceFileEntry(entry);
1827
+ });
1828
+
1829
+ await mapWithConcurrency(filePathsToRefresh, INDEX_READ_CONCURRENCY, async (filePath) => {
1830
+ const markdownContent = isMarkdownFilePath(filePath)
1831
+ ? await this.vaultFileStore.readMarkdownFile(filePath)
1832
+ : null;
1833
+ const rowRecord = this.createSnapshotRow(filePath, workspaceState, snapshot.wikiTargetIndex, markdownContent);
1834
+ snapshot.rowsByPath.set(filePath, rowRecord.row);
1835
+ snapshot.forwardLinksByPath.set(filePath, rowRecord.forwardLinks);
1836
+ });
1837
+ }
1838
+
1839
+ async ensureIndexSnapshot({ basePath = '', sourcePath = '' } = {}) {
1840
+ await this.synchronizeWorkspaceState();
1841
+ let workspaceState = await this.getWorkspaceState();
1842
+ const requiresFreshScan = [basePath, sourcePath]
1843
+ .filter(Boolean)
1844
+ .some((pathValue) => !workspaceState?.entries?.has?.(pathValue));
1845
+ if (requiresFreshScan) {
1846
+ workspaceState = await this.vaultFileStore.scanWorkspaceState();
1847
+ this.lastWorkspaceState = workspaceState;
1848
+ if (this.indexSnapshot?.scannedAt !== workspaceState?.scannedAt) {
1849
+ this.indexSnapshot = null;
1850
+ }
1851
+ }
1852
+
1853
+ if (this.indexSnapshot?.scannedAt === workspaceState?.scannedAt) {
1854
+ return this.indexSnapshot;
1855
+ }
1856
+
1857
+ return this.buildIndexSnapshot(workspaceState);
1858
+ }
1859
+
1860
+ async initializeFromWorkspaceState(workspaceState = null) {
1861
+ this.lastWorkspaceState = workspaceState ?? null;
1862
+ if (this.indexSnapshot && workspaceState && this.indexSnapshot.scannedAt !== workspaceState.scannedAt) {
1863
+ this.indexSnapshot = null;
1864
+ }
1865
+ return this.indexSnapshot;
1866
+ }
1867
+
1868
+ async applyWorkspaceChange(workspaceChange = {}, {
1869
+ previousState = null,
1870
+ nextState = null,
1871
+ } = {}) {
1872
+ this.lastWorkspaceState = nextState ?? this.lastWorkspaceState;
1873
+ if (!this.indexSnapshot) {
1874
+ return null;
1875
+ }
1876
+
1877
+ if (!previousState || this.indexSnapshot.scannedAt !== previousState.scannedAt) {
1878
+ this.indexSnapshot = null;
1879
+ return null;
1880
+ }
1881
+
1882
+ const changedPaths = Array.from(new Set(workspaceChange.changedPaths ?? []));
1883
+ const deletedFilePaths = (workspaceChange.deletedPaths ?? []).filter((pathValue) => (
1884
+ isWorkspaceFileEntry(previousState?.entries?.get(pathValue))
1885
+ ));
1886
+ const renamedFileEntries = (workspaceChange.renamedPaths ?? []).filter((entry) => (
1887
+ isWorkspaceFileEntry(previousState?.entries?.get(entry?.oldPath))
1888
+ || isWorkspaceFileEntry(nextState?.entries?.get(entry?.newPath))
1889
+ ));
1890
+ const createdFilePaths = changedPaths.filter((pathValue) => (
1891
+ isWorkspaceFileEntry(nextState?.entries?.get(pathValue))
1892
+ && !isWorkspaceFileEntry(previousState?.entries?.get(pathValue))
1893
+ ));
1894
+ const removedChangedFilePaths = changedPaths.filter((pathValue) => (
1895
+ !isWorkspaceFileEntry(nextState?.entries?.get(pathValue))
1896
+ && isWorkspaceFileEntry(previousState?.entries?.get(pathValue))
1897
+ ));
1898
+ const membershipChanged = deletedFilePaths.length > 0
1899
+ || renamedFileEntries.length > 0
1900
+ || createdFilePaths.length > 0
1901
+ || removedChangedFilePaths.length > 0;
1902
+
1903
+ const markdownPathsToRefresh = changedPaths.filter((pathValue) => (
1904
+ isWorkspaceFileEntry(previousState?.entries?.get(pathValue))
1905
+ && isWorkspaceFileEntry(nextState?.entries?.get(pathValue))
1906
+ ));
1907
+
1908
+ if (!membershipChanged && markdownPathsToRefresh.length === 0) {
1909
+ this.indexSnapshot.workspaceState = nextState ?? this.indexSnapshot.workspaceState;
1910
+ this.indexSnapshot.scannedAt = nextState?.scannedAt ?? this.indexSnapshot.scannedAt;
1911
+ return this.indexSnapshot;
1912
+ }
1913
+
1914
+ const snapshot = this.indexSnapshot;
1915
+ if (membershipChanged) {
1916
+ const membershipAffectedPaths = [
1917
+ ...deletedFilePaths,
1918
+ ...removedChangedFilePaths,
1919
+ ...createdFilePaths,
1920
+ ...renamedFileEntries.flatMap((entry) => [entry.oldPath, entry.newPath]),
1921
+ ];
1922
+ const impactedSourcePaths = this.collectImpactedSourcesForMembershipChanges(snapshot, membershipAffectedPaths);
1923
+
1924
+ [...deletedFilePaths, ...removedChangedFilePaths].forEach((pathValue) => {
1925
+ this.removeSnapshotPath(snapshot, pathValue);
1926
+ });
1927
+ renamedFileEntries.forEach((entry) => {
1928
+ this.removeSnapshotPath(snapshot, entry.oldPath);
1929
+ });
1930
+ [...createdFilePaths, ...renamedFileEntries.map((entry) => entry.newPath)].forEach((pathValue) => {
1931
+ const nextEntry = nextState?.entries?.get(pathValue);
1932
+ if (isWorkspaceFileEntry(nextEntry)) {
1933
+ this.upsertSnapshotPath(snapshot, pathValue);
1934
+ }
1935
+ });
1936
+
1937
+ snapshot.wikiTargetIndex = createWikiTargetIndex(snapshot.filePaths);
1938
+ await this.refreshSnapshotRows(snapshot, nextState, [
1939
+ ...markdownPathsToRefresh,
1940
+ ...createdFilePaths,
1941
+ ...renamedFileEntries.map((entry) => entry.newPath),
1942
+ ...impactedSourcePaths,
1943
+ ]);
1944
+ } else {
1945
+ await this.refreshSnapshotRows(snapshot, nextState, markdownPathsToRefresh);
1946
+ }
1947
+
1948
+ snapshot.workspaceState = nextState;
1949
+ snapshot.scannedAt = nextState?.scannedAt ?? snapshot.scannedAt;
1950
+ this.rebuildBacklinks(snapshot);
1951
+ return snapshot;
1952
+ }
1953
+
1954
+ async query({
1955
+ activeFilePath = '',
1956
+ basePath = '',
1957
+ search = '',
1958
+ source = null,
1959
+ sourcePath = '',
1960
+ view: requestedView = '',
1961
+ } = {}) {
1962
+ const baseSource = source ?? (basePath ? await this.vaultFileStore.readBaseFile(basePath) : '');
1963
+ if (typeof baseSource !== 'string') {
1964
+ throw new Error('Base source not found');
1965
+ }
1966
+
1967
+ const definition = normalizeBaseDefinition(baseSource);
1968
+ const snapshot = await this.ensureIndexSnapshot({
1969
+ basePath,
1970
+ sourcePath,
1971
+ });
1972
+ const thisFilePath = sourcePath || activeFilePath || basePath || '';
1973
+ const thisFile = snapshot.rowsByPath.get(thisFilePath)?.file ?? null;
1974
+ const activeView = definition.views.find((entry) => entry.name === requestedView || entry.id === requestedView) ?? definition.views[0];
1975
+ const columns = buildColumns(definition, activeView);
1976
+ const evaluatedPropertyIds = collectEvaluatedPropertyIds(columns, activeView);
1977
+
1978
+ let rows = snapshot.filePaths
1979
+ .map((filePath) => snapshot.rowsByPath.get(filePath))
1980
+ .filter(Boolean)
1981
+ .filter((row) => {
1982
+ const globalContext = createEvaluationRootContext({
1983
+ currentRow: row,
1984
+ definition,
1985
+ snapshot,
1986
+ thisFile,
1987
+ });
1988
+ if (!evaluateFilterNode(definition.filters, globalContext)) {
1989
+ return false;
1990
+ }
1991
+
1992
+ const viewContext = createEvaluationRootContext({
1993
+ currentRow: row,
1994
+ definition,
1995
+ snapshot,
1996
+ thisFile,
1997
+ });
1998
+ return evaluateFilterNode(activeView.filters, viewContext);
1999
+ })
2000
+ .map((row) => {
2001
+ const rawCells = {};
2002
+ evaluatedPropertyIds.forEach((propertyId) => {
2003
+ rawCells[propertyId] = getPropertyValue(propertyId, row, definition, snapshot, thisFile);
2004
+ });
2005
+ return {
2006
+ file: row.file,
2007
+ rawCells,
2008
+ };
2009
+ });
2010
+
2011
+ activeView.sort.forEach((sortConfig) => {
2012
+ rows = rows.slice().sort((left, right) => {
2013
+ const delta = compareValues(left.rawCells[sortConfig.property], right.rawCells[sortConfig.property]);
2014
+ return sortConfig.direction === 'desc' ? -delta : delta;
2015
+ });
2016
+ });
2017
+
2018
+ if (activeView.limit != null) {
2019
+ rows = rows.slice(0, activeView.limit);
2020
+ }
2021
+
2022
+ rows = rows.filter((row) => rowMatchesSearch(row, columns, search));
2023
+
2024
+ const groupsByKey = new Map();
2025
+ if (activeView.groupBy) {
2026
+ rows.forEach((row) => {
2027
+ const groupValue = row.rawCells[activeView.groupBy];
2028
+ const groupKey = toDisplayText(groupValue) || 'Empty';
2029
+ const entry = groupsByKey.get(groupKey) ?? {
2030
+ key: groupKey,
2031
+ label: groupKey,
2032
+ rows: [],
2033
+ value: serializeBaseValue(groupValue, {
2034
+ rowFilePath: row.file.path,
2035
+ snapshot,
2036
+ sourcePath: thisFile?.path ?? '',
2037
+ }),
2038
+ };
2039
+ entry.rows.push(row);
2040
+ groupsByKey.set(groupKey, entry);
2041
+ });
2042
+ } else {
2043
+ groupsByKey.set('All', {
2044
+ key: 'All',
2045
+ label: 'All',
2046
+ rows,
2047
+ value: serializeBaseValue(null),
2048
+ });
2049
+ }
2050
+
2051
+ const serializedRows = rows.map((row) => ({
2052
+ cells: columns.reduce((acc, column) => {
2053
+ acc[column.id] = serializeBaseValue(row.rawCells[column.id], {
2054
+ rowFilePath: row.file.path,
2055
+ snapshot,
2056
+ sourcePath: thisFile?.path ?? '',
2057
+ });
2058
+ return acc;
2059
+ }, {}),
2060
+ file: serializeBaseValue(row.file, {
2061
+ rowFilePath: row.file.path,
2062
+ snapshot,
2063
+ sourcePath: thisFile?.path ?? '',
2064
+ }),
2065
+ path: row.file.path,
2066
+ }));
2067
+ const rowsByPath = new Map(serializedRows.map((row) => [row.path, row]));
2068
+
2069
+ const groups = Array.from(groupsByKey.values()).map((group) => ({
2070
+ key: group.key,
2071
+ label: group.label,
2072
+ summaries: createSummaryPayload(columns, group.rows, activeView.summaries, definition, snapshot, thisFile),
2073
+ value: group.value,
2074
+ rows: group.rows.map((row) => rowsByPath.get(row.file.path)),
2075
+ }));
2076
+
2077
+ return {
2078
+ columns,
2079
+ csv: createCsv(rows, columns),
2080
+ definition,
2081
+ groups,
2082
+ rows: serializedRows,
2083
+ summaries: createSummaryPayload(columns, rows, activeView.summaries, definition, snapshot, thisFile),
2084
+ thisFile: serializeBaseValue(thisFile, {
2085
+ snapshot,
2086
+ sourcePath: thisFile?.path ?? '',
2087
+ }),
2088
+ totalRows: rows.length,
2089
+ view: {
2090
+ ...activeView,
2091
+ supported: activeView.supported,
2092
+ },
2093
+ views: definition.views.map((view) => ({
2094
+ id: view.id,
2095
+ name: view.name,
2096
+ supported: view.supported,
2097
+ type: view.type,
2098
+ })),
2099
+ };
2100
+ }
2101
+ }