collabmd 0.1.46 → 0.1.48

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 (317) hide show
  1. package/README.md +9 -5
  2. package/dist/client/assets/{CodeMirrorEditor-UCMRAMCV-CYM5nxUi.js → CodeMirrorEditor-UCMRAMCV-BPH4FJkv.js} +1 -1
  3. package/dist/client/assets/JetBrainsMono-Regular-BQaDgvhP.woff2 +0 -0
  4. package/dist/client/assets/{abnfDiagram-N423BO3Z-CUMTFJhI.js → abnfDiagram-VCTEODGH-BNDLzJ7L.js} +1 -1
  5. package/dist/client/assets/architecture-7GRP2DOG-BMOPAkUC.js +1 -0
  6. package/dist/client/assets/{architectureDiagram-T3A2C74G-w25m71oV.js → architectureDiagram-5GKGNRK7-I39sYjHI.js} +1 -1
  7. package/dist/client/assets/babel-CY5KOv-I.js +16 -0
  8. package/dist/client/assets/base-BYODPHdS.js +1 -0
  9. package/dist/client/assets/blockDiagram-NRAW4CY4-C6DtJy5Y.js +129 -0
  10. package/dist/client/assets/browser-BKLM0ThC-IxjwuOIz-BBqQnUEb.js +1 -0
  11. package/dist/client/assets/c4Diagram-UCG6FXSJ-CtWtxS9_.js +38 -0
  12. package/dist/client/assets/channel-CaoKA_We.js +1 -0
  13. package/dist/client/assets/{chunk-U6XO7XAA-BFxjP5U3.js → chunk-2ZTRR5NV-C2qZJila.js} +1 -1
  14. package/dist/client/assets/{chunk-YOTPTUD7-D0vRKqYp.js → chunk-3Z5EZCMW-DMniOlPd.js} +1 -1
  15. package/dist/client/assets/{chunk-BIQX33UG-DZEsGuSn.js → chunk-5V3GS4D5-i-ZDOEnP.js} +1 -1
  16. package/dist/client/assets/{chunk-MOZMSUNE-XVucA-n6.js → chunk-6AZGARVD-BB6FqMl-.js} +1 -1
  17. package/dist/client/assets/{chunk-5JV3BV7I-Cy5pj3QY.js → chunk-6EIED4P4-DdUJkP0f.js} +1 -1
  18. package/dist/client/assets/{chunk-R7FJI6CG-Cnn3gE-Y.js → chunk-6K3QC6MW-CqVsVn-y.js} +1 -1
  19. package/dist/client/assets/{chunk-OSBZ3O6U-CrKZOUOr.js → chunk-6TQVIW2G-DKlLbNIP.js} +1 -1
  20. package/dist/client/assets/{chunk-JG7HCLWE-BYfiSaVt.js → chunk-747NJXEK-BFkZPlab.js} +1 -1
  21. package/dist/client/assets/{chunk-NSK5VX7P-TLH37VXI.js → chunk-75Z2AOVW-CdFSaPjz.js} +1 -1
  22. package/dist/client/assets/chunk-CKBBP62Z-DG26UiBv.js +2 -0
  23. package/dist/client/assets/{chunk-3NCLNEKW-Y2Jf_LI-.js → chunk-CLGD4ZFX-DQLgbQrv.js} +1 -1
  24. package/dist/client/assets/chunk-DSNCTWBM-8xkug7fQ.js +2 -0
  25. package/dist/client/assets/chunk-DU6HZSFF-COXDzJK1.js +127 -0
  26. package/dist/client/assets/{chunk-2GRJ4B5K-DhnlUv3F.js → chunk-F27PBJKO-CNHIFhjo.js} +1 -1
  27. package/dist/client/assets/{chunk-YGJVY4SA-CjSe7Bx7.js → chunk-FLYJHZSQ-Be7lKF17.js} +1 -1
  28. package/dist/client/assets/{chunk-KEIR6QF5-BICK3FdT.js → chunk-FOHPRMQF-DHwB1DNv.js} +2 -2
  29. package/dist/client/assets/{chunk-5RXB4S5H-BWrwFqMI.js → chunk-G27WJ6UU-D9-eg537.js} +2 -2
  30. package/dist/client/assets/chunk-GMAD6QVW-CbcBqPM5.js +72 -0
  31. package/dist/client/assets/{chunk-QBLGF6JB-CxAyS2mW.js → chunk-I5DQTOEV-Hm2LfiYI.js} +1 -1
  32. package/dist/client/assets/{chunk-5FCAYU7R-Dh5nylU8.js → chunk-ICYGCRZG-749o-pGJ.js} +1 -1
  33. package/dist/client/assets/{chunk-CQNSW5MT-B8S09OIh.js → chunk-IH6LHLGP-CC6I9F3i.js} +1 -1
  34. package/dist/client/assets/chunk-JQ64N6SF-DSFNH4bh.js +1 -0
  35. package/dist/client/assets/{chunk-CYSBUYHQ-C1Rf4art.js → chunk-KI3K4JFJ-Rma-0k_M.js} +1 -1
  36. package/dist/client/assets/{chunk-GF5L2VYU-DkJpO7ff.js → chunk-LCL6LL3I-DmDkVukh.js} +1 -1
  37. package/dist/client/assets/chunk-LNGE3PJU-DWpGwHrW.js +34 -0
  38. package/dist/client/assets/chunk-OBVCFTLP-BJR7u1jh.js +1 -0
  39. package/dist/client/assets/{chunk-5TONJI2A-DQOY3q1H.js → chunk-OUJLGHUK-D0j2JRSg.js} +1 -1
  40. package/dist/client/assets/chunk-P2QGCYS3-BRpqY32H.js +1 -0
  41. package/dist/client/assets/{chunk-KBJHAD2P-CB_3zWUf.js → chunk-POPQ4Y6H-Cb4SlVZF.js} +1 -1
  42. package/dist/client/assets/{chunk-4I5QYGJK-CCB2YcIH.js → chunk-PWAF6VOD-Cz8IwBB5.js} +1 -1
  43. package/dist/client/assets/chunk-R7TYR2AO-CTd0Yj98.js +10 -0
  44. package/dist/client/assets/chunk-RHFEMEQ7-CWY8cf4H.js +168 -0
  45. package/dist/client/assets/chunk-RM4UPSZO-CWRwxNWJ.js +41 -0
  46. package/dist/client/assets/{chunk-6Q2QTUOP-CPlWzBtc.js → chunk-SVP7TREG-CyHOmcac.js} +1 -1
  47. package/dist/client/assets/chunk-TEH6E4GO-DVayPj-q.js +62 -0
  48. package/dist/client/assets/{chunk-EMLP6XTP-RLD4nXpI.js → chunk-UY3FDG6J-CnmaAkG5.js} +1 -1
  49. package/dist/client/assets/{chunk-5HE753X5-Bw-yg4kO.js → chunk-XHIXRSVI-BFQ6B8BE.js} +1 -1
  50. package/dist/client/assets/classDiagram-DTDB5LWJ-7fEmn0zV.js +1 -0
  51. package/dist/client/assets/classDiagram-v2-JRS7N3AN-7fEmn0zV.js +1 -0
  52. package/dist/client/assets/comment-ui-shared-DuoyznXW.js +7 -0
  53. package/dist/client/assets/cynefin-OW5HDTMX-7tP7QfM3.js +1 -0
  54. package/dist/client/assets/{cynefinDiagram-MW4NZA55-CJxXfJek.js → cynefinDiagram-5FMLGOSQ-CdTPi2yO.js} +1 -1
  55. package/dist/client/assets/dagre-3AP2YEHR-5gtJtd0O.js +4 -0
  56. package/dist/client/assets/dagre-PrKaheQc.js +1 -0
  57. package/dist/client/assets/{diagram-7IWD3JNH-B2d2Bm15.js → diagram-S7CK7UJ4-BudWz9WU.js} +4 -4
  58. package/dist/client/assets/{diagram-UB23O5K3-DJcKCwv9.js → diagram-UQ7AKVKN-3v4rbH-s.js} +1 -1
  59. package/dist/client/assets/{diagram-B4RE2ZJO-NP4UAwjR.js → diagram-VSXAHHWV-CQRVEZR7.js} +1 -1
  60. package/dist/client/assets/{diagram-Q27KOJAE-DylDuwor.js → diagram-VX7I27RA-C_-rj0sw.js} +1 -1
  61. package/dist/client/assets/{diagram-LBJQPF4R-D1FJQV8t.js → diagram-Z3DM3KII-B4yxavgj.js} +1 -1
  62. package/dist/client/assets/direct-engine-DdrQKpgq-CtKfQzCt.js +5 -0
  63. package/dist/client/assets/dist-73RPdcyU.js +1 -0
  64. package/dist/client/assets/{dist-Bm6pf9Bl.js → dist-BJ1bJs33.js} +1 -1
  65. package/dist/client/assets/{dist-BalScOwZ.js → dist-BK9QvQrc.js} +1 -1
  66. package/dist/client/assets/{dist-DLMiIsNC.js → dist-BPHLJ09L.js} +1 -1
  67. package/dist/client/assets/{dist-Bf8f4HmM.js → dist-B_yQaEv_.js} +1 -1
  68. package/dist/client/assets/{dist-CC5IrQMG.js → dist-BeajGMhO.js} +1 -1
  69. package/dist/client/assets/{dist-PDZ3bSqm.js → dist-Bw3VIE_v.js} +1 -1
  70. package/dist/client/assets/{dist-xElaxbia.js → dist-ByrG2qBA.js} +1 -1
  71. package/dist/client/assets/{dist-ule2n6ak.js → dist-C5NgpdG5.js} +1 -1
  72. package/dist/client/assets/dist-CH-sQu3r.js +1 -0
  73. package/dist/client/assets/dist-CKS_-are.js +1 -0
  74. package/dist/client/assets/{dist-D-Z6FLem.js → dist-CdmKGRGr.js} +1 -1
  75. package/dist/client/assets/dist-ChRoo3IB.js +9 -0
  76. package/dist/client/assets/{dist-dtAdgL39.js → dist-CietwTVS.js} +1 -1
  77. package/dist/client/assets/{dist-jv4WdPnK.js → dist-D37Hyu3h.js} +1 -1
  78. package/dist/client/assets/dist-D3fehAZ2.js +2 -0
  79. package/dist/client/assets/{dist-BEwK4csK.js → dist-D5wCC32z.js} +1 -1
  80. package/dist/client/assets/{dist-shrl6K_0.js → dist-DDUn5zTz.js} +1 -1
  81. package/dist/client/assets/{dist-CZgOmxK6.js → dist-DGEbEfw4.js} +1 -1
  82. package/dist/client/assets/{dist-B5HTH2BO.js → dist-DVy5woUy.js} +1 -1
  83. package/dist/client/assets/{dist-DZKu9Cs8.js → dist-DZAAWTG-.js} +1 -1
  84. package/dist/client/assets/{dist-TjMh8n1u.js → dist-Dir5dDKZ.js} +1 -1
  85. package/dist/client/assets/dist-Dl_tpDSr.js +1 -0
  86. package/dist/client/assets/{dist-FWJsgGYI.js → dist-DuH3ZrHo.js} +1 -1
  87. package/dist/client/assets/{dist-BjHJDtyU.js → dist-DutPuFmC.js} +1 -1
  88. package/dist/client/assets/{dist-Cqhv5LAk.js → dist-LQ4kDCKz.js} +1 -1
  89. package/dist/client/assets/{dist-CCP_AKPG.js → dist-RKBTaQMb.js} +1 -1
  90. package/dist/client/assets/{dist-BoVBdSjk.js → dist-Tw-Fxpeb.js} +1 -1
  91. package/dist/client/assets/dist-eBx8q6Sy.js +1 -0
  92. package/dist/client/assets/{dist-rGBmqxC7.js → dist-mj2Ht75J.js} +1 -1
  93. package/dist/client/assets/{dist-BDt3rz7l.js → dist-netZOQtD.js} +1 -1
  94. package/dist/client/assets/document-formatter-Dxl_a8XO.js +2 -0
  95. package/dist/client/assets/{drawio-editor-FzY1cVw8.js → drawio-editor-BVaNNtYp.js} +2 -2
  96. package/dist/client/assets/{drawioEditor-BjiKJqlc.js → drawioEditor-BkIBlXx0.js} +2 -2
  97. package/dist/client/assets/{ebnfDiagram-BXEA7PRR-nw0wmA6y.js → ebnfDiagram-PWID7BFC-OXa8VEp1.js} +1 -1
  98. package/dist/client/assets/editor-session-DMyVdHLj.js +54 -0
  99. package/dist/client/assets/embedded-editor-base-B3l6Xy65.css +1 -0
  100. package/dist/client/assets/embedpdf-BmE13ZZ0.js +1 -0
  101. package/dist/client/assets/embedpdf-DA4bA119-BPqZxwjc.js +2363 -0
  102. package/dist/client/assets/{en-7NFCYGKX-BrgYZAEe.js → en-SJ2YIMFF-CJBL3nkq.js} +1 -1
  103. package/dist/client/assets/erDiagram-SSCWMZ5O-C-iy6VkX.js +99 -0
  104. package/dist/client/assets/estree-CuT_pB8K.js +44 -0
  105. package/dist/client/assets/eventmodeling-NTZA5JFV-BR2FzK4R.js +1 -0
  106. package/dist/client/assets/excalidraw-editor-BbSbI80a.css +1 -0
  107. package/dist/client/assets/excalidraw-editor-BjYaNEMY.js +9 -0
  108. package/dist/client/assets/excalidrawEditor-ChqF_d82.js +2 -0
  109. package/dist/client/assets/export-page-Dyu0XCbu.js +57 -0
  110. package/dist/client/assets/exportDocument-CJBx4Xjx.css +1 -0
  111. package/dist/client/assets/exportDocument-Dgvfa2Sd.js +2 -0
  112. package/dist/client/assets/{file-icon-svg-CQAjlWjK.js → file-icon-svg-Y_kpF957.js} +1 -1
  113. package/dist/client/assets/file-kind-BwMIcZbi.js +1 -0
  114. package/dist/client/assets/file-search-DDLyyLDU.js +1 -0
  115. package/dist/client/assets/flowDiagram-A5DVABFB-CiW1eN8C.js +1 -0
  116. package/dist/client/assets/{ganttDiagram-PKOTCBZU-BnM97BCT.js → ganttDiagram-EL5Y4UJY-DtKHAbez.js} +1 -1
  117. package/dist/client/assets/gitGraph-4MIJSDKK-DYlXv_yJ.js +1 -0
  118. package/dist/client/assets/{gitGraphDiagram-DS77QQ5N-BQpQhjuN.js → gitGraphDiagram-WWUBYQGX-oue8fQ5o.js} +1 -1
  119. package/dist/client/assets/github-dark.min-BV82VuKq.css +1 -0
  120. package/dist/client/assets/github.min-v3dd8CNH.css +1 -0
  121. package/dist/client/assets/html-Cdnr2qzU.js +25 -0
  122. package/dist/client/assets/image-ZVKINSPA-0zXSnE7M.js +1 -0
  123. package/dist/client/assets/index-CSNIMyOP.css +1 -0
  124. package/dist/client/assets/index-DG3N2Ps-.js +2 -0
  125. package/dist/client/assets/info-A6RAGUB7-BlU-8_xu.js +1 -0
  126. package/dist/client/assets/{infoDiagram-6WML65LV-DYB8HCDQ.js → infoDiagram-RXCK75RN-BMzo6KIn.js} +1 -1
  127. package/dist/client/assets/{ishikawaDiagram-WSZJBQD7-Coz_P3t6.js → ishikawaDiagram-5VMMS53U-BIM3h287.js} +1 -1
  128. package/dist/client/assets/{journeyDiagram-NVQOT4AX-B6edChce.js → journeyDiagram-EYS64GPL-mF6Lh8O-.js} +1 -1
  129. package/dist/client/assets/{kanban-definition-27J2QSJJ-BFd9-cLc.js → kanban-definition-3QL26DDD-DLN2NyoR.js} +2 -2
  130. package/dist/client/assets/{line-B_S_S8kV.js → line-BfTWJmgf.js} +1 -1
  131. package/dist/client/assets/main-D0wCxpVn.js +903 -0
  132. package/dist/client/assets/markdown-CByV-4CU.js +70 -0
  133. package/dist/client/assets/{mermaid-parser.core-CUVdebAV.js → mermaid-parser.core-Bl0efOMt.js} +2 -2
  134. package/dist/client/assets/mermaid.core-BJRLUQZE.js +11 -0
  135. package/dist/client/assets/{mindmap-definition-FAOFIHXS-C9PQ38Al.js → mindmap-definition-FBJOCRG2-CRyHaHTk.js} +1 -1
  136. package/dist/client/assets/packet-AYTQ26CC-BSJEH9Lb.js +1 -0
  137. package/dist/client/assets/pdfium-RAgkpwfK.wasm +0 -0
  138. package/dist/client/assets/{pegDiagram-VL7TDLO6-BMZUrSaU.js → pegDiagram-XKGWAZYB-B31fKPR2.js} +1 -1
  139. package/dist/client/assets/pie-WAS4IAKB-qxv01Y8W.js +1 -0
  140. package/dist/client/assets/{pieDiagram-7S7Q4E2Y-h8kbCL9o.js → pieDiagram-E7YTZNPT-B5OZPb88.js} +1 -1
  141. package/dist/client/assets/preview-render-compiler-CrJIooVD.js +35 -0
  142. package/dist/client/assets/preview-render-compiler-O0JxBVNF.js +1 -0
  143. package/dist/client/assets/{preview-render-profile-CE-5rVTC.js → preview-render-profile-B4RWYWHt.js} +1 -1
  144. package/dist/client/assets/preview-render-worker-_QTxqKvP.js +60 -0
  145. package/dist/client/assets/prod-BiYPMR1i.js +177 -0
  146. package/dist/client/assets/prod-VxdGZ5Ly.js +1 -0
  147. package/dist/client/assets/{quadrantDiagram-CIZ2JOQS-CkElyfMi.js → quadrantDiagram-AXDQQJYC-Drrw14YH.js} +1 -1
  148. package/dist/client/assets/quick-switcher-controller-CaEjEtq_.js +1 -0
  149. package/dist/client/assets/radar-RG4KPBEZ-B6h6pWOs.js +1 -0
  150. package/dist/client/assets/railroad-74A4TZTK-CGtTWdGc.js +1 -0
  151. package/dist/client/assets/railroad-abnf-HS5TGJTU-Cq7y22IA.js +1 -0
  152. package/dist/client/assets/railroad-ebnf-LZEXJU2U-V0aQVv9m.js +1 -0
  153. package/dist/client/assets/railroad-peg-WCYAUIDC-BQiIsX_p.js +1 -0
  154. package/dist/client/assets/{railroadDiagram-AXF67PYL-c75gnikD.js → railroadDiagram-O6MQD6OU-BPifP0MB.js} +1 -1
  155. package/dist/client/assets/{requirementDiagram-LRYGKXZP-mNxKLuHS.js → requirementDiagram-EFPCY7ZU-CRZG6mRB.js} +2 -2
  156. package/dist/client/assets/{sankeyDiagram-W5VNT64P-0OhplksI.js → sankeyDiagram-P5KCCOFB-DvarEJpo.js} +1 -1
  157. package/dist/client/assets/{sequenceDiagram-SI44F4Z6-BJ_yAocC.js → sequenceDiagram-WJ2MYXX4-B4oWlb-w.js} +1 -1
  158. package/dist/client/assets/standalone-6z5x8CWe.js +29 -0
  159. package/dist/client/assets/{stateDiagram-OKZ733FA-Cc83O86s.js → stateDiagram-HBIQ2CUA-qbHIIqRZ.js} +1 -1
  160. package/dist/client/assets/stateDiagram-v2-4QOOHH4V-B--gjrit.js +1 -0
  161. package/dist/client/assets/swimlanes-XN3QIQJK-xB6CtUGj.js +1 -0
  162. package/dist/client/assets/swimlanesDiagram-VK2B7HYN-DO8XNXEg.js +8 -0
  163. package/dist/client/assets/{timeline-definition-Z64GVDOM-BWDAGTHz.js → timeline-definition-24CTP7MA-Lj_yTNlY.js} +1 -1
  164. package/dist/client/assets/treeView-Q6P3EWNA-BTTYcvrF.js +1 -0
  165. package/dist/client/assets/treemap-WGGIJYW6-Cg7tyfH8.js +1 -0
  166. package/dist/client/assets/{vault-api-client-_LpV1aIn.js → vault-api-client-BkwdFjx0.js} +2 -2
  167. package/dist/client/assets/vault-utils-DvoSftJT.js +22 -0
  168. package/dist/client/assets/{vennDiagram-T6HMQDX7-LOSsnlMB.js → vennDiagram-4TSXK5OY-BekRp5Y0.js} +1 -1
  169. package/dist/client/assets/wardley-WFR3VGLG-C6N1rULY.js +1 -0
  170. package/dist/client/assets/{wardleyDiagram-T6FBY63Y-BxII3foY.js → wardleyDiagram-VM6X3IG4-kdnV_Hdm.js} +1 -1
  171. package/dist/client/assets/worker-engine-m0rlHn8R-S8mpn_O0.js +17369 -0
  172. package/dist/client/assets/{xychartDiagram-ELKLHX3M-B-pTEjju.js → xychartDiagram-S5SC5T6Z-DufGwNSB.js} +3 -3
  173. package/dist/client/assets/yaml-9ltHPDNO.js +154 -0
  174. package/dist/client/drawio-editor.html +1 -1
  175. package/dist/client/excalidraw-editor.html +1 -1
  176. package/dist/client/export-document.html +3 -3
  177. package/dist/client/index.html +56 -24
  178. package/package.json +22 -18
  179. package/src/client/app/index.html +53 -21
  180. package/src/client/application/app-shell/comments-feature.js +2 -3
  181. package/src/client/application/app-shell/export-feature.js +17 -1
  182. package/src/client/application/app-shell/git-feature.js +30 -11
  183. package/src/client/application/app-shell/presence-feature.js +2 -2
  184. package/src/client/application/app-shell/ui-feature-identity.js +13 -0
  185. package/src/client/application/app-shell/ui-feature-shell.js +228 -9
  186. package/src/client/application/app-shell-elements.js +5 -0
  187. package/src/client/application/pdf-preview-controller.js +53 -970
  188. package/src/client/application/preview-render-compiler.js +3 -0
  189. package/src/client/application/quick-switcher-loader.js +1 -1
  190. package/src/client/application/workspace-coordinator.js +21 -4
  191. package/src/client/application/workspace-preview-controller.js +120 -5
  192. package/src/client/application/workspace-route-controller.js +4 -1
  193. package/src/client/assets/vendor/highlight/github-dark.min.css +2 -10
  194. package/src/client/assets/vendor/highlight/github.min.css +2 -10
  195. package/src/client/assets/vendor/jetbrains-mono/JetBrainsMono-Regular.woff2 +0 -0
  196. package/src/client/assets/vendor/jetbrains-mono/OFL.txt +93 -0
  197. package/src/client/bootstrap/collabmd-app-shell.js +31 -8
  198. package/src/client/domain/document-formatter.js +193 -0
  199. package/src/client/domain/file-search.js +73 -0
  200. package/src/client/domain/git-labels.js +5 -0
  201. package/src/client/domain/vault-paths.js +6 -4
  202. package/src/client/domain/wiki-link-completions.js +20 -20
  203. package/src/client/drawio-editor.js +8 -3
  204. package/src/client/excalidraw-editor.js +163 -6
  205. package/src/client/export/export-host.js +57 -36
  206. package/src/client/export/export-page.js +20 -6
  207. package/src/client/export/export-pipeline.js +322 -22
  208. package/src/client/infrastructure/editor-session.js +4 -0
  209. package/src/client/infrastructure/editor-view-adapter.js +60 -14
  210. package/src/client/presentation/bases-preview-controller.js +35 -11
  211. package/src/client/presentation/comment-ui/comment-ui-render.js +4 -0
  212. package/src/client/presentation/comment-ui-controller.js +2 -0
  213. package/src/client/presentation/excalidraw-embed-controller.js +7 -0
  214. package/src/client/presentation/file-action-controller.js +15 -2
  215. package/src/client/presentation/file-explorer-controller.js +3 -5
  216. package/src/client/presentation/file-explorer-view.js +43 -45
  217. package/src/client/presentation/file-history-view-controller.js +6 -1
  218. package/src/client/presentation/file-tree-state.js +5 -14
  219. package/src/client/presentation/git-diff-view-controller.js +36 -11
  220. package/src/client/presentation/git-panel-controller.js +12 -8
  221. package/src/client/presentation/quick-switcher-controller.js +92 -153
  222. package/src/client/styles/components/scrollbars.css +10 -0
  223. package/src/client/styles/export-document.css +44 -29
  224. package/src/client/styles/features/collaboration-presence.css +13 -1
  225. package/src/client/styles/features/preview-markdown.css +79 -0
  226. package/src/client/styles/features/quick-switcher.css +8 -0
  227. package/src/client/styles/foundation/themes.css +1 -0
  228. package/src/client/styles/foundation/tokens.css +8 -0
  229. package/src/client/styles/layout/shell.css +73 -339
  230. package/src/client/styles/layout/sidebar.css +42 -4
  231. package/src/client/styles/layout/view-modes.css +2 -0
  232. package/src/client/styles/overrides/codemirror.css +31 -19
  233. package/src/client/styles/overrides/highlightjs.css +20 -4
  234. package/src/client/styles/surfaces/excalidraw-editor.css +42 -0
  235. package/src/domain/file-kind.js +12 -1
  236. package/src/server/domain/ripgrep-search-service.js +110 -37
  237. package/src/server/infrastructure/git/git-service.js +23 -11
  238. package/src/server/infrastructure/http/create-git-api-command-handler.js +3 -1
  239. package/src/server/infrastructure/http/create-structurizr-api-handler.js +4 -2
  240. package/src/server/infrastructure/persistence/path-utils.js +10 -4
  241. package/src/server/infrastructure/persistence/vault-file-store.js +2 -0
  242. package/src/server/infrastructure/structurizr/structurizr-workspace-service.js +33 -7
  243. package/dist/client/assets/architecture-TIHT7OUA-CsHfPErM.js +0 -1
  244. package/dist/client/assets/base-CxPEiHuy.js +0 -1
  245. package/dist/client/assets/blockDiagram-VBNYF7ZC-CipJt9Jl.js +0 -132
  246. package/dist/client/assets/c4Diagram-5PPSVZJV-B5ktVx6g.js +0 -10
  247. package/dist/client/assets/channel-4Jkmq93I.js +0 -1
  248. package/dist/client/assets/chunk-7BUUIJ7U-Bb538aSH.js +0 -1
  249. package/dist/client/assets/chunk-7Z6QIM7H-BP9Pdsm9.js +0 -10
  250. package/dist/client/assets/chunk-ERSWUTIN-hHdvnhaY.js +0 -41
  251. package/dist/client/assets/chunk-I66GZJ75-CVFiiffQ.js +0 -127
  252. package/dist/client/assets/chunk-J7OUQ5F2-4CEb7pvH.js +0 -2
  253. package/dist/client/assets/chunk-JQJVKLGR-cx8X_24v.js +0 -156
  254. package/dist/client/assets/chunk-QR6OTTB3-CDAA_5Ib.js +0 -62
  255. package/dist/client/assets/chunk-RYQCIY6F-D-a0zH8K.js +0 -1
  256. package/dist/client/assets/chunk-UBXNYLIW-Bhk-PbFK.js +0 -1
  257. package/dist/client/assets/chunk-W5SLKNZC-BdNSCxZ9.js +0 -1
  258. package/dist/client/assets/chunk-WRU74C26-h6_XkD3_.js +0 -70
  259. package/dist/client/assets/chunk-ZIRB5QZD-O39ZBUk3.js +0 -32
  260. package/dist/client/assets/classDiagram-JCYQIIEL-L7lsyW_w.js +0 -1
  261. package/dist/client/assets/classDiagram-v2-OCEON4UE-L7lsyW_w.js +0 -1
  262. package/dist/client/assets/comment-ui-shared-BC4pt4w8.js +0 -7
  263. package/dist/client/assets/cynefin-VYW2F7L2-Ds2Fw2Y0.js +0 -1
  264. package/dist/client/assets/dagre-Buvkdvvj.js +0 -1
  265. package/dist/client/assets/dagre-VZM6K2ZE-L1xArOGs.js +0 -4
  266. package/dist/client/assets/dist-B5Jf1SLZ.js +0 -2
  267. package/dist/client/assets/dist-BKW4PALF.js +0 -1
  268. package/dist/client/assets/dist-BWcHHOx-.js +0 -1
  269. package/dist/client/assets/dist-DaYdhcVs.js +0 -1
  270. package/dist/client/assets/dist-Kh2COra_.js +0 -1
  271. package/dist/client/assets/dist-tOaegDYS2.js +0 -1
  272. package/dist/client/assets/editor-session-Cm9ekeNo.js +0 -54
  273. package/dist/client/assets/embedded-editor-base-CwTkk911.css +0 -1
  274. package/dist/client/assets/erDiagram-JOGREHBK-cYUpEKpf.js +0 -85
  275. package/dist/client/assets/es-DXGV3RHd.js +0 -22
  276. package/dist/client/assets/eventmodeling-45OFAUF4-CLEiVx5s.js +0 -1
  277. package/dist/client/assets/excalidraw-editor-B46zsTFI.js +0 -9
  278. package/dist/client/assets/excalidraw-editor-Bt7gMSoh.css +0 -1
  279. package/dist/client/assets/excalidrawEditor-CT2pHq7e.js +0 -2
  280. package/dist/client/assets/export-page-A7NHawJY.js +0 -39
  281. package/dist/client/assets/exportDocument-B2L8fe34.css +0 -1
  282. package/dist/client/assets/exportDocument-BaqcOAAW.js +0 -2
  283. package/dist/client/assets/file-kind-BbqgGzpc.js +0 -1
  284. package/dist/client/assets/flowDiagram-UKHOOZJN-D0ypP0Ez.js +0 -1
  285. package/dist/client/assets/gitGraph-TEB2WS4Q-CZFBqwW-.js +0 -1
  286. package/dist/client/assets/github-dark.min-Z5exjX_n.css +0 -1
  287. package/dist/client/assets/github.min-D2BCvnWf.css +0 -1
  288. package/dist/client/assets/image-QXRYHUNP-SWEV8H0J.js +0 -1
  289. package/dist/client/assets/index-ClbjMBVt.js +0 -2
  290. package/dist/client/assets/index-Pum8ET-5.css +0 -1
  291. package/dist/client/assets/info-DKCQHKI2--1InqQeT.js +0 -1
  292. package/dist/client/assets/main-B3uPyqic.js +0 -893
  293. package/dist/client/assets/map-BaFkSB1l.js +0 -1
  294. package/dist/client/assets/mermaid.core-DN-lF51U.js +0 -11
  295. package/dist/client/assets/packet-7NZHBO7P-BGMXB0XL.js +0 -1
  296. package/dist/client/assets/pdf-BL9Pr2D5.js +0 -54
  297. package/dist/client/assets/pdf.worker-CLesOks4.mjs +0 -64857
  298. package/dist/client/assets/pdf_viewer-FVkkThnz.js +0 -551
  299. package/dist/client/assets/pie-RZYD4A2V-DgYg3tCt.js +0 -1
  300. package/dist/client/assets/preview-render-compiler-BD-XhkS2.js +0 -35
  301. package/dist/client/assets/preview-render-compiler-BKedaMxx.js +0 -1
  302. package/dist/client/assets/preview-render-worker-CiPqc9n6.js +0 -60
  303. package/dist/client/assets/prod-Dy20X7eT.js +0 -1
  304. package/dist/client/assets/prod-hnwh7wRM.js +0 -177
  305. package/dist/client/assets/quick-switcher-controller-fqOYR7qR.js +0 -12
  306. package/dist/client/assets/radar-I7S5WNFK-Ag-zp_Rq.js +0 -1
  307. package/dist/client/assets/railroad-3IZDKUUU-aibJDIDV.js +0 -1
  308. package/dist/client/assets/railroad-abnf-AHOZXSZD-BBMEuvIl.js +0 -1
  309. package/dist/client/assets/railroad-ebnf-EBAXGLYW-Be1nseej.js +0 -1
  310. package/dist/client/assets/railroad-peg-LSFZ7HO6-DIvD-Eyb.js +0 -1
  311. package/dist/client/assets/stateDiagram-v2-UEYNNEHI-B1-BufUk.js +0 -1
  312. package/dist/client/assets/swimlanes-SLNWSIFB-oVTWEJIj.js +0 -2
  313. package/dist/client/assets/swimlanesDiagram-ULZ7WXOC-C5OTVwEu.js +0 -8
  314. package/dist/client/assets/treeView-QDETBFTQ-uHZ-3Fz8.js +0 -1
  315. package/dist/client/assets/treemap-6X3UGDF4-BnUKyy3l.js +0 -1
  316. package/dist/client/assets/vault-utils-wdQ0RNR9.js +0 -1
  317. package/dist/client/assets/wardley-OPB4EBWU-Da7TLC2F.js +0 -1
@@ -9,6 +9,9 @@ import { extractYamlFrontmatter } from '../../domain/yaml-frontmatter.js';
9
9
  import { renderFrontmatterBlock } from './markdown-frontmatter.js';
10
10
  import { analyzeMarkdownComplexity } from './preview-render-profile.js';
11
11
 
12
+ hljs.registerAliases(['cql', 'mariadb', 'mssql', 'mysql', 'plsql', 'sqlite'], { languageName: 'sql' });
13
+ hljs.registerAliases(['ecmascript', 'node'], { languageName: 'javascript' });
14
+
12
15
  const DIRECT_VIDEO_MIME_TYPES = Object.freeze({
13
16
  '.mp4': 'video/mp4',
14
17
  '.ogg': 'video/ogg',
@@ -27,7 +27,7 @@ export async function ensureQuickSwitcherInstance(host) {
27
27
  getSearchConfig: () => host.runtimeConfig.search ?? {},
28
28
  onFileSelect: (filePath) => host.workspaceRouteController.handleFileSelection(filePath, {
29
29
  closeSidebarOnMobile: true,
30
- revealInTree: true,
30
+ revealInTree: !host.isMobileViewport(),
31
31
  }),
32
32
  onTextMatchSelect: (match) => {
33
33
  if (!match?.file) {
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  isBaseFilePath,
3
+ isHtmlFilePath,
3
4
  isMarkdownFilePath,
4
5
  supportsBacklinksForFilePath,
5
6
  } from '../../domain/file-kind.js';
@@ -51,6 +52,7 @@ export class WorkspaceCoordinator {
51
52
  onRenderBasePreview,
52
53
  onRenderExcalidrawPreview,
53
54
  onRenderDrawioPreview,
55
+ onRenderHtmlPreview,
54
56
  onRenderImagePreview,
55
57
  onRenderPdfPreview,
56
58
  onRenderStructurizrPreview,
@@ -103,6 +105,7 @@ export class WorkspaceCoordinator {
103
105
  this.onRenderBasePreview = onRenderBasePreview;
104
106
  this.onRenderDrawioPreview = onRenderDrawioPreview;
105
107
  this.onRenderExcalidrawPreview = onRenderExcalidrawPreview;
108
+ this.onRenderHtmlPreview = onRenderHtmlPreview;
106
109
  this.onRenderImagePreview = onRenderImagePreview;
107
110
  this.onRenderPdfPreview = onRenderPdfPreview;
108
111
  this.onRenderStructurizrPreview = onRenderStructurizrPreview;
@@ -180,6 +183,7 @@ export class WorkspaceCoordinator {
180
183
  isDrawio = false,
181
184
  filePath,
182
185
  isExcalidraw = false,
186
+ isHtml = false,
183
187
  isImage = false,
184
188
  isPdf = false,
185
189
  supportsBacklinks,
@@ -187,6 +191,7 @@ export class WorkspaceCoordinator {
187
191
  if (isExcalidraw) this.onRenderExcalidrawPreview(filePath);
188
192
  if (isBase || isBaseFilePath(filePath)) this.onRenderBasePreview(filePath);
189
193
  if (isDrawio) this.onRenderDrawioPreview(filePath);
194
+ if (isHtml) this.onRenderHtmlPreview({ content: this.session?.getText?.() ?? '' });
190
195
  if (isImage) this.onRenderImagePreview(filePath);
191
196
  if (isPdf) this.onRenderPdfPreview(filePath);
192
197
  if (this.isStructurizrWorkspaceFile(filePath)) {
@@ -200,7 +205,14 @@ export class WorkspaceCoordinator {
200
205
 
201
206
  async openFile(filePath, { drawioMode = null } = {}) {
202
207
  if (!this.isTabActive()) {
203
- return;
208
+ return false;
209
+ }
210
+
211
+ if (!filePath || !this.getFileList().includes(filePath)) {
212
+ this.cleanupSession();
213
+ this.stateStore.sessionLoadToken += 1;
214
+ this.onFileOpenError({ code: 'not-found', filePath });
215
+ return false;
204
216
  }
205
217
 
206
218
  const normalizedDrawioMode = drawioMode ?? null;
@@ -210,6 +222,7 @@ export class WorkspaceCoordinator {
210
222
  const isBase = this.isBaseFile(filePath);
211
223
  const isImage = this.isImageFile(filePath);
212
224
  const isPdf = this.isPdfFile(filePath);
225
+ const isHtml = isHtmlFilePath(filePath);
213
226
  const isMermaid = this.isMermaidFile(filePath);
214
227
  const isPlantUml = this.isPlantUmlFile(filePath);
215
228
  const isStructurizrWorkspace = this.isStructurizrWorkspaceFile(filePath);
@@ -221,7 +234,7 @@ export class WorkspaceCoordinator {
221
234
  ) {
222
235
  this.onUpdateActiveFile(filePath);
223
236
  this.onUpdateLobbyCurrentFile(filePath);
224
- return;
237
+ return true;
225
238
  }
226
239
 
227
240
  const loadToken = ++this.stateStore.sessionLoadToken;
@@ -252,7 +265,7 @@ export class WorkspaceCoordinator {
252
265
  session: null,
253
266
  supportsBacklinks: chromeState.supportsBacklinks,
254
267
  });
255
- return;
268
+ return true;
256
269
  }
257
270
 
258
271
  const EditorSession = await this.loadEditorSessionClass();
@@ -272,6 +285,7 @@ export class WorkspaceCoordinator {
272
285
 
273
286
  this.onContentChange({
274
287
  isBase,
288
+ isHtml,
275
289
  isMermaid,
276
290
  isPlantUml,
277
291
  isStructurizrWorkspace,
@@ -313,6 +327,7 @@ export class WorkspaceCoordinator {
313
327
  filePath,
314
328
  isBase,
315
329
  isExcalidraw,
330
+ isHtml,
316
331
  session,
317
332
  supportsBacklinks: chromeState.supportsBacklinks,
318
333
  });
@@ -426,6 +441,7 @@ export class WorkspaceCoordinator {
426
441
  session.ensureInitialContent?.();
427
442
  await readySession('post-initialize');
428
443
  }
444
+ return true;
429
445
  } catch (error) {
430
446
  console.error('[app] Failed to initialize editor:', error);
431
447
  session.destroy();
@@ -438,7 +454,8 @@ export class WorkspaceCoordinator {
438
454
  return;
439
455
  }
440
456
 
441
- this.onFileOpenError();
457
+ this.onFileOpenError({ code: 'load-failed', filePath });
458
+ return false;
442
459
  }
443
460
  }
444
461
  }
@@ -1,11 +1,40 @@
1
1
  import {
2
2
  isBaseFilePath,
3
3
  isDiagramFilePath,
4
+ isHtmlFilePath,
4
5
  isMarkdownFilePath,
5
6
  isStructurizrFilePath,
6
7
  } from '../../domain/file-kind.js';
8
+ import { canFormatDocument } from '../domain/document-formatter.js';
9
+ import { setDiagramActionButtonIcon } from '../domain/diagram-action-icons.js';
7
10
  import { resolveApiUrl } from '../domain/runtime-paths.js';
8
11
 
12
+ const HTML_PREVIEW_CSP = "default-src 'none'; base-uri about:; form-action 'none'; object-src 'none'; frame-src 'none'; worker-src 'none'; connect-src 'none'; style-src 'unsafe-inline'; img-src data: blob:; font-src data:; media-src data: blob:";
13
+
14
+ function createHtmlPreviewDocument(content, allowScripts = false) {
15
+ const scriptSource = allowScripts ? "'unsafe-inline'" : "'none'";
16
+ return `<meta http-equiv="Content-Security-Policy" content="${HTML_PREVIEW_CSP}; script-src ${scriptSource};"><base href="about:srcdoc">${String(content ?? '')}`;
17
+ }
18
+
19
+ function hasHtmlScripts(content) {
20
+ const preview = new DOMParser().parseFromString(content, 'text/html');
21
+ if (preview.scripts.length > 0) return true;
22
+ return [...preview.querySelectorAll('*')].some((element) => [...element.attributes].some(({ name, value }) => (
23
+ (name.startsWith('on') && name in element)
24
+ || ((name === 'href' || name === 'xlink:href') && /^\s*javascript:/iu.test(value))
25
+ )));
26
+ }
27
+
28
+ function syncFormatDocumentButton(button, filePath, isPlantUml) {
29
+ if (!button) return;
30
+ const actionLabel = isPlantUml ? 'Indent PlantUML document' : 'Format document';
31
+ button.classList.toggle('hidden', !canFormatDocument(filePath));
32
+ button.setAttribute('aria-label', actionLabel);
33
+ button.setAttribute('title', actionLabel);
34
+ const label = button.querySelector('.ui-action-label');
35
+ if (label) label.textContent = isPlantUml ? 'Indent' : 'Format';
36
+ }
37
+
9
38
  export class WorkspacePreviewController {
10
39
  constructor({
11
40
  backlinksPanel,
@@ -43,6 +72,14 @@ export class WorkspacePreviewController {
43
72
  updateTheme() {},
44
73
  };
45
74
  this.elements = elements;
75
+ this.htmlPreviewShell = null;
76
+ if (this.elements.htmlPreviewMaximizeButton) {
77
+ this.elements.htmlPreviewMaximizeButton.addEventListener('click', () => {
78
+ const isMaximized = this.htmlPreviewShell?.classList.contains('is-maximized');
79
+ this.setHtmlPreviewMaximized(!isMaximized);
80
+ });
81
+ setDiagramActionButtonIcon(this.elements.htmlPreviewMaximizeButton, 'maximize');
82
+ }
46
83
  this.excalidrawEmbed = excalidrawEmbed;
47
84
  this.getDisplayName = getDisplayName;
48
85
  this.getSession = getSession;
@@ -91,14 +128,29 @@ export class WorkspacePreviewController {
91
128
  return source;
92
129
  }
93
130
 
131
+ setHtmlPreviewMaximized(maximized) {
132
+ const isMaximized = Boolean(maximized && this.htmlPreviewShell);
133
+ this.htmlPreviewShell?.classList.toggle('is-maximized', isMaximized);
134
+ globalThis.document?.body?.classList.toggle('html-preview-maximized-open', isMaximized);
135
+
136
+ const button = this.elements.htmlPreviewMaximizeButton;
137
+ if (button) {
138
+ setDiagramActionButtonIcon(button, isMaximized ? 'restore' : 'maximize');
139
+ button.title = isMaximized ? 'Restore HTML preview' : 'Maximize HTML preview';
140
+ button.setAttribute('aria-label', button.title);
141
+ }
142
+ }
143
+
94
144
  resetPreviewMode() {
145
+ this.setHtmlPreviewMaximized(false);
146
+ this.htmlPreviewShell = null;
95
147
  this.pdfPreview.cancel();
96
- this.elements.previewContainer?.classList?.remove('is-pdf-file-preview');
97
148
  this.elements.previewContent?.classList.remove('is-drawio-file-preview');
98
149
  this.elements.previewContent?.classList.remove('is-excalidraw-file-preview');
99
150
  this.elements.previewContent?.classList.remove('is-base-file-preview');
100
151
  this.elements.previewContent?.classList.remove('is-image-file-preview');
101
152
  this.elements.previewContent?.classList.remove('is-pdf-file-preview');
153
+ this.elements.previewContent?.classList.remove('is-html-file-preview');
102
154
  this.elements.previewContent?.classList.remove('is-mermaid-file-preview');
103
155
  this.elements.previewContent?.classList.remove('is-plantuml-file-preview');
104
156
  this.elements.previewContent?.classList.remove('is-structurizr-file-preview');
@@ -111,6 +163,7 @@ export class WorkspacePreviewController {
111
163
  const isBase = this.isBaseFile(filePath);
112
164
  const isImage = this.isImageFile(filePath);
113
165
  const isPdf = this.isPdfFile(filePath);
166
+ const isHtml = isHtmlFilePath(filePath);
114
167
  const isMarkdown = isMarkdownFilePath(filePath);
115
168
  const isMermaid = this.isMermaidFile(filePath);
116
169
  const isPlantUml = this.isPlantUmlFile(filePath);
@@ -121,9 +174,11 @@ export class WorkspacePreviewController {
121
174
  this.backlinksPanel.setDisplayMode?.(usesHeaderBacklinks ? 'header' : 'dock');
122
175
 
123
176
  this.elements.editorFindButton?.classList.toggle('hidden', !isMarkdown);
177
+ syncFormatDocumentButton(this.elements.editorFormatButton, filePath, isPlantUml);
124
178
  this.elements.markdownToolbar?.classList.toggle('hidden', !isMarkdown);
125
179
  this.elements.exportMenuGroup?.classList.toggle('hidden', !isMarkdown);
126
- this.elements.outlineToggle?.classList.toggle('hidden', isDiagramFile || isImage || isPdf || isBase);
180
+ this.elements.htmlPreviewMaximizeButton?.classList.toggle('hidden', !isHtml);
181
+ this.elements.outlineToggle?.classList.toggle('hidden', isDiagramFile || isImage || isPdf || isHtml || isBase);
127
182
  this.elements.previewContent?.classList.toggle('is-mermaid-file-preview', isMermaid);
128
183
  this.elements.previewContent?.classList.toggle('is-plantuml-file-preview', isPlantUml);
129
184
  this.elements.previewContent?.classList.toggle('is-structurizr-file-preview', isStructurizr);
@@ -133,7 +188,7 @@ export class WorkspacePreviewController {
133
188
  this.backlinksPanel.clear();
134
189
  }
135
190
 
136
- if ((isDrawio && drawioMode !== 'text') || isExcalidraw || isImage || isPdf || (isBase && preferPreviewForBase)) {
191
+ if ((isDrawio && drawioMode !== 'text') || isExcalidraw || isHtml || isImage || isPdf || (isBase && preferPreviewForBase)) {
137
192
  this.layoutController.setView('preview', { persist: false });
138
193
  this.outlineController.close();
139
194
  this.backlinksPanel.clear();
@@ -272,14 +327,12 @@ export class WorkspacePreviewController {
272
327
  this.drawioEmbed.detachForCommit();
273
328
  this.excalidrawEmbed.detachForCommit();
274
329
  this.resetPreviewMode();
275
- this.elements.previewContainer?.classList?.add('is-pdf-file-preview');
276
330
  previewElement.classList.add('is-pdf-file-preview');
277
331
  const renderHost = this.previewRenderer.ensureRenderHost();
278
332
  this.previewRenderer.normalizePreviewChildren(renderHost);
279
333
 
280
334
  if (renderHost) {
281
335
  this.pdfPreview.render({
282
- displayName: this.getDisplayName(filePath),
283
336
  filePath,
284
337
  renderHost,
285
338
  });
@@ -295,6 +348,68 @@ export class WorkspacePreviewController {
295
348
  this.schedulePreviewLayoutSyncCallback({ delayMs: 0 });
296
349
  }
297
350
 
351
+ renderHtmlFilePreview({ content = '' } = {}) {
352
+ const previewElement = this.elements.previewContent;
353
+ if (!previewElement) {
354
+ return;
355
+ }
356
+
357
+ const wasMaximized = this.htmlPreviewShell?.classList.contains('is-maximized') ?? false;
358
+ this.videoEmbed?.detachForCommit();
359
+ this.drawioEmbed.detachForCommit();
360
+ this.excalidrawEmbed.detachForCommit();
361
+ this.resetPreviewMode();
362
+ previewElement.classList.add('is-html-file-preview');
363
+ const renderHost = this.previewRenderer.ensureRenderHost();
364
+ this.previewRenderer.normalizePreviewChildren(renderHost);
365
+
366
+ const source = String(content ?? '');
367
+ const iframe = document.createElement('iframe');
368
+ iframe.className = 'html-file-preview-frame';
369
+ iframe.title = 'HTML preview';
370
+ iframe.referrerPolicy = 'no-referrer';
371
+ iframe.setAttribute('allow', "camera 'none'; microphone 'none'; geolocation 'none'; clipboard-read 'none'; clipboard-write 'none'");
372
+ iframe.setAttribute('sandbox', '');
373
+ // ponytail: full iframe replacement resets script consent whenever the content changes.
374
+ iframe.srcdoc = createHtmlPreviewDocument(source);
375
+
376
+ const shell = document.createElement('div');
377
+ shell.className = 'html-file-preview-shell';
378
+
379
+ if (hasHtmlScripts(source)) {
380
+ const scriptGate = document.createElement('div');
381
+ scriptGate.className = 'html-file-preview-script-gate';
382
+ scriptGate.textContent = 'Scripts are disabled by default. Run them only if you trust this HTML file.';
383
+
384
+ const runScriptsButton = document.createElement('button');
385
+ runScriptsButton.type = 'button';
386
+ runScriptsButton.className = 'ui-button ui-button--secondary ui-button--compact';
387
+ runScriptsButton.textContent = 'Run scripts';
388
+ runScriptsButton.addEventListener('click', () => {
389
+ iframe.setAttribute('sandbox', 'allow-scripts');
390
+ iframe.srcdoc = createHtmlPreviewDocument(source, true);
391
+ scriptGate.remove();
392
+ });
393
+ scriptGate.append(runScriptsButton);
394
+ shell.append(scriptGate);
395
+ }
396
+ shell.append(iframe);
397
+ this.htmlPreviewShell = shell;
398
+ this.setHtmlPreviewMaximized(wasMaximized);
399
+
400
+ if (renderHost) {
401
+ renderHost.replaceChildren(shell);
402
+ renderHost.style.minHeight = '';
403
+ }
404
+
405
+ previewElement.dataset.renderPhase = 'ready';
406
+ this.outlineController.close();
407
+ this.backlinksPanel.clear();
408
+ this.scrollSyncController.setLargeDocumentMode(false);
409
+ this.scrollSyncController.invalidatePreviewBlocks();
410
+ this.schedulePreviewLayoutSyncCallback({ delayMs: 0 });
411
+ }
412
+
298
413
  async renderBaseFilePreview(filePath, { source = null } = {}) {
299
414
  const previewElement = this.elements.previewContent;
300
415
  if (!previewElement) {
@@ -285,8 +285,11 @@ export class WorkspaceRouteController {
285
285
  this.fileHistoryView?.hide?.();
286
286
  this.clearStaticPreviewDocument?.();
287
287
  this.syncMainChrome({ mode: 'editor' });
288
- await this.workspaceCoordinator.openFile(filePath, options);
288
+ const didOpen = await this.workspaceCoordinator.openFile(filePath, options);
289
289
  this.setSession(this.workspaceCoordinator.getSession());
290
+ if (didOpen === false) {
291
+ return false;
292
+ }
290
293
 
291
294
  if (shouldRevealInTree) {
292
295
  this.revealFileInTree(filePath, { clearSearch: true });
@@ -1,10 +1,2 @@
1
- pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
2
- Theme: GitHub Dark
3
- Description: Dark theme as seen on github.com
4
- Author: github.com
5
- Maintainer: @Hirse
6
- Updated: 2021-05-15
7
-
8
- Outdated base version: https://github.com/primer/github-syntax-dark
9
- Current colors taken from GitHub's CSS
10
- */.hljs{color:#c9d1d9;background:#0d1117}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#ff7b72}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#d2a8ff}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#79c0ff}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#a5d6ff}.hljs-built_in,.hljs-symbol{color:#ffa657}.hljs-code,.hljs-comment,.hljs-formula{color:#8b949e}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#7ee787}.hljs-subst{color:#c9d1d9}.hljs-section{color:#1f6feb;font-weight:700}.hljs-bullet{color:#f2cc60}.hljs-emphasis{color:#c9d1d9;font-style:italic}.hljs-strong{color:#c9d1d9;font-weight:700}.hljs-addition{color:#aff5b4;background-color:#033a16}.hljs-deletion{color:#ffdcd7;background-color:#67060c}
1
+ /* Highlight.js tokens mapped to CodeMirror's oneDarkHighlightStyle. */
2
+ pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#abb2bf;background:#282c34}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword{color:#c678dd}.hljs-attr,.hljs-attribute,.hljs-property,.hljs-variable{color:#e06c75}.hljs-title.function_,.hljs-title.function_.invoke__{color:#61afef}.hljs-name,.hljs-selector-tag,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-type{color:#e5c07b}.hljs-atom,.hljs-built_in,.hljs-bullet,.hljs-literal,.hljs-symbol,.hljs-variable.language_{color:#d19a66}.hljs-number{color:#e5c07b}.hljs-meta .hljs-string,.hljs-string{color:#98c379}.hljs-link,.hljs-operator,.hljs-regexp{color:#56b6c2}.hljs-code,.hljs-comment,.hljs-formula,.hljs-meta,.hljs-quote{color:#7d8799}.hljs-subst{color:#abb2bf}.hljs-section{color:#e06c75;font-weight:700}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-addition{color:#98c379}.hljs-deletion{color:#e06c75}
@@ -1,10 +1,2 @@
1
- pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
2
- Theme: GitHub
3
- Description: Light theme as seen on github.com
4
- Author: github.com
5
- Maintainer: @Hirse
6
- Updated: 2021-05-15
7
-
8
- Outdated base version: https://github.com/primer/github-syntax-light
9
- Current colors taken from GitHub's CSS
10
- */.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#005cc5}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-code,.hljs-comment,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0}
1
+ /* Highlight.js tokens mapped to CodeMirror's defaultHighlightStyle. */
2
+ pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#404740;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-selector-tag{color:#708}.hljs-atom,.hljs-bullet,.hljs-literal,.hljs-symbol,.hljs-variable.language_{color:#219}.hljs-number{color:#164}.hljs-meta .hljs-string,.hljs-regexp{color:#e40}.hljs-string{color:#a11}.hljs-title.function_,.hljs-title.function_.invoke__{color:#00f}.hljs-title.class_,.hljs-title.class_.inherited__{color:#167}.hljs-built_in,.hljs-name,.hljs-type{color:#085}.hljs-attr,.hljs-attribute,.hljs-property{color:#00c}.hljs-code,.hljs-comment,.hljs-formula,.hljs-quote{color:#940}.hljs-meta,.hljs-operator,.hljs-subst,.hljs-variable{color:#404740}.hljs-section{color:#00f;font-weight:700}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-addition{color:#164}.hljs-deletion{color:#a11}
@@ -0,0 +1,93 @@
1
+ Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ https://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -99,7 +99,13 @@ export class CollabMdAppShell {
99
99
  this.sessionLoadToken = 0;
100
100
  this.navigation = {
101
101
  getHashRoute,
102
- navigateToFile,
102
+ navigateToFile: (filePath, options = {}) => {
103
+ const { preserveFollow = false, ...routeOptions } = options;
104
+ if (!preserveFollow && filePath !== this.currentFilePath) {
105
+ this.stopFollowingUser();
106
+ }
107
+ navigateToFile(filePath, routeOptions);
108
+ },
103
109
  navigateToGitCommit,
104
110
  navigateToGitDiff,
105
111
  navigateToGitFileHistory,
@@ -162,6 +168,7 @@ export class CollabMdAppShell {
162
168
  this.chatToastController = new ToastController(this.elements.chatToastContainer);
163
169
  this.fileExplorer = new FileExplorerController({
164
170
  mobileBreakpointQuery: this.mobileBreakpointQuery,
171
+ onDirectoryExport: (directoryPath, format) => this.handleDirectoryExportRequest(directoryPath, format),
165
172
  onFileDelete: () => this.navigation.navigateToFile(null),
166
173
  onFileSelect: (filePath) => this.workspaceRouteController.handleFileSelection(filePath, {
167
174
  closeSidebarOnMobile: true,
@@ -202,7 +209,11 @@ export class CollabMdAppShell {
202
209
  });
203
210
  this.outlineController = new OutlineController({
204
211
  mobileBreakpointQuery: this.mobileBreakpointQuery,
205
- onNavigateToHeading: ({ sourceLine }) => {
212
+ onNavigateToHeading: ({ headingId, sourceLine }) => {
213
+ const heading = document.getElementById(headingId);
214
+ if (this.elements.previewContent?.contains(heading)) {
215
+ this.unfoldPreviewHeading(heading);
216
+ }
206
217
  if (!Number.isFinite(sourceLine)) return;
207
218
  this.scrollSyncController.suspendSync(250);
208
219
  this.session?.scrollToLine(sourceLine, 0);
@@ -247,6 +258,8 @@ export class CollabMdAppShell {
247
258
  this.drawioEmbed.reconcileEmbeds(this.elements.previewContent);
248
259
  this.excalidrawEmbed.reconcileEmbeds(this.elements.previewContent, { isLargeDocument: stats.isLargeDocument });
249
260
  this.scrollSyncController.setLargeDocumentMode(stats.isLargeDocument);
261
+ this.syncPreviewCodeCopyButtons();
262
+ this.syncPreviewHeadingFoldButtons();
250
263
  this.syncPreviewHeadingLinkButtons();
251
264
  this.applyPendingPreviewRouteAnchor({ behavior: 'auto', clearMissing: true });
252
265
  this.schedulePreviewLayoutSync({ delayMs: 0 });
@@ -288,8 +301,7 @@ export class CollabMdAppShell {
288
301
  scrollEditorToLine: (lineNumber, viewportRatio) => this.session?.scrollToLine(lineNumber, viewportRatio),
289
302
  });
290
303
  this.pdfPreview = new PdfPreviewController({
291
- outlineController: this.outlineController,
292
- previewContainer: this.elements.previewContainer,
304
+ getTheme: () => this.themeController.getTheme(),
293
305
  });
294
306
  this.backlinksPanel = new BacklinksPanel({
295
307
  headerPanelElement: this.elements.backlinksHeaderPanel,
@@ -304,6 +316,7 @@ export class CollabMdAppShell {
304
316
  getLocalUser: () => this.lobby.getLocalUser(),
305
317
  getTheme: () => this.themeController.getTheme(),
306
318
  onOpenFile: (filePath) => filePath && this.navigation.navigateToFile(filePath),
319
+ onStopFollowing: () => this.stopFollowingUser(),
307
320
  onToggleQuickSwitcher: () => {
308
321
  void this.toggleQuickSwitcher();
309
322
  },
@@ -493,8 +506,15 @@ export class CollabMdAppShell {
493
506
  this.clearInitialFileBootstrap();
494
507
  },
495
508
  onConnectionChange: (state) => this.handleConnectionChange(state),
496
- onContentChange: ({ isBase, isMermaid, isPlantUml, isStructurizrWorkspace }) => {
509
+ onContentChange: ({ isBase, isHtml, isMermaid, isPlantUml, isStructurizrWorkspace }) => {
497
510
  this.handleCommentEditorContentChange();
511
+ if (isHtml) {
512
+ this.workspacePreviewController.renderHtmlFilePreview({
513
+ content: this.session?.getText?.() ?? '',
514
+ });
515
+ return;
516
+ }
517
+
498
518
  if (isBase) {
499
519
  this.scheduleBaseFilePreview(this.currentFilePath, {
500
520
  source: this.session?.getText?.() ?? '',
@@ -517,10 +537,11 @@ export class CollabMdAppShell {
517
537
  },
518
538
  onCommentsChange: (threads) => this.handleCommentThreadsChange(threads),
519
539
  onFileAwarenessChange: (users) => this.updateFileAwareness(users),
520
- onFileOpenError: () => {
521
- this.showEditorLoadError();
540
+ onFileOpenError: ({ code } = {}) => {
541
+ const notFound = code === 'not-found';
542
+ this.showEditorLoadError(notFound ? 'File not found' : 'Failed to load file');
522
543
  this.syncWrapToggle();
523
- this.toastController.show('Failed to initialize editor');
544
+ this.toastController.show(notFound ? 'File not found' : 'Failed to initialize editor');
524
545
  },
525
546
  onFileOpenReady: () => {
526
547
  this.hideEditorLoading();
@@ -538,6 +559,7 @@ export class CollabMdAppShell {
538
559
  onRenderDrawioPreview: (filePath) => this.workspacePreviewController.renderDrawioFilePreview(filePath),
539
560
  onRenderBasePreview: (filePath) => this.renderBaseFilePreview(filePath),
540
561
  onRenderExcalidrawPreview: (filePath) => this.workspacePreviewController.renderExcalidrawFilePreview(filePath),
562
+ onRenderHtmlPreview: (options) => this.workspacePreviewController.renderHtmlFilePreview(options),
541
563
  onRenderImagePreview: (filePath) => this.workspacePreviewController.renderImageFilePreview(filePath),
542
564
  onRenderPdfPreview: (filePath) => this.workspacePreviewController.renderPdfFilePreview(filePath),
543
565
  onRenderStructurizrPreview: (filePath, options) => this.workspacePreviewController.renderStructurizrFilePreview(filePath, options),
@@ -554,6 +576,7 @@ export class CollabMdAppShell {
554
576
  });
555
577
  this.syncCommentChrome(filePath);
556
578
  this.syncFileHistoryButton({ filePath, mode: 'editor' });
579
+ this.syncReviewFileChangesButton({ filePath, mode: 'editor' });
557
580
  if (this.elements.activeFileName) {
558
581
  this.elements.activeFileName.textContent = displayName;
559
582
  }