@tequila99/githuman 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (377) hide show
  1. package/README.md +55 -0
  2. package/dist/cli/config.js +13 -1
  3. package/dist/cli/server-runtime.js +3 -0
  4. package/dist/server/app.js +36 -4
  5. package/dist/server/config/agents.js +2 -1
  6. package/dist/server/config/openapi.js +4 -0
  7. package/dist/server/db/migrations.js +55 -0
  8. package/dist/server/errors/notes.js +3 -0
  9. package/dist/server/hooks/notes/same-origin.js +37 -0
  10. package/dist/server/hooks/terminal/local-origin.js +2 -1
  11. package/dist/server/repositories/notes-catalog.repo.js +128 -0
  12. package/dist/server/repositories/notes.repo.js +402 -0
  13. package/dist/server/routes/notes.js +167 -0
  14. package/dist/server/routes/terminal.js +2 -1
  15. package/dist/server/services/git.service.js +15 -11
  16. package/dist/server/services/notes-identity.service.js +726 -0
  17. package/dist/server/services/notes-operations.service.js +298 -0
  18. package/dist/server/services/notes-watcher.service.js +44 -0
  19. package/dist/server/services/notes-writer.service.js +116 -0
  20. package/dist/server/services/notes.service.js +125 -0
  21. package/dist/server/services/terminal/backend.js +6 -3
  22. package/dist/server/services/terminal/channel.js +6 -3
  23. package/dist/server/services/terminal/registry.js +10 -5
  24. package/dist/server/services/terminal/session.js +10 -5
  25. package/dist/server/services/terminal/tokens.js +4 -2
  26. package/dist/server/utils/hash.js +4 -0
  27. package/dist/server/utils/note-asset-format.js +19 -0
  28. package/dist/server/utils/system-error.js +14 -0
  29. package/dist/shared/events/types.js +1 -0
  30. package/dist/shared/notes/asset-formats.js +39 -0
  31. package/dist/shared/notes/constants.js +2 -0
  32. package/dist/shared/notes/document.js +118 -0
  33. package/dist/shared/notes/identity.js +24 -0
  34. package/dist/shared/notes/links.js +44 -0
  35. package/dist/shared/notes/reference-path.js +54 -0
  36. package/dist/shared/notes/references.js +190 -0
  37. package/dist/shared/notes/schemas.js +164 -0
  38. package/dist/shared/notes/types.js +1 -0
  39. package/dist/shared/utils/heading-slug.js +7 -0
  40. package/dist/shared/utils/is-uuid.js +5 -0
  41. package/dist/shared/utils/safe-decode.js +9 -0
  42. package/dist/web/assets/AppPage-cl-3VfAl.js +1 -0
  43. package/dist/web/assets/ClosePopup-D2_HzWXW.js +1 -0
  44. package/dist/web/assets/CreateButton-pmDRGwna.js +93 -0
  45. package/dist/web/assets/CreateReviewFabButton-CcXWnmSN.js +1 -0
  46. package/dist/web/assets/{ErrorNotFound-CYOZg8yN.js → ErrorNotFound-Cq0wNQMu.js} +1 -1
  47. package/dist/web/assets/IndexPage-CmBmgu4A.js +1 -0
  48. package/dist/web/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  49. package/dist/web/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  50. package/dist/web/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  51. package/dist/web/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  52. package/dist/web/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  53. package/dist/web/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  54. package/dist/web/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  55. package/dist/web/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  56. package/dist/web/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  57. package/dist/web/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  58. package/dist/web/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  59. package/dist/web/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  60. package/dist/web/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  61. package/dist/web/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  62. package/dist/web/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  63. package/dist/web/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  64. package/dist/web/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  65. package/dist/web/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  66. package/dist/web/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  67. package/dist/web/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  68. package/dist/web/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  69. package/dist/web/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  70. package/dist/web/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  71. package/dist/web/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  72. package/dist/web/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  73. package/dist/web/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  74. package/dist/web/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  75. package/dist/web/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  76. package/dist/web/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  77. package/dist/web/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  78. package/dist/web/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  79. package/dist/web/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  80. package/dist/web/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  81. package/dist/web/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  82. package/dist/web/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  83. package/dist/web/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  84. package/dist/web/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  85. package/dist/web/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  86. package/dist/web/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  87. package/dist/web/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  88. package/dist/web/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  89. package/dist/web/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  90. package/dist/web/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  91. package/dist/web/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  92. package/dist/web/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  93. package/dist/web/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  94. package/dist/web/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  95. package/dist/web/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  96. package/dist/web/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  97. package/dist/web/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  98. package/dist/web/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  99. package/dist/web/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  100. package/dist/web/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  101. package/dist/web/assets/KaTeX_Size3-Regular-gV2CO0n9.woff2 +0 -0
  102. package/dist/web/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  103. package/dist/web/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  104. package/dist/web/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  105. package/dist/web/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  106. package/dist/web/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  107. package/dist/web/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  108. package/dist/web/assets/MainLayout-DM30ynlR.css +1 -0
  109. package/dist/web/assets/MainLayout-DOGoQ-1m.js +6 -0
  110. package/dist/web/assets/NoteVisualEditor-CClIKW0X.css +1 -0
  111. package/dist/web/assets/NoteVisualEditor-zjZr9aod.js +1056 -0
  112. package/dist/web/assets/NotesPage-C5VXA9Bb.css +1 -0
  113. package/dist/web/assets/NotesPage-Jeva3Jta.js +114 -0
  114. package/dist/web/assets/{PdfPreview-D3HwZ7pH.js → PdfPreview-CdgeqqEv.js} +1 -1
  115. package/dist/web/assets/QBtn-DoggJe1Q.js +1 -0
  116. package/dist/web/assets/QFab-DyUFgj0W.js +1 -0
  117. package/dist/web/assets/QForm-BiRkV9BY.js +4 -0
  118. package/dist/web/assets/QInput-DJgTh2Qy.js +1 -0
  119. package/dist/web/assets/QScrollArea-DfPW35JQ.js +1 -0
  120. package/dist/web/assets/QSelect-BpZ5KfWP.js +1 -0
  121. package/dist/web/assets/QSpace-BRLIXkHB.js +1 -0
  122. package/dist/web/assets/ReviewDetailPage-CpJPrSKO.js +1 -0
  123. package/dist/web/assets/ReviewsPage-BaxUZzUZ.js +1 -0
  124. package/dist/web/assets/{StatusSwitcher-DTD5inU1.css → StatusSwitcher-BCv_9MtI.css} +1 -1
  125. package/dist/web/assets/StatusSwitcher-D5UG_YWP.js +1 -0
  126. package/dist/web/assets/{TerminalView-B11UHZv3.css → TerminalView-C1jFlfLH.css} +1 -1
  127. package/dist/web/assets/TerminalView-DMJTXE-G.js +19 -0
  128. package/dist/web/assets/_baseMerge-BzZFQ6mI.js +1 -0
  129. package/dist/web/assets/{abnfDiagram-O67JEVCF-C5SYdl8k.js → abnfDiagram-O67JEVCF-CiOkMSRz.js} +1 -1
  130. package/dist/web/assets/agent-icon-Dx8WBYX_.js +1 -0
  131. package/dist/web/assets/agent-store-B1VK6S0D.js +1 -0
  132. package/dist/web/assets/apl-gfMMiTNf.js +1 -0
  133. package/dist/web/assets/app-info-store-D76h_OdJ.js +1 -0
  134. package/dist/web/assets/architecture-7GRP2DOG-Byc4Oz95.js +1 -0
  135. package/dist/web/assets/{architectureDiagram-NJMV4G6O-Bx8KGjS_.js → architectureDiagram-NJMV4G6O-BexHJffj.js} +1 -1
  136. package/dist/web/assets/asciiarmor-C_eisQCp.js +1 -0
  137. package/dist/web/assets/asn1-DCl_8MCW.js +1 -0
  138. package/dist/web/assets/asterisk-BEn0Cwpx.js +1 -0
  139. package/dist/web/assets/{blockDiagram-BEXU5L5S-B4ybhPir.js → blockDiagram-BEXU5L5S-CEyB_5a1.js} +1 -1
  140. package/dist/web/assets/brainfuck-D5EjA2JK.js +1 -0
  141. package/dist/web/assets/{c4Diagram-YGBWAQC7-D2Fzm9Zx.js → c4Diagram-YGBWAQC7-BRNWA7xI.js} +1 -1
  142. package/dist/web/assets/ccount-CcG1m-Yh.js +1 -0
  143. package/dist/web/assets/channel-DbRAFIx1.js +1 -0
  144. package/dist/web/assets/{chunk-3FUC2YCW-DLRX-HPs.js → chunk-3FUC2YCW-BcQR1JDF.js} +1 -1
  145. package/dist/web/assets/{chunk-5DYCD2WN-6HcgVbfR.js → chunk-5DYCD2WN-D6aQ1hFt.js} +1 -1
  146. package/dist/web/assets/{chunk-742MDFTN-CfTGkhlJ.js → chunk-742MDFTN-BRgrFtkf.js} +1 -1
  147. package/dist/web/assets/{chunk-7INBJB4K-COfv2qWf.js → chunk-7INBJB4K-3RBjXeq6.js} +1 -1
  148. package/dist/web/assets/{chunk-7M6MHVWA-D0FxecF4.js → chunk-7M6MHVWA-Malugc_N.js} +5 -5
  149. package/dist/web/assets/{chunk-7PRAP22T-DFjSoEy0.js → chunk-7PRAP22T-Bb3gaISA.js} +1 -1
  150. package/dist/web/assets/{chunk-GTNCS2PH-CGWGXDNO.js → chunk-GTNCS2PH-Cps7XhUC.js} +1 -1
  151. package/dist/web/assets/{chunk-GWA4HPMP-J0EaOPjD.js → chunk-GWA4HPMP-Bfp2Tg3_.js} +1 -1
  152. package/dist/web/assets/{chunk-MBY4JIJT-PzEUkWiy.js → chunk-MBY4JIJT-IfXbX1Ur.js} +1 -1
  153. package/dist/web/assets/{chunk-NETBCI7D-DHHOcLF0.js → chunk-NETBCI7D-r2fmahwk.js} +1 -1
  154. package/dist/web/assets/{chunk-O7XYJQB3-BHUId2wW.js → chunk-O7XYJQB3-sadsiWmA.js} +1 -1
  155. package/dist/web/assets/{chunk-UA2S7LBM-DXQ1DAj6.js → chunk-UA2S7LBM-DibfwtDn.js} +1 -1
  156. package/dist/web/assets/{chunk-WEXAMYUT-BMiibMha.js → chunk-WEXAMYUT-DBouMgEO.js} +1 -1
  157. package/dist/web/assets/{chunk-Z7XXMR3K-BcgKYeJS.js → chunk-Z7XXMR3K-fAHToON5.js} +1 -1
  158. package/dist/web/assets/{chunk-ZIGJFQKS-D6psU74o.js → chunk-ZIGJFQKS-CJG1UIHO.js} +1 -1
  159. package/dist/web/assets/{classDiagram-v2-NBCMYWYE-6IwOSgSE.js → classDiagram-v2-NBCMYWYE-CPHP5ynj.js} +4 -4
  160. package/dist/web/assets/clike-D_6L3tnO.js +1 -0
  161. package/dist/web/assets/clojure-BflJGmDX.js +1 -0
  162. package/dist/web/assets/cmake-84nbDH0I.js +1 -0
  163. package/dist/web/assets/cobol-DHLQUbN7.js +1 -0
  164. package/dist/web/assets/coffeescript-De_zI4J0.js +1 -0
  165. package/dist/web/assets/commonlisp-DgAKBe0r.js +1 -0
  166. package/dist/web/assets/core-Bumj8M77.js +12 -0
  167. package/dist/web/assets/crystal-Bsdphhtm.js +1 -0
  168. package/dist/web/assets/css-CnaYoQib.js +1 -0
  169. package/dist/web/assets/{cynefin-OW5HDTMX-C77WtKve.js → cynefin-OW5HDTMX-BU7_LYGR.js} +1 -1
  170. package/dist/web/assets/{cynefinDiagram-VND7K2PF-BvIp3Y9w.js → cynefinDiagram-VND7K2PF-BXFEy9Io.js} +1 -1
  171. package/dist/web/assets/cypher-p9eYesGn.js +1 -0
  172. package/dist/web/assets/d-DWkQyNnU.js +1 -0
  173. package/dist/web/assets/dagre-6A5THRUB-aKpdpQ18.js +4 -0
  174. package/dist/web/assets/{diagram-22UHCM2B-DQUkKx9q.js → diagram-22UHCM2B-ddbRgIQ9.js} +8 -8
  175. package/dist/web/assets/{diagram-3UASUU5V-CTzVKsCf.js → diagram-3UASUU5V-vNYy6WP_.js} +1 -1
  176. package/dist/web/assets/{diagram-ATOU4E4O--Z3AVUjn.js → diagram-ATOU4E4O-B9Z3zFfp.js} +1 -1
  177. package/dist/web/assets/{diagram-CDSNMT55-BA-cRZ39.js → diagram-CDSNMT55-D3TaDPXU.js} +1 -1
  178. package/dist/web/assets/{diagram-MLGK6HIB-Bx_zLrYg.js → diagram-MLGK6HIB-DOXcXm2Y.js} +1 -1
  179. package/dist/web/assets/{diagram-MPIPVDR6-CWKuh-e-.js → diagram-MPIPVDR6-B5E2J8pO.js} +1 -1
  180. package/dist/web/assets/diff-ChtP43wD.js +1 -0
  181. package/dist/web/assets/dist-3B0OaUZ-.js +1 -0
  182. package/dist/web/assets/dist-BFbA030x.js +1 -0
  183. package/dist/web/assets/dist-BGzvKGEu.js +1 -0
  184. package/dist/web/assets/dist-BX8UA0fl.js +11 -0
  185. package/dist/web/assets/dist-BXUopzfH.js +2 -0
  186. package/dist/web/assets/dist-BY24_62d.js +1 -0
  187. package/dist/web/assets/dist-C3sBgvRy.js +1 -0
  188. package/dist/web/assets/dist-C9STut2J.js +1 -0
  189. package/dist/web/assets/dist-C9cJQvJH.js +23 -0
  190. package/dist/web/assets/dist-CRoJr3t6.js +6 -0
  191. package/dist/web/assets/dist-CqGqStPp.js +1 -0
  192. package/dist/web/assets/dist-Cxd9qKh7.js +1 -0
  193. package/dist/web/assets/dist-D2Ce45aH.js +13 -0
  194. package/dist/web/assets/dist-D7Llw4iH.js +1 -0
  195. package/dist/web/assets/dist-DSPzgfNo.js +1 -0
  196. package/dist/web/assets/dist-DUt0feNB.js +1 -0
  197. package/dist/web/assets/dist-DZQ2IsS9.js +1 -0
  198. package/dist/web/assets/dist-DpKJcdvz.js +1 -0
  199. package/dist/web/assets/dist-DuZv0LJj.js +1 -0
  200. package/dist/web/assets/dist-Kd0W7Y_b.js +9 -0
  201. package/dist/web/assets/dist-LFPPEX39.js +1 -0
  202. package/dist/web/assets/dist-PDsGXJi3.js +1 -0
  203. package/dist/web/assets/dist-lC0EKTFH.js +1 -0
  204. package/dist/web/assets/dockerfile-DJkHQgkl.js +1 -0
  205. package/dist/web/assets/dtd-DTF72YNO.js +1 -0
  206. package/dist/web/assets/dylan-BCDoL_-p.js +1 -0
  207. package/dist/web/assets/ebnf-D4c0_ac3.js +1 -0
  208. package/dist/web/assets/{ebnfDiagram-ZINNZB2B-MyQLfQVI.js → ebnfDiagram-ZINNZB2B-D-OCB_ud.js} +1 -1
  209. package/dist/web/assets/ecl-BVIeWmwY.js +1 -0
  210. package/dist/web/assets/eiffel-BEjRio4Q.js +1 -0
  211. package/dist/web/assets/{elk-276RUBZZ-DBbqEAnd.js → elk-276RUBZZ-CzjP8RHy.js} +1 -1
  212. package/dist/web/assets/elm-Cshzl8qu.js +1 -0
  213. package/dist/web/assets/equal-arrays-GA_7ZCAb.js +1 -0
  214. package/dist/web/assets/{erDiagram-OPXOYQCR-CbRo_Rnk.js → erDiagram-OPXOYQCR-Clohps7p.js} +1 -1
  215. package/dist/web/assets/erlang-BV0c4Hdn.js +1 -0
  216. package/dist/web/assets/eventmodeling-NTZA5JFV-FWK4tnN_.js +1 -0
  217. package/dist/web/assets/factor-LKH5gN8L.js +1 -0
  218. package/dist/web/assets/fcl-ClOhbFR7.js +1 -0
  219. package/dist/web/assets/flowDiagram-KWPJA3E3-C10B5_6J.js +1 -0
  220. package/dist/web/assets/forth-D6RzAl64.js +1 -0
  221. package/dist/web/assets/fortran-Bt6PBEDR.js +1 -0
  222. package/dist/web/assets/{ganttDiagram-FUAMR5RP-D1gJBc1W.js → ganttDiagram-FUAMR5RP-ZWH4HYq5.js} +1 -1
  223. package/dist/web/assets/gas-BHEdbvp9.js +1 -0
  224. package/dist/web/assets/gherkin-oBAE_ms0.js +1 -0
  225. package/dist/web/assets/{gitGraph-4MIJSDKK-CIzz8UCs.js → gitGraph-4MIJSDKK-C3AfRnC8.js} +1 -1
  226. package/dist/web/assets/{gitGraphDiagram-X574FWY7-B5-RB5JZ.js → gitGraphDiagram-X574FWY7-BobkQARX.js} +1 -1
  227. package/dist/web/assets/graphlib-C64HifUL.js +1 -0
  228. package/dist/web/assets/groovy-CUpZ7dEl.js +1 -0
  229. package/dist/web/assets/haskell-BRsoo5mP.js +1 -0
  230. package/dist/web/assets/haxe-DjVOVvNP.js +1 -0
  231. package/dist/web/assets/http-CLVgA2GD.js +1 -0
  232. package/dist/web/assets/i18n-CC_rvfan.js +1 -0
  233. package/dist/web/assets/idl-BUZw3wgd.js +1 -0
  234. package/dist/web/assets/index-Ic8yFbJg.js +2 -0
  235. package/dist/web/assets/{info-A6RAGUB7-DF-JCGlS.js → info-A6RAGUB7-Dh_SAe09.js} +1 -1
  236. package/dist/web/assets/{infoDiagram-VRGFBTTK-z0Xepdo0.js → infoDiagram-VRGFBTTK-izDlhNTw.js} +1 -1
  237. package/dist/web/assets/{init-app-DAsY3Joz.js → init-app-C1a6BWWN.js} +1 -1
  238. package/dist/web/assets/{is-DssfAlMe.js → is-CE4jkrGQ.js} +1 -1
  239. package/dist/web/assets/isArrayLikeObject-BbaDyxId.js +1 -0
  240. package/dist/web/assets/{ishikawaDiagram-OU5B5YK6-UqXiqAoe.js → ishikawaDiagram-OU5B5YK6-BJ89XzVJ.js} +1 -1
  241. package/dist/web/assets/javascript-Bu8mWwtz.js +1 -0
  242. package/dist/web/assets/{journeyDiagram-ZHPQQLJL-CPGeWRg-.js → journeyDiagram-ZHPQQLJL-poV-f08K.js} +1 -1
  243. package/dist/web/assets/julia-CQfgDRfP.js +1 -0
  244. package/dist/web/assets/{kanban-definition-PNTS6WVX-CMq9WuD5.js → kanban-definition-PNTS6WVX-Cn3FEnH7.js} +1 -1
  245. package/dist/web/assets/{line-cZB9xcQk.js → line-bE9Mqcqy.js} +1 -1
  246. package/dist/web/assets/livescript-BXxG0Yva.js +1 -0
  247. package/dist/web/assets/lua-DPCEkfD_.js +1 -0
  248. package/dist/web/assets/markdown-D85iiL_9.js +15 -0
  249. package/dist/web/assets/mathematica-u8YMmbU0.js +1 -0
  250. package/dist/web/assets/mbox-BEMVcqjs.js +1 -0
  251. package/dist/web/assets/{mermaid-parser.core-D8h1T47v.js → mermaid-parser.core-Cua7H5pF.js} +3 -3
  252. package/dist/web/assets/{mermaid.core-CdpJws-B.js → mermaid.core-BMPOA8T-.js} +7 -7
  253. package/dist/web/assets/{mindmap-definition-NLK3R4M7-B01KHb5Z.js → mindmap-definition-NLK3R4M7-DaTGr8Fs.js} +1 -1
  254. package/dist/web/assets/mirc-C9zpzAZU.js +1 -0
  255. package/dist/web/assets/mllike-B45xgp2S.js +1 -0
  256. package/dist/web/assets/modelica-CqHI_q-D.js +1 -0
  257. package/dist/web/assets/mscgen-qgSLujhx.js +1 -0
  258. package/dist/web/assets/mumps-BSzj6Xyz.js +1 -0
  259. package/dist/web/assets/nginx-8H7HVH4w.js +1 -0
  260. package/dist/web/assets/nsis-viPvXFiq.js +1 -0
  261. package/dist/web/assets/ntriples-B9h1VB_g.js +1 -0
  262. package/dist/web/assets/octave-D2Q8cUp1.js +1 -0
  263. package/dist/web/assets/oz-BwTct_5T.js +1 -0
  264. package/dist/web/assets/{packet-AYTQ26CC-CagxQ791.js → packet-AYTQ26CC-DmLfghd9.js} +1 -1
  265. package/dist/web/assets/pascal-Dp_KdFgX.js +1 -0
  266. package/dist/web/assets/{pegDiagram-GJSIUBJH-amhZRgGf.js → pegDiagram-GJSIUBJH-CTlxXcbf.js} +1 -1
  267. package/dist/web/assets/perl-BkSkiI9m.js +1 -0
  268. package/dist/web/assets/{pie-WAS4IAKB-zv3udP2i.js → pie-WAS4IAKB-52oNsEtc.js} +1 -1
  269. package/dist/web/assets/{pieDiagram-5QR66LMP-CjPzT-fa.js → pieDiagram-5QR66LMP-CbJtB1te.js} +1 -1
  270. package/dist/web/assets/pig-AF4Hwhju.js +1 -0
  271. package/dist/web/assets/pinia-BlCzIRX-.js +1 -0
  272. package/dist/web/assets/powershell-BcIto6Sf.js +1 -0
  273. package/dist/web/assets/properties-C357ku5U.js +1 -0
  274. package/dist/web/assets/protobuf-D1ij_kNL.js +1 -0
  275. package/dist/web/assets/pug-3K-JMW4g.js +1 -0
  276. package/dist/web/assets/puppet-BZyAS7I4.js +1 -0
  277. package/dist/web/assets/purify.es--06brOip.js +3 -0
  278. package/dist/web/assets/python-B_1Jd8HM.js +1 -0
  279. package/dist/web/assets/q-B9NhS7L_.js +1 -0
  280. package/dist/web/assets/{quadrantDiagram-O4NWA36T-7YpPBn0t.js → quadrantDiagram-O4NWA36T-DCg-uD08.js} +1 -1
  281. package/dist/web/assets/r-CxDmU1I4.js +1 -0
  282. package/dist/web/assets/{radar-RG4KPBEZ-DZ-nSYpA.js → radar-RG4KPBEZ-9uA3AOZR.js} +1 -1
  283. package/dist/web/assets/{railroad-74A4TZTK-CoylUO-u.js → railroad-74A4TZTK-BPxQfpxv.js} +1 -1
  284. package/dist/web/assets/railroad-abnf-HS5TGJTU-CPVHNg05.js +1 -0
  285. package/dist/web/assets/railroad-ebnf-LZEXJU2U-DAjTaOUg.js +1 -0
  286. package/dist/web/assets/railroad-peg-WCYAUIDC-DkxyKsj4.js +1 -0
  287. package/dist/web/assets/{railroadDiagram-XR7U4H2S-DlHZky0v.js → railroadDiagram-XR7U4H2S-CwBNr6fr.js} +1 -1
  288. package/dist/web/assets/{requirementDiagram-PLB6GJNP-Dn9whLhB.js → requirementDiagram-PLB6GJNP-BbtZt0St.js} +1 -1
  289. package/dist/web/assets/rpm-gpDK5sbt.js +1 -0
  290. package/dist/web/assets/ruby-ChfNwlCY.js +1 -0
  291. package/dist/web/assets/{safe-storage-B3bJArYP.js → safe-storage-Bn-sHAYw.js} +1 -1
  292. package/dist/web/assets/{sankeyDiagram-IPEJSGJF-jIf4UAnN.js → sankeyDiagram-IPEJSGJF-DRWdMnFl.js} +1 -1
  293. package/dist/web/assets/sas-C2OyD2Y6.js +1 -0
  294. package/dist/web/assets/scheme-D9qYN0V5.js +1 -0
  295. package/dist/web/assets/{sequenceDiagram-PO4LG4MO-CJahxeyg.js → sequenceDiagram-PO4LG4MO-C4tWeWpt.js} +1 -1
  296. package/dist/web/assets/shell-DwuoZtxw.js +1 -0
  297. package/dist/web/assets/sieve-tLWDfEkZ.js +1 -0
  298. package/dist/web/assets/simple-mode-DXiLM1-G.js +1 -0
  299. package/dist/web/assets/smalltalk-BLp5-jwC.js +1 -0
  300. package/dist/web/assets/solr-B78wSQJQ.js +1 -0
  301. package/dist/web/assets/sparql-Dz-mlCAC.js +1 -0
  302. package/dist/web/assets/spreadsheet-CTIncYxj.js +1 -0
  303. package/dist/web/assets/sql-DuQMFDvy.js +1 -0
  304. package/dist/web/assets/{stateDiagram-v2-GCMORJYK-DArbI5q3.js → stateDiagram-v2-GCMORJYK-pE0T1U5E.js} +2 -2
  305. package/dist/web/assets/stex-DNzd62Q_.js +1 -0
  306. package/dist/web/assets/stylus-BOVgKnng.js +1 -0
  307. package/dist/web/assets/swift-DKB6_1j6.js +1 -0
  308. package/dist/web/assets/{swimlanes-2SLR337P-wyJPqm8c.js → swimlanes-2SLR337P-DKky6E3p.js} +1 -1
  309. package/dist/web/assets/swimlanesDiagram-TC7HE7FX-CPhibEqM.js +8 -0
  310. package/dist/web/assets/tcl-BGfruO1u.js +1 -0
  311. package/dist/web/assets/textile-C4jVoHG1.js +1 -0
  312. package/dist/web/assets/theme-B-g7wQEs.js +1 -0
  313. package/dist/web/assets/tiddlywiki-VlUiK86J.js +1 -0
  314. package/dist/web/assets/tiki-AK6FwT8q.js +1 -0
  315. package/dist/web/assets/{timeline-definition-EJHVYXUP-Bdh9ma4o.js → timeline-definition-EJHVYXUP-CsRzcMLr.js} +1 -1
  316. package/dist/web/assets/toml-BPTmHmyx.js +1 -0
  317. package/dist/web/assets/{treeView-Q6P3EWNA-CEiXTwqS.js → treeView-Q6P3EWNA-CQYqoPG3.js} +1 -1
  318. package/dist/web/assets/{treemap-WGGIJYW6-am0aIfU-.js → treemap-WGGIJYW6-BzFw4gFs.js} +1 -1
  319. package/dist/web/assets/troff-C2dAgh7P.js +1 -0
  320. package/dist/web/assets/ttcn-PPSTk1ow.js +1 -0
  321. package/dist/web/assets/ttcn-cfg-2b4Gb5sE.js +1 -0
  322. package/dist/web/assets/turtle-Cx3rYX2g.js +1 -0
  323. package/dist/web/assets/{use-app-theme-FYzHIigd.js → use-app-theme-9qFZUBqz.js} +1 -1
  324. package/dist/web/assets/use-dark-BHObfh0O.js +1 -0
  325. package/dist/web/assets/use-panel-width-Dyh49bod.js +1 -0
  326. package/dist/web/assets/use-router-link-BGc0noIO.js +1 -0
  327. package/dist/web/assets/use-server-events-24_soFuj.js +1 -0
  328. package/dist/web/assets/use-virtual-scroll-BSXYZjZ5.js +1 -0
  329. package/dist/web/assets/{usecaseDiagram-POWQR4AR-r3Qf5Bj-.js → usecaseDiagram-POWQR4AR-IMfiBw6h.js} +1 -1
  330. package/dist/web/assets/vb-BthdM_4N.js +1 -0
  331. package/dist/web/assets/vbscript-D9f6rSsU.js +1 -0
  332. package/dist/web/assets/velocity-CqftRsjg.js +1 -0
  333. package/dist/web/assets/{vennDiagram-UO4OBE2U-eOWNPvLI.js → vennDiagram-UO4OBE2U-JKdzpNy2.js} +1 -1
  334. package/dist/web/assets/verilog-CjI9Y6RI.js +1 -0
  335. package/dist/web/assets/vhdl-kS471soi.js +1 -0
  336. package/dist/web/assets/{wardley-WFR3VGLG-BdipY77V.js → wardley-WFR3VGLG-B9Yiwlp8.js} +1 -1
  337. package/dist/web/assets/{wardleyDiagram-VNRHLVJA-sFpl0u9C.js → wardleyDiagram-VNRHLVJA-BVoc2hGS.js} +1 -1
  338. package/dist/web/assets/webidl-D5jiJvOU.js +1 -0
  339. package/dist/web/assets/xquery-BKJx4mf9.js +1 -0
  340. package/dist/web/assets/{xychartDiagram-PMCCYNJV-CtLqW--F.js → xychartDiagram-PMCCYNJV-B_XV1aim.js} +1 -1
  341. package/dist/web/assets/yacas-CXXgtw0p.js +1 -0
  342. package/dist/web/assets/z80-Co3PbHdE.js +1 -0
  343. package/dist/web/index.html +6 -3
  344. package/package.json +8 -2
  345. package/dist/web/assets/AppPage-CiRB13sb.js +0 -93
  346. package/dist/web/assets/CreateReviewFabButton-DTvX9Psc.js +0 -1
  347. package/dist/web/assets/IndexPage-hI7bcJ6L.js +0 -1
  348. package/dist/web/assets/MainLayout-DCexR9_Y.css +0 -1
  349. package/dist/web/assets/MainLayout-baVxjyeL.js +0 -11
  350. package/dist/web/assets/QBtn-CzrOO1zA.js +0 -1
  351. package/dist/web/assets/QScrollArea-Cu8zdp0y.js +0 -1
  352. package/dist/web/assets/QSelect-DQ_RRYIL.js +0 -1
  353. package/dist/web/assets/QSpace-CEuZSBS2.js +0 -13
  354. package/dist/web/assets/ReviewDetailPage-CayB2dtb.js +0 -1
  355. package/dist/web/assets/ReviewsPage-DWfEVjWO.js +0 -1
  356. package/dist/web/assets/StatusSwitcher--zNcE2-Y.js +0 -1
  357. package/dist/web/assets/TerminalView-DvVbWk3f.js +0 -19
  358. package/dist/web/assets/agent-store-DX4gIEHa.js +0 -1
  359. package/dist/web/assets/app-info-store-Vy_Pq2yR.js +0 -1
  360. package/dist/web/assets/architecture-7GRP2DOG-Dpxe25D8.js +0 -1
  361. package/dist/web/assets/channel--0tdF_Sb.js +0 -1
  362. package/dist/web/assets/core-C37KF-j0.js +0 -12
  363. package/dist/web/assets/dagre-6A5THRUB-DN7jrLfY.js +0 -4
  364. package/dist/web/assets/eventmodeling-NTZA5JFV-DMla2cPF.js +0 -1
  365. package/dist/web/assets/flowDiagram-KWPJA3E3-Bas61_mX.js +0 -1
  366. package/dist/web/assets/graphlib-DS17s2tU.js +0 -1
  367. package/dist/web/assets/i18n-B1_G449i.js +0 -1
  368. package/dist/web/assets/index-DEwYKvIG.js +0 -2
  369. package/dist/web/assets/pinia-DWj71cM9.js +0 -1
  370. package/dist/web/assets/railroad-abnf-HS5TGJTU-C20Z1OCq.js +0 -1
  371. package/dist/web/assets/railroad-ebnf-LZEXJU2U-BltGHYDI.js +0 -1
  372. package/dist/web/assets/railroad-peg-WCYAUIDC-BT3QI-zw.js +0 -1
  373. package/dist/web/assets/swimlanesDiagram-TC7HE7FX-DgRybibH.js +0 -8
  374. package/dist/web/assets/theme-CFC7Mb_O.js +0 -1
  375. package/dist/web/assets/use-panel-width-e-yXva8i.js +0 -1
  376. package/dist/web/assets/use-server-events-znzHKZZx.js +0 -1
  377. package/dist/web/assets/use-virtual-scroll-CIwaJCUj.js +0 -1
@@ -42,15 +42,18 @@ export class TerminalRegistry {
42
42
  }
43
43
  get(id) {
44
44
  const entry = this.entries.get(id);
45
- if (!entry)
45
+ if (!entry) {
46
46
  throw new TerminalNotFoundError('Terminal session no longer exists.');
47
+ }
47
48
  return entry.session;
48
49
  }
49
50
  async create(cols, rows) {
50
- if (this.stopped)
51
+ if (this.stopped) {
51
52
  throw new TerminalNotFoundError('Terminal server is stopping.');
52
- if (this.entries.size + this.creating >= MAX_TERMINAL_SESSIONS)
53
+ }
54
+ if (this.entries.size + this.creating >= MAX_TERMINAL_SESSIONS) {
53
55
  throw new TerminalLimitError('The terminal limit has been reached.');
56
+ }
54
57
  this.creating++;
55
58
  try {
56
59
  const backend = await (this.options.backend ?? createBackend)(this.options.repositoryPath, cols, rows);
@@ -78,16 +81,18 @@ export class TerminalRegistry {
78
81
  }
79
82
  attach(id, subscriber) {
80
83
  const entry = this.entries.get(id);
81
- if (!entry)
84
+ if (!entry) {
82
85
  throw new TerminalNotFoundError('Terminal session no longer exists.');
86
+ }
83
87
  entry.subscribers.add(subscriber);
84
88
  entry.orphanedSince = null;
85
89
  entry.idleSince = null;
86
90
  }
87
91
  detach(subscriber) {
88
92
  for (const entry of this.entries.values()) {
89
- if (!entry.subscribers.delete(subscriber) || entry.subscribers.size)
93
+ if (!entry.subscribers.delete(subscriber) || entry.subscribers.size) {
90
94
  continue;
95
+ }
91
96
  entry.orphanedSince = this.now();
92
97
  entry.idleSince = entry.session.running === 'idle' ? this.now() : null;
93
98
  }
@@ -99,8 +99,9 @@ export class TerminalSession {
99
99
  let end = Math.min(data.length, offset + FRAME_PART_UNITS);
100
100
  if (end < data.length &&
101
101
  data.charCodeAt(end - 1) >= HIGH_SURROGATE_FIRST &&
102
- data.charCodeAt(end - 1) <= HIGH_SURROGATE_LAST)
102
+ data.charCodeAt(end - 1) <= HIGH_SURROGATE_LAST) {
103
103
  end--;
104
+ }
104
105
  const part = data.slice(offset, end);
105
106
  offset = end;
106
107
  const bytes = Buffer.byteLength(part);
@@ -131,8 +132,9 @@ export class TerminalSession {
131
132
  .catch(() => this.onExit())
132
133
  .finally(() => {
133
134
  this.pendingBytes -= bytes;
134
- if (!this.stopped && this.pendingBytes < QUEUE_RESUME_BYTES)
135
+ if (!this.stopped && this.pendingBytes < QUEUE_RESUME_BYTES) {
135
136
  this.updateFlow();
137
+ }
136
138
  });
137
139
  }
138
140
  }
@@ -167,8 +169,9 @@ export class TerminalSession {
167
169
  scrollback = Math.floor(scrollback / 2);
168
170
  data = this.serializer.serialize({ scrollback }) + this.tail.tail;
169
171
  }
170
- if (Buffer.byteLength(data) > TERMINAL_SNAPSHOT_BYTES)
172
+ if (Buffer.byteLength(data) > TERMINAL_SNAPSHOT_BYTES) {
171
173
  throw new TerminalError('Terminal snapshot exceeds its limit.');
174
+ }
172
175
  send({
173
176
  type: 'snapshot',
174
177
  terminalId: this.id,
@@ -186,8 +189,9 @@ export class TerminalSession {
186
189
  this.backend.write(data);
187
190
  }
188
191
  line(data) {
189
- if (this.backend.mode !== 'pipe')
192
+ if (this.backend.mode !== 'pipe') {
190
193
  throw new TerminalError('Line input requires limited mode.');
194
+ }
191
195
  this.output(data.replace(/\n/g, '\r\n') + '\r\n');
192
196
  this.backend.write(data + '\n');
193
197
  }
@@ -203,8 +207,9 @@ export class TerminalSession {
203
207
  this.flush();
204
208
  this.queue = this.queue
205
209
  .then(() => {
206
- if (this.stopped || (cols === this.cols && rows === this.rows))
210
+ if (this.stopped || (cols === this.cols && rows === this.rows)) {
207
211
  return undefined;
212
+ }
208
213
  this.backend.resize(cols, rows);
209
214
  this.terminal.resize(cols, rows);
210
215
  this.cols = cols;
@@ -10,8 +10,9 @@ export class TerminalTokens {
10
10
  }
11
11
  issue(origin) {
12
12
  this.prune();
13
- if (this.tokens.size >= MAX_TOKENS)
13
+ if (this.tokens.size >= MAX_TOKENS) {
14
14
  this.tokens.delete(this.tokens.keys().next().value ?? '');
15
+ }
15
16
  const token = randomBytes(32).toString('base64url');
16
17
  this.tokens.set(token, { origin, expires: this.now() + TERMINAL_TOKEN_MS });
17
18
  return token;
@@ -22,9 +23,10 @@ export class TerminalTokens {
22
23
  return !!info && info.expires > this.now() && info.origin === origin;
23
24
  }
24
25
  prune() {
25
- for (const [token, info] of this.tokens)
26
+ for (const [token, info] of this.tokens) {
26
27
  if (info.expires <= this.now())
27
28
  this.tokens.delete(token);
29
+ }
28
30
  }
29
31
  clear() {
30
32
  this.tokens.clear();
@@ -0,0 +1,4 @@
1
+ import { createHash } from 'node:crypto';
2
+ export function sha256Hex(data) {
3
+ return createHash('sha256').update(data).digest('hex');
4
+ }
@@ -0,0 +1,19 @@
1
+ import { fileTypeFromBuffer } from 'file-type';
2
+ import { NOTE_ASSET_FORMATS, SUPPORTED_NOTE_ASSETS } from "../../shared/notes/asset-formats.js";
3
+ import { BadRequestError } from "../errors/http.js";
4
+ export async function detectNoteAssetFormat(bytes) {
5
+ let detected;
6
+ try {
7
+ detected = await fileTypeFromBuffer(bytes);
8
+ }
9
+ catch (cause) {
10
+ throw new BadRequestError('Could not identify attachment format', { cause });
11
+ }
12
+ const format = detected &&
13
+ NOTE_ASSET_FORMATS.find(candidate => candidate.extension === detected.ext ||
14
+ candidate.aliases.some(alias => alias === detected.ext));
15
+ if (!format) {
16
+ throw new BadRequestError('Supported images: ' + SUPPORTED_NOTE_ASSETS);
17
+ }
18
+ return format;
19
+ }
@@ -0,0 +1,14 @@
1
+ export function hasErrorCode(error, ...codes) {
2
+ return (error !== null &&
3
+ typeof error === 'object' &&
4
+ 'code' in error &&
5
+ typeof error.code === 'string' &&
6
+ codes.includes(error.code));
7
+ }
8
+ export function isSystemError(error, code) {
9
+ return error instanceof Error && hasErrorCode(error, code);
10
+ }
11
+ // Git file reads treat a non-directory path component as a missing path.
12
+ export function isMissingPathError(error) {
13
+ return hasErrorCode(error, 'ENOENT', 'ENOTDIR');
14
+ }
@@ -10,5 +10,6 @@ export const SERVER_EVENT_TYPES = [
10
10
  'comment:created',
11
11
  'comment:updated',
12
12
  'comment:deleted',
13
+ 'notes:changed',
13
14
  'files:changed'
14
15
  ];
@@ -0,0 +1,39 @@
1
+ // Keep upload policy, response MIME types and asset identifiers in agreement.
2
+ export const NOTE_ASSET_FORMATS = [
3
+ // Animated PNG retains the same storage extension as existing PNG attachments.
4
+ {
5
+ extension: 'png',
6
+ mime: 'image/png',
7
+ label: 'PNG',
8
+ display: 'image',
9
+ aliases: ['apng']
10
+ },
11
+ {
12
+ extension: 'jpg',
13
+ mime: 'image/jpeg',
14
+ label: 'JPEG',
15
+ display: 'image',
16
+ aliases: []
17
+ },
18
+ {
19
+ extension: 'gif',
20
+ mime: 'image/gif',
21
+ label: 'GIF',
22
+ display: 'image',
23
+ aliases: []
24
+ },
25
+ {
26
+ extension: 'webp',
27
+ mime: 'image/webp',
28
+ label: 'WebP',
29
+ display: 'image',
30
+ aliases: []
31
+ }
32
+ ];
33
+ // Existing content hashes and extensions remain valid across server upgrades.
34
+ export const NOTE_ASSET_ID_PATTERN = `^[a-f0-9]{64}\\.(${NOTE_ASSET_FORMATS.map(format => format.extension).join('|')})$`;
35
+ // Error messages follow the same allowlist as upload validation.
36
+ export const SUPPORTED_NOTE_ASSETS = NOTE_ASSET_FORMATS.map(format => format.label).join(', ');
37
+ export function noteAssetFormat(extension) {
38
+ return NOTE_ASSET_FORMATS.find(format => format.extension === extension);
39
+ }
@@ -0,0 +1,2 @@
1
+ // Bound image uploads in both the browser and the multipart parser.
2
+ export const MAX_NOTE_ASSET_BYTES = 10_000_000;
@@ -0,0 +1,118 @@
1
+ import { isRecord } from "../utils/guards.js";
2
+ import { errorMessage } from "../utils/error-message.js";
3
+ import { isMap, isSeq, isScalar, parseDocument } from 'yaml';
4
+ export function splitNote(text) {
5
+ const bom = text.startsWith('\uFEFF') ? '\uFEFF' : '';
6
+ const source = text.slice(bom.length);
7
+ if (!/^---\r?\n/.test(source)) {
8
+ return {
9
+ head: bom,
10
+ body: source,
11
+ yaml: '',
12
+ eol: text.includes('\r\n') ? '\r\n' : '\n'
13
+ };
14
+ }
15
+ const match = source.match(/^---\r?\n([\s\S]*?)(?:^---[ \t]*(?:\r?\n|$))/m);
16
+ if (!match)
17
+ throw new Error('Unclosed YAML frontmatter');
18
+ return {
19
+ head: bom + match[0],
20
+ body: source.slice(match[0].length),
21
+ yaml: match[1] ?? '',
22
+ eol: match[0].includes('\r\n') ? '\r\n' : '\n'
23
+ };
24
+ }
25
+ export function noteMetadata(text) {
26
+ try {
27
+ const { doc } = parseNoteHeader(text);
28
+ const tags = doc.get('tags');
29
+ if (tags === undefined)
30
+ return { tags: [], error: null };
31
+ if (!isSeq(tags) ||
32
+ tags.items.some(item => !isScalar(item) || typeof item.value !== 'string')) {
33
+ throw new Error('tags must be a list of strings');
34
+ }
35
+ return {
36
+ tags: normalizeTags(tags.items.map(item => (isScalar(item) ? String(item.value) : ''))),
37
+ error: null
38
+ };
39
+ }
40
+ catch (error) {
41
+ return {
42
+ tags: [],
43
+ error: errorMessage(error)
44
+ };
45
+ }
46
+ }
47
+ export function normalizeTags(tags) {
48
+ return [...new Set(tags.map(tag => tag.trim()).filter(Boolean))];
49
+ }
50
+ export function setNoteTags(text, tags) {
51
+ const metadata = noteMetadata(text);
52
+ if (metadata.error)
53
+ throw new Error(metadata.error);
54
+ const next = normalizeTags(tags);
55
+ if (JSON.stringify(next) === JSON.stringify(metadata.tags))
56
+ return text;
57
+ const { parts, doc } = parseNoteHeader(text);
58
+ doc.set('tags', next);
59
+ return writeNoteHeader(text, parts, doc.toString());
60
+ }
61
+ function parseNoteHeader(text) {
62
+ const parts = splitNote(text);
63
+ const doc = parseDocument(parts.yaml);
64
+ if (doc.errors.length)
65
+ throw new Error(doc.errors[0]?.message);
66
+ if (doc.contents && !isMap(doc.contents)) {
67
+ throw new Error('Frontmatter must be a YAML mapping');
68
+ }
69
+ return { parts, doc };
70
+ }
71
+ export function noteProperties(text) {
72
+ const { doc } = parseNoteHeader(text);
73
+ if (!isMap(doc.contents))
74
+ return [];
75
+ const values = doc.toJS({ maxAliasCount: 100 });
76
+ if (!isRecord(values))
77
+ return [];
78
+ return doc.contents.items.map(item => {
79
+ if (!isScalar(item.key) || typeof item.key.value !== 'string') {
80
+ throw new Error('Property names must be strings');
81
+ }
82
+ const key = item.key.value;
83
+ return { key, value: values[key] };
84
+ });
85
+ }
86
+ function writeNoteHeader(text, parts, yaml) {
87
+ const bom = text.startsWith('\uFEFF') ? '\uFEFF' : '';
88
+ return (bom +
89
+ '---' +
90
+ parts.eol +
91
+ yaml.replace(/\n/g, parts.eol) +
92
+ '---' +
93
+ parts.eol +
94
+ parts.body);
95
+ }
96
+ export function setNoteProperty(text, key, value) {
97
+ if (!key.trim())
98
+ throw new Error('Property name must not be empty');
99
+ if (key === 'tags') {
100
+ if (!Array.isArray(value))
101
+ throw new Error('tags must be a list of strings');
102
+ return setNoteTags(text, value);
103
+ }
104
+ const { parts, doc } = parseNoteHeader(text);
105
+ const current = noteProperties(text).find(property => property.key === key);
106
+ if (current && JSON.stringify(current.value) === JSON.stringify(value)) {
107
+ return text;
108
+ }
109
+ doc.set(key, value);
110
+ return writeNoteHeader(text, parts, doc.toString());
111
+ }
112
+ export function removeNoteProperty(text, key) {
113
+ const { parts, doc } = parseNoteHeader(text);
114
+ if (!doc.has(key))
115
+ return text;
116
+ doc.delete(key);
117
+ return writeNoteHeader(text, parts, doc.toString());
118
+ }
@@ -0,0 +1,24 @@
1
+ import { isScalar, parseDocument } from 'yaml';
2
+ import { isUuid } from "../utils/is-uuid.js";
3
+ import { splitNote, setNoteProperty } from "./document.js";
4
+ export function noteIdentity(text) {
5
+ try {
6
+ const doc = parseDocument(splitNote(text).yaml);
7
+ const value = doc.get('githuman_id', true);
8
+ if (value === undefined)
9
+ return { id: null, warning: null };
10
+ if (isScalar(value) && isUuid(value.value)) {
11
+ return { id: value.value.toLowerCase(), warning: null };
12
+ }
13
+ return {
14
+ id: null,
15
+ warning: 'githuman_id must be a UUID. The catalog identity is unchanged.'
16
+ };
17
+ }
18
+ catch {
19
+ return { id: null, warning: null };
20
+ }
21
+ }
22
+ export function withNoteIdentity(text, id) {
23
+ return setNoteProperty(text, 'githuman_id', id);
24
+ }
@@ -0,0 +1,44 @@
1
+ export function noteLink(from, to) {
2
+ const base = from.split('/').slice(0, -1);
3
+ const target = to.split('/');
4
+ while (base.length && target.length && base[0] === target[0]) {
5
+ base.shift();
6
+ target.shift();
7
+ }
8
+ return [
9
+ ...base.map(() => '..'),
10
+ ...target.map(segment => encodeURIComponent(segment).replace(/[!'()*]/g, char => '%' + char.charCodeAt(0).toString(16)))
11
+ ].join('/');
12
+ }
13
+ export function resolveNoteLink(from, href) {
14
+ if (/^[a-z][a-z\d+.-]*:/i.test(href) || href.startsWith('//'))
15
+ return null;
16
+ if (href.startsWith('/') || href.includes('\\') || href.includes('?')) {
17
+ throw new Error('Invalid note link');
18
+ }
19
+ const [target = '', fragment = ''] = href.split('#');
20
+ const decoded = decodeURIComponent(target);
21
+ if (decoded.includes('\\') ||
22
+ decoded.includes('\0') ||
23
+ decoded.startsWith('/')) {
24
+ throw new Error('Invalid note link');
25
+ }
26
+ const parts = target ? from.split('/').slice(0, -1) : from.split('/');
27
+ for (const part of decoded.split('/')) {
28
+ if (!part || part === '.')
29
+ continue;
30
+ if (part === '..') {
31
+ if (!parts.length)
32
+ throw new Error('Link leaves the notes folder');
33
+ parts.pop();
34
+ }
35
+ else {
36
+ parts.push(part);
37
+ }
38
+ }
39
+ const path = parts.join('/');
40
+ if (!path.toLowerCase().endsWith('.md')) {
41
+ throw new Error('This link does not point to a Markdown note');
42
+ }
43
+ return { path, anchor: decodeURIComponent(fragment) };
44
+ }
@@ -0,0 +1,54 @@
1
+ export function localReference(from, href) {
2
+ if (/^[a-z][a-z\d+.-]*:/i.test(href) ||
3
+ href.startsWith('/') ||
4
+ href.includes('?')) {
5
+ return null;
6
+ }
7
+ const hash = href.indexOf('#');
8
+ const target = hash < 0 ? href : href.slice(0, hash);
9
+ const anchor = hash < 0 ? '' : href.slice(hash + 1);
10
+ try {
11
+ const decoded = decodeURIComponent(target);
12
+ if (decoded.startsWith('/') || /[\\\0]/.test(decoded))
13
+ return null;
14
+ const parts = target ? from.split('/').slice(0, -1) : from.split('/');
15
+ for (const part of decoded.split('/')) {
16
+ if (!part || part === '.')
17
+ continue;
18
+ if (part === '..') {
19
+ if (!parts.length)
20
+ return null;
21
+ parts.pop();
22
+ }
23
+ else {
24
+ parts.push(part);
25
+ }
26
+ }
27
+ return { path: parts.join('/'), anchor };
28
+ }
29
+ catch {
30
+ return null;
31
+ }
32
+ }
33
+ export function wikiReference(value, from, paths) {
34
+ const match = value.match(/^\[\[([^\]|]+)(?:\|([^\]]+))?\]\]$/);
35
+ if (!match)
36
+ return null;
37
+ const [name = '', anchor = ''] = match[1].split('#');
38
+ const target = /\.md$/i.test(name) ? name : name + '.md';
39
+ const local = localReference(from, target.split('/').map(encodeURIComponent).join('/'))?.path;
40
+ const candidates = paths.filter(path => path.split('/').at(-1) === target);
41
+ const path = local && paths.includes(local)
42
+ ? local
43
+ : paths.includes(target)
44
+ ? target
45
+ : candidates.length === 1
46
+ ? candidates[0]
47
+ : null;
48
+ return {
49
+ path,
50
+ anchor,
51
+ label: match[2] ?? name.replace(/\.md$/i, ''),
52
+ ambiguous: candidates.length > 1 && !path
53
+ };
54
+ }
@@ -0,0 +1,190 @@
1
+ import { localReference, wikiReference } from "./reference-path.js";
2
+ export { localReference, wikiReference } from "./reference-path.js";
3
+ import { fromMarkdown } from 'mdast-util-from-markdown';
4
+ import { isMap, isSeq, isScalar, parseDocument } from 'yaml';
5
+ import { splitNote } from "./document.js";
6
+ import { noteLink } from "./links.js";
7
+ import { safeDecodeURIComponent } from "../utils/safe-decode.js";
8
+ // The AST excludes code and HTML; this scanner locates only a parsed destination.
9
+ function destinationRange(source, definition) {
10
+ let depth = 0;
11
+ let cursor = source.startsWith('!') ? 1 : 0;
12
+ for (; cursor < source.length; cursor++) {
13
+ if (source[cursor] === '\\') {
14
+ cursor++;
15
+ continue;
16
+ }
17
+ if (source[cursor] === '[')
18
+ depth++;
19
+ if (source[cursor] === ']' && --depth === 0) {
20
+ cursor++;
21
+ break;
22
+ }
23
+ }
24
+ while (/\s/.test(source[cursor] ?? '') && cursor < source.length)
25
+ cursor++;
26
+ if (source[cursor] !== (definition ? ':' : '('))
27
+ return null;
28
+ cursor++;
29
+ while (cursor < source.length && /\s/.test(source[cursor]))
30
+ cursor++;
31
+ const angle = source[cursor] === '<';
32
+ if (angle)
33
+ cursor++;
34
+ const start = cursor;
35
+ depth = 0;
36
+ for (; cursor < source.length; cursor++) {
37
+ const char = source[cursor];
38
+ if (char === '\\') {
39
+ cursor++;
40
+ continue;
41
+ }
42
+ if (angle && char === '>')
43
+ break;
44
+ if (!angle) {
45
+ if (char === '(')
46
+ depth++;
47
+ if (char === ')') {
48
+ if (!depth)
49
+ break;
50
+ depth--;
51
+ }
52
+ if (/\s/.test(char))
53
+ break;
54
+ }
55
+ }
56
+ return cursor >= start ? [start, cursor] : null;
57
+ }
58
+ export function noteReferences(text) {
59
+ let parts;
60
+ try {
61
+ parts = splitNote(text);
62
+ }
63
+ catch {
64
+ return [];
65
+ }
66
+ const result = [];
67
+ const bodyOffset = text.length - parts.body.length;
68
+ const tree = fromMarkdown(parts.body);
69
+ const uses = new Map();
70
+ const definitions = new Map();
71
+ const visit = (node) => {
72
+ if (node.type === 'linkReference' || node.type === 'imageReference') {
73
+ const group = uses.get(node.identifier) ?? [];
74
+ group.push({
75
+ position: bodyOffset + (node.position?.start.offset ?? 0),
76
+ image: node.type === 'imageReference'
77
+ });
78
+ uses.set(node.identifier, group);
79
+ }
80
+ if (node.type === 'link' ||
81
+ node.type === 'image' ||
82
+ node.type === 'definition') {
83
+ const start = node.position?.start.offset;
84
+ const end = node.position?.end.offset;
85
+ if (start !== undefined && end !== undefined) {
86
+ const raw = parts.body.slice(start, end);
87
+ const range = destinationRange(raw, node.type === 'definition');
88
+ if (range) {
89
+ result.push({
90
+ href: node.url,
91
+ start: bodyOffset + start + range[0],
92
+ end: bodyOffset + start + range[1],
93
+ context: raw.slice(0, range[0]) + '<href>' + raw.slice(range[1]),
94
+ format: 'markdown',
95
+ image: node.type === 'image',
96
+ displayStarts: [bodyOffset + start]
97
+ });
98
+ }
99
+ if (range && node.type === 'definition') {
100
+ definitions.set(result[result.length - 1], node.identifier);
101
+ }
102
+ }
103
+ }
104
+ if ('children' in node)
105
+ for (const child of node.children)
106
+ visit(child);
107
+ };
108
+ visit(tree);
109
+ for (const [ref, identifier] of definitions) {
110
+ const references = uses.get(identifier) ?? [];
111
+ ref.displayStarts = references.map(use => use.position);
112
+ ref.image = references.length > 0 && references.every(use => use.image);
113
+ }
114
+ try {
115
+ const doc = parseDocument(parts.yaml);
116
+ const offset = text.indexOf(parts.yaml, text.startsWith('\uFEFF') ? 5 : 4);
117
+ if (doc.errors.length || !isMap(doc.contents))
118
+ return result;
119
+ const scalar = (value, key) => {
120
+ if (!isScalar(value) || typeof value.value !== 'string' || !value.range) {
121
+ return;
122
+ }
123
+ const wiki = value.value.startsWith('[[');
124
+ if (!wiki && !/\.md(?:#|$)/i.test(value.value))
125
+ return;
126
+ result.push({
127
+ href: value.value,
128
+ start: offset + value.range[0],
129
+ end: offset + value.range[1],
130
+ context: 'yaml:' + key,
131
+ format: wiki ? 'wiki' : 'yaml',
132
+ image: false,
133
+ displayStarts: [offset + value.range[0]]
134
+ });
135
+ };
136
+ for (const pair of doc.contents.items) {
137
+ if (!isScalar(pair.key) ||
138
+ pair.key.value === 'githuman_id' ||
139
+ pair.key.value === 'tags') {
140
+ continue;
141
+ }
142
+ const key = String(pair.key.value);
143
+ if (isSeq(pair.value)) {
144
+ for (const value of pair.value.items)
145
+ scalar(value, key);
146
+ }
147
+ else {
148
+ scalar(pair.value, key);
149
+ }
150
+ }
151
+ }
152
+ catch {
153
+ /* Invalid YAML must not prevent indexing the Markdown body. */
154
+ }
155
+ return result;
156
+ }
157
+ export function referenceTarget(ref, from, paths) {
158
+ if (ref.format === 'wiki') {
159
+ const wiki = wikiReference(ref.href, from, paths);
160
+ return wiki?.path
161
+ ? { path: wiki.path, anchor: encodeURIComponent(wiki.anchor) }
162
+ : null;
163
+ }
164
+ return localReference(from, ref.href);
165
+ }
166
+ export function rewriteReferences(text, changes) {
167
+ let result = text;
168
+ for (const change of [...changes].sort((a, b) => b.reference.start - a.reference.start)) {
169
+ const ref = change.reference;
170
+ const href = noteLink(change.from, change.target) +
171
+ (change.anchor ? '#' + change.anchor : '');
172
+ let replacement = href;
173
+ if (ref.format === 'wiki') {
174
+ const alias = ref.href.match(/\|([^\]]+)\]\]$/)?.[1];
175
+ replacement =
176
+ '[[' +
177
+ change.target.replace(/\.md$/i, '') +
178
+ (change.anchor ? '#' + safeDecodeURIComponent(change.anchor) : '') +
179
+ (alias ? '|' + alias : '') +
180
+ ']]';
181
+ }
182
+ if (ref.format !== 'markdown')
183
+ replacement = JSON.stringify(replacement);
184
+ result = result.slice(0, ref.start) + replacement + result.slice(ref.end);
185
+ }
186
+ return result;
187
+ }
188
+ export function sameReference(a, b) {
189
+ return a.href === b.href && a.context === b.context && a.format === b.format;
190
+ }