jj-plus 0.10.10

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 (404) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +102 -0
  3. package/assets/jj-plus-icon.png +0 -0
  4. package/dist/_virtual/_rolldown/runtime.cjs +23 -0
  5. package/dist/bin.cjs +112 -0
  6. package/dist/bin.cjs.map +1 -0
  7. package/dist/cli/options.cjs +376 -0
  8. package/dist/cli/options.cjs.map +1 -0
  9. package/dist/cli/timeline-json.cjs +29 -0
  10. package/dist/cli/timeline-json.cjs.map +1 -0
  11. package/dist/extension/blame-codelens.cjs +228 -0
  12. package/dist/extension/blame-codelens.cjs.map +1 -0
  13. package/dist/extension/command-runner.cjs +99 -0
  14. package/dist/extension/command-runner.cjs.map +1 -0
  15. package/dist/extension/constants.cjs +56 -0
  16. package/dist/extension/constants.cjs.map +1 -0
  17. package/dist/extension/editor-extra-features.cjs +464 -0
  18. package/dist/extension/editor-extra-features.cjs.map +1 -0
  19. package/dist/extension/history-adapters.cjs +702 -0
  20. package/dist/extension/history-adapters.cjs.map +1 -0
  21. package/dist/extension/index.cjs +657 -0
  22. package/dist/extension/index.cjs.map +1 -0
  23. package/dist/extension/repo-timeline-panel.cjs +402 -0
  24. package/dist/extension/repo-timeline-panel.cjs.map +1 -0
  25. package/dist/extension/resolve-file-path.cjs +16 -0
  26. package/dist/extension/resolve-file-path.cjs.map +1 -0
  27. package/dist/extension/revision-diff-nav.cjs +169 -0
  28. package/dist/extension/revision-diff-nav.cjs.map +1 -0
  29. package/dist/extension/settings.cjs +41 -0
  30. package/dist/extension/settings.cjs.map +1 -0
  31. package/dist/extension/timeline-at-line.cjs +72 -0
  32. package/dist/extension/timeline-at-line.cjs.map +1 -0
  33. package/dist/extension/timeline-panel.cjs +1113 -0
  34. package/dist/extension/timeline-panel.cjs.map +1 -0
  35. package/dist/extension/timeline-service.cjs +1154 -0
  36. package/dist/extension/timeline-service.cjs.map +1 -0
  37. package/dist/extension/uri-utils.cjs +75 -0
  38. package/dist/extension/uri-utils.cjs.map +1 -0
  39. package/dist/package.cjs +11 -0
  40. package/dist/package.cjs.map +1 -0
  41. package/dist/shared/blame.cjs +211 -0
  42. package/dist/shared/blame.cjs.map +1 -0
  43. package/dist/shared/diff-content-search.cjs +23 -0
  44. package/dist/shared/diff-content-search.cjs.map +1 -0
  45. package/dist/shared/diff-helpers.cjs +12 -0
  46. package/dist/shared/diff-helpers.cjs.map +1 -0
  47. package/dist/shared/diff-stats.cjs +129 -0
  48. package/dist/shared/diff-stats.cjs.map +1 -0
  49. package/dist/shared/file-oplog.cjs +82 -0
  50. package/dist/shared/file-oplog.cjs.map +1 -0
  51. package/dist/shared/history-helpers.cjs +257 -0
  52. package/dist/shared/history-helpers.cjs.map +1 -0
  53. package/dist/shared/history-search.cjs +85 -0
  54. package/dist/shared/history-search.cjs.map +1 -0
  55. package/dist/shared/jj-revset-suggestions.cjs +41 -0
  56. package/dist/shared/jj-revset-suggestions.cjs.map +1 -0
  57. package/dist/shared/line-history.cjs +181 -0
  58. package/dist/shared/line-history.cjs.map +1 -0
  59. package/dist/shared/list-file-revisions.cjs +36 -0
  60. package/dist/shared/list-file-revisions.cjs.map +1 -0
  61. package/dist/shared/non-textual-details.cjs +43 -0
  62. package/dist/shared/non-textual-details.cjs.map +1 -0
  63. package/dist/shared/resolve-file-path.cjs +14 -0
  64. package/dist/shared/resolve-file-path.cjs.map +1 -0
  65. package/dist/shared/revision-diff-availability.cjs +18 -0
  66. package/dist/shared/revision-diff-availability.cjs.map +1 -0
  67. package/dist/shared/revision-diff-pair.cjs +42 -0
  68. package/dist/shared/revision-diff-pair.cjs.map +1 -0
  69. package/dist/shared/revset.cjs +16 -0
  70. package/dist/shared/revset.cjs.map +1 -0
  71. package/dist/shared/timeline-model.cjs +29 -0
  72. package/dist/shared/timeline-model.cjs.map +1 -0
  73. package/dist/standalone/server.cjs +1733 -0
  74. package/dist/standalone/server.cjs.map +1 -0
  75. package/dist/webview/timeline-template.cjs +214 -0
  76. package/dist/webview/timeline-template.cjs.map +1 -0
  77. package/package.json +320 -0
  78. package/webview-dist/assets/worker-DuV13XDT.js +161 -0
  79. package/webview-dist/chunks/abap-CLvhMVsD.js +1 -0
  80. package/webview-dist/chunks/actionscript-3-Cs6JJXT5.js +1 -0
  81. package/webview-dist/chunks/ada-C5qYipkI.js +1 -0
  82. package/webview-dist/chunks/ahk-CA9gdOdF.js +1 -0
  83. package/webview-dist/chunks/ahk2-_6rzW9BS.js +1 -0
  84. package/webview-dist/chunks/andromeeda-vGVdxbeo.js +1 -0
  85. package/webview-dist/chunks/angular-html-DTpR04n4.js +1 -0
  86. package/webview-dist/chunks/angular-ts-BCtbMvbl.js +1 -0
  87. package/webview-dist/chunks/apache-U0d_L8uA.js +1 -0
  88. package/webview-dist/chunks/apex-KFGFyKwG.js +1 -0
  89. package/webview-dist/chunks/apl-BMZuN1Ql.js +1 -0
  90. package/webview-dist/chunks/applescript-CCn79oCD.js +1 -0
  91. package/webview-dist/chunks/ara-4CJ0cIlV.js +1 -0
  92. package/webview-dist/chunks/asciidoc-SCjQUq34.js +1 -0
  93. package/webview-dist/chunks/asm-Cmm7eHzH.js +1 -0
  94. package/webview-dist/chunks/astro-DrbV4Z7r.js +1 -0
  95. package/webview-dist/chunks/aurora-x-CDeNXAV0.js +1 -0
  96. package/webview-dist/chunks/awk-BWXHIvNe.js +1 -0
  97. package/webview-dist/chunks/ayu-dark-DluEY0Gj.js +1 -0
  98. package/webview-dist/chunks/ayu-light-C3h-C4tm.js +1 -0
  99. package/webview-dist/chunks/ayu-mirage-Bqwy1Gya.js +1 -0
  100. package/webview-dist/chunks/ballerina-B7ZEbQpA.js +1 -0
  101. package/webview-dist/chunks/bat-qdxAdBWQ.js +1 -0
  102. package/webview-dist/chunks/beancount-D-usSTwE.js +1 -0
  103. package/webview-dist/chunks/berry-DKpUyyne.js +1 -0
  104. package/webview-dist/chunks/bibtex-Ci_nEsc7.js +1 -0
  105. package/webview-dist/chunks/bicep-CUHmPFLl.js +1 -0
  106. package/webview-dist/chunks/bird2-CYIUgYqB.js +1 -0
  107. package/webview-dist/chunks/blade-oPV8S6rR.js +1 -0
  108. package/webview-dist/chunks/bsl-_VjlB9mv.js +1 -0
  109. package/webview-dist/chunks/c-DYf-3tob.js +1 -0
  110. package/webview-dist/chunks/c3-D0apG41V.js +1 -0
  111. package/webview-dist/chunks/cadence-CQ2zXKGN.js +1 -0
  112. package/webview-dist/chunks/cairo-DLTphjLi.js +1 -0
  113. package/webview-dist/chunks/catppuccin-frappe-C9Q5zVZY.js +1 -0
  114. package/webview-dist/chunks/catppuccin-latte-CtsyrtPq.js +1 -0
  115. package/webview-dist/chunks/catppuccin-macchiato-R8nAf1vR.js +1 -0
  116. package/webview-dist/chunks/catppuccin-mocha-DjuaAJKi.js +1 -0
  117. package/webview-dist/chunks/chapel-DY-WYB1D.js +1 -0
  118. package/webview-dist/chunks/clarity-CtfBBspg.js +1 -0
  119. package/webview-dist/chunks/clojure-DqKBuwfJ.js +1 -0
  120. package/webview-dist/chunks/cmake-Bj61d0ZC.js +1 -0
  121. package/webview-dist/chunks/cobol-DvdX_6CO.js +1 -0
  122. package/webview-dist/chunks/codeowners-C8r90Shi.js +1 -0
  123. package/webview-dist/chunks/codeql-oeQT6MSM.js +1 -0
  124. package/webview-dist/chunks/coffee-C1kO7jr_.js +1 -0
  125. package/webview-dist/chunks/common-lisp-Cv5bFMCO.js +1 -0
  126. package/webview-dist/chunks/coq-DuBRPxYg.js +1 -0
  127. package/webview-dist/chunks/cpp-CoSarUrI.js +1 -0
  128. package/webview-dist/chunks/crystal-SLJeZ5EP.js +1 -0
  129. package/webview-dist/chunks/csharp-oqKa8noW.js +1 -0
  130. package/webview-dist/chunks/css-cfScyrSP.js +1 -0
  131. package/webview-dist/chunks/csv-Dx-8-gkx.js +1 -0
  132. package/webview-dist/chunks/cue-CE9AQfxI.js +1 -0
  133. package/webview-dist/chunks/cypher-ClKdZ_lG.js +1 -0
  134. package/webview-dist/chunks/d-qD-0Kul2.js +1 -0
  135. package/webview-dist/chunks/dark-plus-Cs2F2srj.js +1 -0
  136. package/webview-dist/chunks/dart-CnvKMtbv.js +1 -0
  137. package/webview-dist/chunks/dax-BkyTk9wS.js +1 -0
  138. package/webview-dist/chunks/desktop-Dlh5hvp9.js +1 -0
  139. package/webview-dist/chunks/diff-woXpYk--.js +1 -0
  140. package/webview-dist/chunks/docker-IyjqRm3v.js +1 -0
  141. package/webview-dist/chunks/dotenv-_5a1GRtc.js +1 -0
  142. package/webview-dist/chunks/dracula-BHWKrbxM.js +1 -0
  143. package/webview-dist/chunks/dracula-soft-5eyTD99u.js +1 -0
  144. package/webview-dist/chunks/dream-maker-DW3nJb8Q.js +1 -0
  145. package/webview-dist/chunks/edge-lvBr3t3s.js +1 -0
  146. package/webview-dist/chunks/elixir-BLoPe0KG.js +1 -0
  147. package/webview-dist/chunks/elm-BveBINBn.js +1 -0
  148. package/webview-dist/chunks/emacs-lisp-c_oH4hRZ.js +1 -0
  149. package/webview-dist/chunks/erb-Bmf8z4ph.js +1 -0
  150. package/webview-dist/chunks/erlang-Cphh6RMH.js +1 -0
  151. package/webview-dist/chunks/everforest-dark-sB-x3p7T.js +1 -0
  152. package/webview-dist/chunks/everforest-light-Df2xbC6M.js +1 -0
  153. package/webview-dist/chunks/fennel-DQxkIbk2.js +1 -0
  154. package/webview-dist/chunks/fish-BJitypiv.js +1 -0
  155. package/webview-dist/chunks/fluent-C03EYrpw.js +1 -0
  156. package/webview-dist/chunks/fortran-fixed-form-DEKoE2YW.js +1 -0
  157. package/webview-dist/chunks/fortran-free-form-CYNrtFtB.js +1 -0
  158. package/webview-dist/chunks/fsharp-D13ZGOAj.js +1 -0
  159. package/webview-dist/chunks/gdresource-xMC7jr7x.js +1 -0
  160. package/webview-dist/chunks/gdscript-DYvRD3hg.js +1 -0
  161. package/webview-dist/chunks/gdshader-CBce3t8t.js +1 -0
  162. package/webview-dist/chunks/genie-CV2tkWYe.js +1 -0
  163. package/webview-dist/chunks/gherkin-DExj1W_8.js +1 -0
  164. package/webview-dist/chunks/git-commit-BSykSTBG.js +1 -0
  165. package/webview-dist/chunks/git-rebase-BBii7GBM.js +1 -0
  166. package/webview-dist/chunks/github-dark-C-LZuMrd.js +1 -0
  167. package/webview-dist/chunks/github-dark-default-DXG-b-1a.js +1 -0
  168. package/webview-dist/chunks/github-dark-dimmed-Bx1FflLF.js +1 -0
  169. package/webview-dist/chunks/github-dark-high-contrast-B_tTalzw.js +1 -0
  170. package/webview-dist/chunks/github-light-EUqPIrTm.js +1 -0
  171. package/webview-dist/chunks/github-light-default-BXViO-2h.js +1 -0
  172. package/webview-dist/chunks/github-light-high-contrast-B68TUdTA.js +1 -0
  173. package/webview-dist/chunks/gleam-CSRkHgEL.js +1 -0
  174. package/webview-dist/chunks/glimmer-js-CuCPna-X.js +1 -0
  175. package/webview-dist/chunks/glimmer-ts-DNAjZNDK.js +1 -0
  176. package/webview-dist/chunks/glsl-COQvRxdz.js +1 -0
  177. package/webview-dist/chunks/gn-ilITqXS6.js +1 -0
  178. package/webview-dist/chunks/gnuplot-7GGW24-e.js +1 -0
  179. package/webview-dist/chunks/go-rLFTqkRN.js +1 -0
  180. package/webview-dist/chunks/graphql-1cKCVreZ.js +1 -0
  181. package/webview-dist/chunks/groovy-CacY0gHj.js +1 -0
  182. package/webview-dist/chunks/gruvbox-dark-hard-C820rvS2.js +1 -0
  183. package/webview-dist/chunks/gruvbox-dark-medium-BPjhmG05.js +1 -0
  184. package/webview-dist/chunks/gruvbox-dark-soft-MrdJrrXF.js +1 -0
  185. package/webview-dist/chunks/gruvbox-light-hard-BC_s9l72.js +1 -0
  186. package/webview-dist/chunks/gruvbox-light-medium-BAWPOn9u.js +1 -0
  187. package/webview-dist/chunks/gruvbox-light-soft-BSMLrYjP.js +1 -0
  188. package/webview-dist/chunks/hack-7CXYxWGO.js +1 -0
  189. package/webview-dist/chunks/haml-CeE16iG9.js +1 -0
  190. package/webview-dist/chunks/handlebars-CLm7Miue.js +1 -0
  191. package/webview-dist/chunks/haskell-D8IpX4py.js +1 -0
  192. package/webview-dist/chunks/haxe-C8oCnwJJ.js +1 -0
  193. package/webview-dist/chunks/hcl-Dh228itO.js +1 -0
  194. package/webview-dist/chunks/hjson-CxZEssPk.js +1 -0
  195. package/webview-dist/chunks/hlsl-Cvrh5tZx.js +1 -0
  196. package/webview-dist/chunks/horizon-CE9ld1lL.js +1 -0
  197. package/webview-dist/chunks/horizon-bright-DSNQnXHK.js +1 -0
  198. package/webview-dist/chunks/houston-CsvMBhTu.js +1 -0
  199. package/webview-dist/chunks/html-EbCri-_j.js +1 -0
  200. package/webview-dist/chunks/html-derivative-DGcE2kQi.js +1 -0
  201. package/webview-dist/chunks/http-DpnqgCg2.js +1 -0
  202. package/webview-dist/chunks/hurl-B6NGpamo.js +1 -0
  203. package/webview-dist/chunks/hxml-Dcm88srW.js +1 -0
  204. package/webview-dist/chunks/hy-CZbG8q4J.js +1 -0
  205. package/webview-dist/chunks/imba-DsUTQ-LC.js +1 -0
  206. package/webview-dist/chunks/ini-B5eOa1yu.js +1 -0
  207. package/webview-dist/chunks/java-ZkUoUSJy.js +1 -0
  208. package/webview-dist/chunks/javascript-DLd0EIw7.js +1 -0
  209. package/webview-dist/chunks/jinja-WhIqNp3q.js +1 -0
  210. package/webview-dist/chunks/jison-CIn1t7S8.js +1 -0
  211. package/webview-dist/chunks/json-AHG_JuKN.js +1 -0
  212. package/webview-dist/chunks/json5-BR5RXkoi.js +1 -0
  213. package/webview-dist/chunks/jsonc-CYpm1nAK.js +1 -0
  214. package/webview-dist/chunks/jsonl-CmCQp5Yx.js +1 -0
  215. package/webview-dist/chunks/jsonnet-CJTPZ8u_.js +1 -0
  216. package/webview-dist/chunks/jssm-DXw9l8Rf.js +1 -0
  217. package/webview-dist/chunks/jsx-BLy2KGb2.js +1 -0
  218. package/webview-dist/chunks/julia-XrhdGMY0.js +1 -0
  219. package/webview-dist/chunks/just-CiO9rOBq.js +1 -0
  220. package/webview-dist/chunks/kanagawa-dragon-Bozd7klA.js +1 -0
  221. package/webview-dist/chunks/kanagawa-lotus-BmuOG9ZW.js +1 -0
  222. package/webview-dist/chunks/kanagawa-wave-BML5mF2J.js +1 -0
  223. package/webview-dist/chunks/kdl-CsD5j6eV.js +1 -0
  224. package/webview-dist/chunks/kotlin-DhhofPvG.js +1 -0
  225. package/webview-dist/chunks/kusto-C7mF5XQf.js +1 -0
  226. package/webview-dist/chunks/laserwave-C_8bwKvT.js +1 -0
  227. package/webview-dist/chunks/latex-4tqdYtbu.js +1 -0
  228. package/webview-dist/chunks/lean-CewbzKMR.js +1 -0
  229. package/webview-dist/chunks/less-DVTAwKKz.js +1 -0
  230. package/webview-dist/chunks/light-plus-DVQuIRkW.js +1 -0
  231. package/webview-dist/chunks/liquid-BiiWRCLG.js +1 -0
  232. package/webview-dist/chunks/llvm-DqHOMS-s.js +1 -0
  233. package/webview-dist/chunks/log-BNLmms1o.js +1 -0
  234. package/webview-dist/chunks/logo-Cluzi2Zq.js +1 -0
  235. package/webview-dist/chunks/lua-BPFdS2Mc.js +1 -0
  236. package/webview-dist/chunks/luau-C2pBCSgt.js +1 -0
  237. package/webview-dist/chunks/make-Dixweg8N.js +1 -0
  238. package/webview-dist/chunks/markdown-BYOwaDjH.js +1 -0
  239. package/webview-dist/chunks/marko-BLi1Yy1V.js +1 -0
  240. package/webview-dist/chunks/material-theme-Bm3Qr25_.js +1 -0
  241. package/webview-dist/chunks/material-theme-darker-2IIEA8gg.js +1 -0
  242. package/webview-dist/chunks/material-theme-lighter-uhdI0v04.js +1 -0
  243. package/webview-dist/chunks/material-theme-ocean-CHQ94UKr.js +1 -0
  244. package/webview-dist/chunks/material-theme-palenight-B5W6OYN7.js +1 -0
  245. package/webview-dist/chunks/matlab-D7qyCx1q.js +1 -0
  246. package/webview-dist/chunks/mdc-Dx-qyM1x.js +1 -0
  247. package/webview-dist/chunks/mdx-DQZ5AkYe.js +1 -0
  248. package/webview-dist/chunks/mermaid-BxpfTIzt.js +1 -0
  249. package/webview-dist/chunks/min-dark-BSWPekZh.js +1 -0
  250. package/webview-dist/chunks/min-light-DDpmG2fV.js +1 -0
  251. package/webview-dist/chunks/mipsasm-BMqwQI7S.js +1 -0
  252. package/webview-dist/chunks/mojo-fg40_ntQ.js +1 -0
  253. package/webview-dist/chunks/monokai-B_bV9PQ9.js +1 -0
  254. package/webview-dist/chunks/moonbit-DgjMoLWr.js +1 -0
  255. package/webview-dist/chunks/move-BYnGhZoM.js +1 -0
  256. package/webview-dist/chunks/narrat-_X_XdTYD.js +1 -0
  257. package/webview-dist/chunks/nextflow-BJtWHP5T.js +1 -0
  258. package/webview-dist/chunks/nextflow-groovy-DJMQeKeT.js +1 -0
  259. package/webview-dist/chunks/nginx-rnpjAIVq.js +1 -0
  260. package/webview-dist/chunks/night-owl-DhmEMT88.js +1 -0
  261. package/webview-dist/chunks/night-owl-light-eJ-hLW7d.js +1 -0
  262. package/webview-dist/chunks/nim-kKTJ2fIs.js +1 -0
  263. package/webview-dist/chunks/nix-IvuFDN5E.js +1 -0
  264. package/webview-dist/chunks/nord-Cb4Vim4T.js +1 -0
  265. package/webview-dist/chunks/nsis-CjNLYCLg.js +1 -0
  266. package/webview-dist/chunks/nushell-DHYfO66s.js +1 -0
  267. package/webview-dist/chunks/objective-c-D1A_Heim.js +1 -0
  268. package/webview-dist/chunks/objective-cpp-BsSzOQcm.js +1 -0
  269. package/webview-dist/chunks/ocaml-O90oeIOV.js +1 -0
  270. package/webview-dist/chunks/odin-B1RWQWA5.js +1 -0
  271. package/webview-dist/chunks/one-dark-pro-CLwyXe_n.js +1 -0
  272. package/webview-dist/chunks/one-light-D7Lr4KcI.js +1 -0
  273. package/webview-dist/chunks/openscad-BUDT5pXO.js +1 -0
  274. package/webview-dist/chunks/org-BGWCjkJX.js +1 -0
  275. package/webview-dist/chunks/pascal-4ZHwLPI5.js +1 -0
  276. package/webview-dist/chunks/perl-DEimDILQ.js +1 -0
  277. package/webview-dist/chunks/php-QnaNN--1.js +1 -0
  278. package/webview-dist/chunks/pierre-dark-CpLgRqie.js +1 -0
  279. package/webview-dist/chunks/pierre-dark-protanopia-deuteranopia-B35FxJx-.js +1 -0
  280. package/webview-dist/chunks/pierre-dark-soft-kZQmAZld.js +1 -0
  281. package/webview-dist/chunks/pierre-dark-tritanopia-CpjhbsIL.js +1 -0
  282. package/webview-dist/chunks/pierre-dark-vibrant-CpQYzh95.js +1 -0
  283. package/webview-dist/chunks/pierre-light-CoaEpmwp.js +1 -0
  284. package/webview-dist/chunks/pierre-light-protanopia-deuteranopia-0fSaH845.js +1 -0
  285. package/webview-dist/chunks/pierre-light-soft-lWLdNTOI.js +1 -0
  286. package/webview-dist/chunks/pierre-light-tritanopia-CEbqgOJL.js +1 -0
  287. package/webview-dist/chunks/pierre-light-vibrant-D80Fkn33.js +1 -0
  288. package/webview-dist/chunks/pkl-ot-7Btpt.js +1 -0
  289. package/webview-dist/chunks/plastic-DQwYfKfQ.js +1 -0
  290. package/webview-dist/chunks/plsql-DGHpHOYJ.js +1 -0
  291. package/webview-dist/chunks/po-BiJDBrnU.js +1 -0
  292. package/webview-dist/chunks/poimandres-DRFjx7u4.js +1 -0
  293. package/webview-dist/chunks/polar-C7UOKdEL.js +1 -0
  294. package/webview-dist/chunks/postcss-BXeXVLqQ.js +1 -0
  295. package/webview-dist/chunks/powerquery-DNMTfnFr.js +1 -0
  296. package/webview-dist/chunks/powershell-CCSX75yM.js +1 -0
  297. package/webview-dist/chunks/prisma-DMgNhnYS.js +1 -0
  298. package/webview-dist/chunks/prolog-iXnhIJG7.js +1 -0
  299. package/webview-dist/chunks/proto-DB4EqR-F.js +1 -0
  300. package/webview-dist/chunks/pug-D5rsKmMX.js +1 -0
  301. package/webview-dist/chunks/puppet-CDv2pdJW.js +1 -0
  302. package/webview-dist/chunks/purescript-9MfHhQsQ.js +1 -0
  303. package/webview-dist/chunks/python-gzcpVVnB.js +1 -0
  304. package/webview-dist/chunks/qml-wvbZb8UE.js +1 -0
  305. package/webview-dist/chunks/qmldir-DCQb3MpD.js +1 -0
  306. package/webview-dist/chunks/qss-Fe1Jh2GI.js +1 -0
  307. package/webview-dist/chunks/r-BNyBFaU1.js +1 -0
  308. package/webview-dist/chunks/racket-DcIDlBhZ.js +1 -0
  309. package/webview-dist/chunks/raku-B3gFvitq.js +1 -0
  310. package/webview-dist/chunks/razor-bKaHS6Kz.js +1 -0
  311. package/webview-dist/chunks/rbs-C0MpOrj4.js +1 -0
  312. package/webview-dist/chunks/red-DX1BQOs8.js +1 -0
  313. package/webview-dist/chunks/reg-CRGYupPL.js +1 -0
  314. package/webview-dist/chunks/regexp-B-mZuWUh.js +1 -0
  315. package/webview-dist/chunks/rel-BtDbiS_P.js +1 -0
  316. package/webview-dist/chunks/riscv-Ckw8ddFX.js +1 -0
  317. package/webview-dist/chunks/ron-VUp2lXgN.js +1 -0
  318. package/webview-dist/chunks/rose-pine-aMsaMD1D.js +1 -0
  319. package/webview-dist/chunks/rose-pine-dawn-8PwUyIlP.js +1 -0
  320. package/webview-dist/chunks/rose-pine-moon-DO-qXg-I.js +1 -0
  321. package/webview-dist/chunks/rosmsg-CAekHB0j.js +1 -0
  322. package/webview-dist/chunks/rst-Qq8ybXHe.js +1 -0
  323. package/webview-dist/chunks/ruby-U659LEwU.js +1 -0
  324. package/webview-dist/chunks/rust-Cfkwpbl8.js +1 -0
  325. package/webview-dist/chunks/sas-C4NtLApe.js +1 -0
  326. package/webview-dist/chunks/sass-DXrisJhu.js +1 -0
  327. package/webview-dist/chunks/scala-BiFt_7mu.js +1 -0
  328. package/webview-dist/chunks/scheme-DQCgrYNe.js +1 -0
  329. package/webview-dist/chunks/scss-KAaA4sHk.js +1 -0
  330. package/webview-dist/chunks/sdbl-bTVj8UrX.js +1 -0
  331. package/webview-dist/chunks/shaderlab-TOUzSsQk.js +1 -0
  332. package/webview-dist/chunks/shellscript-_7bOVsRC.js +1 -0
  333. package/webview-dist/chunks/shellsession-Bs_5k0qk.js +1 -0
  334. package/webview-dist/chunks/slack-dark-DnToyrRv.js +1 -0
  335. package/webview-dist/chunks/slack-ochin-B2OO5cIa.js +1 -0
  336. package/webview-dist/chunks/smalltalk-BHpQb5nM.js +1 -0
  337. package/webview-dist/chunks/smithy-Dgaz7aur.js +1 -0
  338. package/webview-dist/chunks/snazzy-light-4G7pJPwS.js +1 -0
  339. package/webview-dist/chunks/solarized-dark-UdsmMDCL.js +1 -0
  340. package/webview-dist/chunks/solarized-light-C1IUL_tW.js +1 -0
  341. package/webview-dist/chunks/solidity-Bj7E1mRn.js +1 -0
  342. package/webview-dist/chunks/soy-C5iuoFCh.js +1 -0
  343. package/webview-dist/chunks/sparql-D_iOobhT.js +1 -0
  344. package/webview-dist/chunks/splunk-BC2Px7Mm.js +1 -0
  345. package/webview-dist/chunks/sql-JX305rZh.js +1 -0
  346. package/webview-dist/chunks/ssh-config-BgfXC-Er.js +1 -0
  347. package/webview-dist/chunks/stata-2Rtik3TV.js +1 -0
  348. package/webview-dist/chunks/stylus-B6D30XZt.js +1 -0
  349. package/webview-dist/chunks/surrealql-IvpiLAIH.js +1 -0
  350. package/webview-dist/chunks/svelte-DeZcV_1u.js +1 -0
  351. package/webview-dist/chunks/swift-CyEgAFGc.js +1 -0
  352. package/webview-dist/chunks/synthwave-84-nFMaYfgc.js +1 -0
  353. package/webview-dist/chunks/system-verilog-Dh5ihWbf.js +1 -0
  354. package/webview-dist/chunks/systemd-BxMlprV5.js +1 -0
  355. package/webview-dist/chunks/talonscript-CohzipZa.js +1 -0
  356. package/webview-dist/chunks/tasl-DMoTqEGO.js +1 -0
  357. package/webview-dist/chunks/tcl-CZd0xW_V.js +1 -0
  358. package/webview-dist/chunks/templ-CcwjPXJr.js +1 -0
  359. package/webview-dist/chunks/terraform-DswuEJGm.js +1 -0
  360. package/webview-dist/chunks/tex-CZYHgHl8.js +1 -0
  361. package/webview-dist/chunks/tokyo-night-oM2G3aXe.js +1 -0
  362. package/webview-dist/chunks/toml-CcmNWLt0.js +1 -0
  363. package/webview-dist/chunks/ts-tags-DPINfEO_.js +1 -0
  364. package/webview-dist/chunks/tsv-sltzmVWM.js +1 -0
  365. package/webview-dist/chunks/tsx-Dq7pSIyE.js +1 -0
  366. package/webview-dist/chunks/turtle-ByJddavk.js +1 -0
  367. package/webview-dist/chunks/twig-DFpC8yDL.js +1 -0
  368. package/webview-dist/chunks/typescript-CN-guYmK.js +1 -0
  369. package/webview-dist/chunks/typespec-BRdr0IET.js +1 -0
  370. package/webview-dist/chunks/typst-hgW4q6mN.js +1 -0
  371. package/webview-dist/chunks/v-DBj4K9d_.js +1 -0
  372. package/webview-dist/chunks/vala-zf12oZj6.js +1 -0
  373. package/webview-dist/chunks/vb-DOwzaHZ0.js +1 -0
  374. package/webview-dist/chunks/verilog-B2gwz-sJ.js +1 -0
  375. package/webview-dist/chunks/vesper-DdrHHSXu.js +1 -0
  376. package/webview-dist/chunks/vhdl-BroJfC0k.js +1 -0
  377. package/webview-dist/chunks/viml-DvXPmvsu.js +1 -0
  378. package/webview-dist/chunks/vitesse-black-fwtXNY1n.js +1 -0
  379. package/webview-dist/chunks/vitesse-dark-BZCL-v6S.js +1 -0
  380. package/webview-dist/chunks/vitesse-light-VbXTXTou.js +1 -0
  381. package/webview-dist/chunks/vue-Dkz9ntel.js +1 -0
  382. package/webview-dist/chunks/vue-html-Dg8LQ5v3.js +1 -0
  383. package/webview-dist/chunks/vue-vine-CIEXICEN.js +1 -0
  384. package/webview-dist/chunks/vyper-CgoNMtux.js +1 -0
  385. package/webview-dist/chunks/wasm-BnjxR4X6.js +1 -0
  386. package/webview-dist/chunks/wasm-ByWQv1Qj.js +1 -0
  387. package/webview-dist/chunks/wenyan-C8pVoKbM.js +1 -0
  388. package/webview-dist/chunks/wgsl-BsKzXJz4.js +1 -0
  389. package/webview-dist/chunks/wikitext-ClFFjSW2.js +1 -0
  390. package/webview-dist/chunks/wit-DdvCle-K.js +1 -0
  391. package/webview-dist/chunks/wolfram-DLL8P-h_.js +1 -0
  392. package/webview-dist/chunks/worker-D52zl71O.js +1 -0
  393. package/webview-dist/chunks/worker-pool-lOjh8Q2A.js +1543 -0
  394. package/webview-dist/chunks/xml-X7YOen_c.js +1 -0
  395. package/webview-dist/chunks/xsl-h4d_Px-X.js +1 -0
  396. package/webview-dist/chunks/yaml-BRDpsfaj.js +1 -0
  397. package/webview-dist/chunks/zenscript-BnlCZFoB.js +1 -0
  398. package/webview-dist/chunks/zig-CMLA9XwU.js +1 -0
  399. package/webview-dist/index.html +18 -0
  400. package/webview-dist/pierre-worker-portable.js +13633 -0
  401. package/webview-dist/repo-timeline-app.js +7 -0
  402. package/webview-dist/repo-timeline.html +14 -0
  403. package/webview-dist/timeline-app.css +2 -0
  404. package/webview-dist/timeline-app.js +85 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.cjs","names":["promisify","execFile","__dirname","path","fileURLToPath","http","JJ_OP_LOG_TEMPLATE","filterFileOpLogPeek","parseJjOpLogOutput","getEntriesForSource","fsSync","fs","parseGitBranchNames","buildJjHistoryLogTemplate","parseJjHistoryLine","parseJjEvolutionSummaryEntries","parseJjSummaryChangedPaths","normalizeSnapshotOperationKey","computeDiffStats","buildNonTextualDetails","parseJjSummaryRenameLines","toJjRootFileFileset","os","spawn","resolvePreferredHistoryBackend","getGitHubRemoteBaseUrl"],"sources":["../../src/standalone/server.ts"],"sourcesContent":["import fsSync from 'node:fs';\nimport fs from 'node:fs/promises';\nimport http, { type IncomingMessage, type ServerResponse } from 'node:http';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { execFile, spawn } from 'node:child_process';\nimport { fileURLToPath } from 'node:url';\nimport { promisify } from 'node:util';\nimport packageJson from '../../package.json' with { type: 'json' };\nimport { getEntriesForSource } from '../shared/timeline-model.ts';\nimport {\n\tgetGitHubRemoteBaseUrl,\n\tnormalizeSnapshotOperationKey,\n\tparseGitBranchNames,\n\tparseJjEvolutionSummaryEntries,\n\tparseJjHistoryLine,\n\tparseJjSummaryChangedPaths,\n\tparseJjSummaryRenameLines,\n\tresolvePreferredHistoryBackend,\n\ttoJjRootFileFileset,\n\tbuildJjHistoryLogTemplate,\n} from '../shared/history-helpers.ts';\nimport { filterFileOpLogPeek, JJ_OP_LOG_TEMPLATE, parseJjOpLogOutput } from '../shared/file-oplog.ts';\nimport type {\n\tComparisonSource,\n\tDiffPreview,\n\tFileRevisionEntry,\n\tHistoryBackend,\n\tRangeOverviewItem,\n\tTimelineCommand,\n\tTimelineData,\n\tTimelineFixtureFile,\n\tTimelineInboundMessage,\n\tTimelinePreferences,\n} from '../shared/timeline-types.ts';\nimport { computeDiffStats } from '../shared/diff-stats.ts';\nimport { buildNonTextualDetails } from '../shared/non-textual-details.ts';\n\nconst execFileAsync = promisify(execFile);\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst rootDir = path.resolve(__dirname, '..', '..');\nconst distDir = path.join(rootDir, 'webview-dist');\nconst displayLocale = 'en-US';\nconst displayTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';\nconst monthFormatter = new Intl.DateTimeFormat(displayLocale, { month: 'long', timeZone: displayTimeZone });\nconst shortDateFormatter = new Intl.DateTimeFormat(displayLocale, {\n\tmonth: 'short',\n\tday: 'numeric',\n\tyear: 'numeric',\n\ttimeZone: displayTimeZone,\n});\nconst subtitleDateFormatter = new Intl.DateTimeFormat(displayLocale, {\n\tyear: 'numeric',\n\tmonth: 'numeric',\n\tday: 'numeric',\n\thour: 'numeric',\n\tminute: '2-digit',\n\tsecond: '2-digit',\n\thour12: true,\n\ttimeZone: displayTimeZone,\n});\nconst timelinePresets = { year: 365, '7d': 7, '30d': 30, '90d': 90, all: Number.POSITIVE_INFINITY };\nconst ignoredWorkspaceEntries = new Set(['.git', '.jj', 'node_modules', 'webview-dist', '.e2e-runtime']);\nconst distAssets = ['index.html', 'timeline-app.js', 'timeline-app.css', 'pierre-worker-portable.js'];\n\ntype RepoContext = {\n\tbackend: HistoryBackend;\n\trepoRoot: string;\n\tremoteBaseUrl?: string;\n};\n\ntype StandaloneRuntime = {\n\thandleCommand(command: TimelineCommand): Promise<TimelineInboundMessage[]>;\n};\n\ntype FileFixtureBuildArgs = {\n\tbackend: HistoryBackend;\n\trelativePath: string;\n\trepoRoot: string;\n\tremoteBaseUrl?: string;\n};\n\nexport async function startStandaloneTimelineServer(args: {\n\tworkspacePath: string;\n\tfilePath: string;\n\topenBrowser?: boolean;\n\tport?: number;\n\tverbose?: boolean;\n}): Promise<{ url: string; close(): Promise<void> }> {\n\tawait ensureDistReady();\n\n\tconst runtime = await createStandaloneRuntime({\n\t\tworkspacePath: args.workspacePath,\n\t\tfilePath: args.filePath,\n\t});\n\tconst server = http.createServer((request, response) => {\n\t\tvoid handleRequest({ request, response, runtime, verbose: args.verbose === true });\n\t});\n\n\tawait new Promise<void>((resolve, reject) => {\n\t\tserver.once('error', reject);\n\t\tserver.listen(args.port || 0, '127.0.0.1', () => {\n\t\t\tserver.off('error', reject);\n\t\t\tresolve();\n\t\t});\n\t});\n\n\tconst address = server.address();\n\tconst actualPort = typeof address === 'object' && address ? address.port : args.port || 0;\n\tconst url = `http://127.0.0.1:${actualPort}/?standalone=1`;\n\n\tif (args.openBrowser !== false) {\n\t\ttry {\n\t\t\tawait openTarget(url);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tprocess.stderr.write(`Failed to open the browser automatically: ${message}\\n`);\n\t\t}\n\t}\n\n\treturn {\n\t\turl,\n\t\tasync close() {\n\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\tserver.close((error) => {\n\t\t\t\t\tif (error) {\n\t\t\t\t\t\treject(error);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tresolve();\n\t\t\t\t});\n\t\t\t});\n\t\t},\n\t};\n}\n\nasync function createStandaloneRuntime(args: { workspacePath: string; filePath: string }): Promise<StandaloneRuntime> {\n\tconst repoContext = await resolveRepoContext(args.workspacePath);\n\tconst absoluteFilePath = path.resolve(args.filePath);\n\tconst relativePath = path.relative(repoContext.repoRoot, absoluteFilePath);\n\tif (!relativePath || relativePath.startsWith('..')) {\n\t\tthrow new Error(`The file must be inside the repository root: ${repoContext.repoRoot}`);\n\t}\n\n\tconst preferencesByPath = new Map<string, Partial<TimelinePreferences>>();\n\tconst fileCache = new Map<string, TimelineFixtureFile>();\n\tconst rangeOverviewCache = new Map<string, RangeOverviewItem[]>();\n\tlet activeRelativePath = normalizePath(relativePath);\n\n\treturn {\n\t\tasync handleCommand(command) {\n\t\t\tswitch (command.command) {\n\t\t\t\tcase 'ready':\n\t\t\t\t\treturn emitTimeline();\n\t\t\t\tcase 'refresh':\n\t\t\t\t\tfileCache.delete(activeRelativePath);\n\t\t\t\t\tclearRangeOverviewCache(activeRelativePath);\n\t\t\t\t\treturn emitTimeline();\n\t\t\t\tcase 'switch-file': {\n\t\t\t\t\tactiveRelativePath = normalizePath(command.relativePath);\n\t\t\t\t\tawait getActiveFileFixture();\n\t\t\t\t\treturn emitTimeline();\n\t\t\t\t}\n\t\t\t\tcase 'persist-state':\n\t\t\t\t\tpreferencesByPath.set(activeRelativePath, extractPersistedPreferences(command));\n\t\t\t\t\treturn [];\n\t\t\t\tcase 'select-entry': {\n\t\t\t\t\tconst fileFixture = await getActiveFileFixture();\n\t\t\t\t\treturn [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'diff-preview',\n\t\t\t\t\t\t\tpayload: getFixturePreview({\n\t\t\t\t\t\t\t\tfileFixture,\n\t\t\t\t\t\t\t\tfromIndex: command.fromIndex,\n\t\t\t\t\t\t\t\ttoIndex: command.toIndex,\n\t\t\t\t\t\t\t\tcomparisonSource: command.comparisonSource,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t\tcase 'load-range-overview': {\n\t\t\t\t\tconst fileFixture = await getActiveFileFixture();\n\t\t\t\t\tconst normalizedFromIndex = Math.max(0, Math.min(command.fromIndex, command.toIndex));\n\t\t\t\t\tconst normalizedToIndex = Math.max(normalizedFromIndex, Math.max(command.fromIndex, command.toIndex));\n\t\t\t\t\tconst comparisonSource = command.comparisonSource === 'snapshot' ? 'snapshot' : 'revision';\n\t\t\t\t\tconst selectedEntryIndexes = command.selectedEntryIndexes || [];\n\t\t\t\t\tconst overviewKey = `${activeRelativePath}:${comparisonSource}:${normalizedFromIndex}:${normalizedToIndex}:${selectedEntryIndexes.join(',') || 'all'}`;\n\t\t\t\t\tlet items = rangeOverviewCache.get(overviewKey);\n\t\t\t\t\tif (!items) {\n\t\t\t\t\t\titems = await buildRangeOverview({\n\t\t\t\t\t\t\trepoRoot: repoContext.repoRoot,\n\t\t\t\t\t\t\tfileFixture,\n\t\t\t\t\t\t\tcurrentRelativePath: activeRelativePath,\n\t\t\t\t\t\t\tfromIndex: normalizedFromIndex,\n\t\t\t\t\t\t\ttoIndex: normalizedToIndex,\n\t\t\t\t\t\t\tcomparisonSource,\n\t\t\t\t\t\t\tselectedEntryIndexes,\n\t\t\t\t\t\t});\n\t\t\t\t\t\trangeOverviewCache.set(overviewKey, items);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'range-overview',\n\t\t\t\t\t\t\tpayload: {\n\t\t\t\t\t\t\t\tfromIndex: normalizedFromIndex,\n\t\t\t\t\t\t\t\ttoIndex: normalizedToIndex,\n\t\t\t\t\t\t\t\tcomparisonSource,\n\t\t\t\t\t\t\t\tselectedEntryIndexes,\n\t\t\t\t\t\t\t\titems,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t\tcase 'load-range-stack': {\n\t\t\t\t\tconst normalizedFromIndex = Math.max(0, Math.min(command.fromIndex, command.toIndex));\n\t\t\t\t\tconst normalizedToIndex = Math.max(normalizedFromIndex, Math.max(command.fromIndex, command.toIndex));\n\t\t\t\t\tconst comparisonSource = command.comparisonSource === 'snapshot' ? 'snapshot' : 'revision';\n\t\t\t\t\tconst items: Array<{ relativePath: string; preview: DiffPreview }> = [];\n\t\t\t\t\tfor (const stackPath of command.relativePaths) {\n\t\t\t\t\t\tconst normalizedPath = normalizePath(stackPath);\n\t\t\t\t\t\tconst fileFixture =\n\t\t\t\t\t\t\tnormalizedPath === activeRelativePath\n\t\t\t\t\t\t\t\t? await getActiveFileFixture()\n\t\t\t\t\t\t\t\t: await getFileFixture(normalizedPath);\n\t\t\t\t\t\titems.push({\n\t\t\t\t\t\t\trelativePath: normalizedPath,\n\t\t\t\t\t\t\tpreview: getFixturePreview({\n\t\t\t\t\t\t\t\tfileFixture,\n\t\t\t\t\t\t\t\tfromIndex: normalizedFromIndex,\n\t\t\t\t\t\t\t\ttoIndex: normalizedToIndex,\n\t\t\t\t\t\t\t\tcomparisonSource,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'range-stack-previews',\n\t\t\t\t\t\t\tpayload: {\n\t\t\t\t\t\t\t\tfromIndex: normalizedFromIndex,\n\t\t\t\t\t\t\t\ttoIndex: normalizedToIndex,\n\t\t\t\t\t\t\t\tcomparisonSource,\n\t\t\t\t\t\t\t\titems,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t\tcase 'search-history': {\n\t\t\t\t\tconst fileFixture = await getActiveFileFixture();\n\t\t\t\t\tconst entries = fileFixture.timelineData.entries.filter((entry) => !entry.isWorkingTree);\n\t\t\t\t\tconst tip = entries[Math.max(0, entries.length - 1)];\n\t\t\t\t\tconst previous = entries[Math.max(0, entries.length - 2)] || tip;\n\t\t\t\t\tconst introducedAt = previous?.index ?? 0;\n\t\t\t\t\tconst tipIndex = tip?.index ?? introducedAt;\n\t\t\t\t\tconst hits: Array<{ entryIndex: number; kind: 'introduced' | 'present' }> = [\n\t\t\t\t\t\t{ entryIndex: introducedAt, kind: 'introduced' },\n\t\t\t\t\t];\n\t\t\t\t\tif (tipIndex !== introducedAt) {\n\t\t\t\t\t\thits.push({ entryIndex: tipIndex, kind: 'present' });\n\t\t\t\t\t}\n\t\t\t\t\tconst message: TimelineInboundMessage = {\n\t\t\t\t\t\ttype: 'history-search',\n\t\t\t\t\t\tpayload: {\n\t\t\t\t\t\t\tquery: command.query,\n\t\t\t\t\t\t\tintroducedAt,\n\t\t\t\t\t\t\tremovedAt: null,\n\t\t\t\t\t\t\thits,\n\t\t\t\t\t\t\tpurpose: command.purpose === 'sidebar' ? 'sidebar' : 'history',\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\treturn [message];\n\t\t\t\t}\n\t\t\t\tcase 'load-revision-tree-files': {\n\t\t\t\t\tconst fileFixture = await getActiveFileFixture();\n\t\t\t\t\treturn [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'revision-tree-files',\n\t\t\t\t\t\t\tpayload: {\n\t\t\t\t\t\t\t\trevision: command.revision,\n\t\t\t\t\t\t\t\tfiles: fileFixture.timelineData.workspaceFiles || [],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t\tcase 'load-file-oplog': {\n\t\t\t\t\tconst fileFixture = await getActiveFileFixture();\n\t\t\t\t\tif (fileFixture.timelineData.backend !== 'jj') {\n\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'file-oplog',\n\t\t\t\t\t\t\t\tpayload: { relativePath: fileFixture.timelineData.relativePath, entries: [] },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t];\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst { stdout } = await run({\n\t\t\t\t\t\t\tcommand: 'jj',\n\t\t\t\t\t\t\targs: ['op', 'log', '--limit', '80', '-T', JJ_OP_LOG_TEMPLATE],\n\t\t\t\t\t\t\tcwd: fileFixture.timelineData.workspacePath || process.cwd(),\n\t\t\t\t\t\t});\n\t\t\t\t\t\tconst fileEntries = [\n\t\t\t\t\t\t\t...(fileFixture.timelineData.snapshotEntries || []),\n\t\t\t\t\t\t\t...fileFixture.timelineData.entries.filter((entry) => Boolean(entry.operationId)),\n\t\t\t\t\t\t];\n\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'file-oplog',\n\t\t\t\t\t\t\t\tpayload: {\n\t\t\t\t\t\t\t\t\trelativePath: fileFixture.timelineData.relativePath,\n\t\t\t\t\t\t\t\t\tentries: filterFileOpLogPeek({\n\t\t\t\t\t\t\t\t\t\topLog: parseJjOpLogOutput(stdout),\n\t\t\t\t\t\t\t\t\t\tfileEntries,\n\t\t\t\t\t\t\t\t\t\trelativePath: fileFixture.timelineData.relativePath,\n\t\t\t\t\t\t\t\t\t\tlimit: 12,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t];\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'file-oplog',\n\t\t\t\t\t\t\t\tpayload: { relativePath: fileFixture.timelineData.relativePath, entries: [] },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcase 'load-entry-diff-counts': {\n\t\t\t\t\tconst fileFixture = await getActiveFileFixture();\n\t\t\t\t\treturn [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'entry-diff-counts',\n\t\t\t\t\t\t\tpayload: {\n\t\t\t\t\t\t\t\tcomparisonSource: command.comparisonSource,\n\t\t\t\t\t\t\t\tcounts: await Promise.all(\n\t\t\t\t\t\t\t\t\tcommand.entryIndexes.map(async (entryIndex) => ({\n\t\t\t\t\t\t\t\t\t\tentryIndex,\n\t\t\t\t\t\t\t\t\t\tdiffCount: await getStandaloneEntryDiffCount({\n\t\t\t\t\t\t\t\t\t\t\trepoRoot: repoContext.repoRoot,\n\t\t\t\t\t\t\t\t\t\t\tfileFixture,\n\t\t\t\t\t\t\t\t\t\t\tentryIndex,\n\t\t\t\t\t\t\t\t\t\t\tcomparisonSource: command.comparisonSource,\n\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t\tcase 'resolve-nonempty-range': {\n\t\t\t\t\tconst fileFixture = await getActiveFileFixture();\n\t\t\t\t\treturn [{ type: 'resolved-range', payload: resolveNonEmptyRange(fileFixture, command.candidateIndexes) }];\n\t\t\t\t}\n\t\t\t\tcase 'hydrate-snapshot-entries': {\n\t\t\t\t\tconst fileFixture = await getActiveFileFixture();\n\t\t\t\t\treturn [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'snapshot-entries',\n\t\t\t\t\t\t\tpayload: {\n\t\t\t\t\t\t\t\tsnapshotEntries: clone(fileFixture.timelineData.snapshotEntries),\n\t\t\t\t\t\t\t\tsnapshotState: clone(fileFixture.timelineData.snapshotState || { loadedChangeIds: [] }),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t\tcase 'open-current-file':\n\t\t\t\t\tawait openTarget(path.join(repoContext.repoRoot, activeRelativePath));\n\t\t\t\t\treturn [];\n\t\t\t\tcase 'open-editor-diff':\n\t\t\t\tcase 'open-range-files-diff': {\n\t\t\t\t\tif (command.command === 'open-range-files-diff' && command.editorCommand) {\n\t\t\t\t\t\tconst fileFixture = await getActiveFileFixture();\n\t\t\t\t\t\tconst plan = await buildStandaloneRangeMultiDiffPlan({\n\t\t\t\t\t\t\trepoRoot: repoContext.repoRoot,\n\t\t\t\t\t\t\tfileFixture,\n\t\t\t\t\t\t\tfromIndex: command.fromIndex,\n\t\t\t\t\t\t\ttoIndex: command.toIndex,\n\t\t\t\t\t\t\tcomparisonSource: command.comparisonSource,\n\t\t\t\t\t\t\tselectedEntryIndexes: command.selectedEntryIndexes || [],\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (plan.files.length) {\n\t\t\t\t\t\t\tawait openMultiDiffWithEditor({\n\t\t\t\t\t\t\t\trepoRoot: repoContext.repoRoot,\n\t\t\t\t\t\t\t\teditorCommand: command.editorCommand,\n\t\t\t\t\t\t\t\tfiles: plan.files,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tconst fileFixture = await getActiveFileFixture();\n\t\t\t\t\tconst preview = getFixturePreview({\n\t\t\t\t\t\tfileFixture,\n\t\t\t\t\t\tfromIndex: command.fromIndex,\n\t\t\t\t\t\ttoIndex: command.toIndex,\n\t\t\t\t\t\tcomparisonSource: command.comparisonSource,\n\t\t\t\t\t});\n\t\t\t\t\tawait openPreviewDocument({ preview, relativePath: activeRelativePath });\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t\tcase 'open-revision-files-diff': {\n\t\t\t\t\tif (command.editorCommand) {\n\t\t\t\t\t\tconst fileFixture = await getActiveFileFixture();\n\t\t\t\t\t\tconst plan = await buildStandaloneEntryMultiDiffPlan({\n\t\t\t\t\t\t\trepoRoot: repoContext.repoRoot,\n\t\t\t\t\t\t\tfileFixture,\n\t\t\t\t\t\t\tentryIndex: command.entryIndex,\n\t\t\t\t\t\t\tcomparisonSource: command.comparisonSource,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (plan.files.length) {\n\t\t\t\t\t\t\tawait openMultiDiffWithEditor({\n\t\t\t\t\t\t\t\trepoRoot: repoContext.repoRoot,\n\t\t\t\t\t\t\t\teditorCommand: command.editorCommand,\n\t\t\t\t\t\t\t\tfiles: plan.files,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tconst fileFixture = await getActiveFileFixture();\n\t\t\t\t\tconst preview = getUnitPreview({\n\t\t\t\t\t\tfileFixture,\n\t\t\t\t\t\tentryIndex: command.entryIndex,\n\t\t\t\t\t\tcomparisonSource: command.comparisonSource,\n\t\t\t\t\t});\n\t\t\t\t\tif (preview) {\n\t\t\t\t\t\tawait openPreviewDocument({ preview, relativePath: activeRelativePath });\n\t\t\t\t\t}\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t\tcase 'open-revision-remote': {\n\t\t\t\t\tconst fileFixture = await getActiveFileFixture();\n\t\t\t\t\tconst sourceEntries = getEntriesForSource(fileFixture.timelineData, command.comparisonSource);\n\t\t\t\t\tconst entry = sourceEntries.find((candidate) => candidate.index === command.entryIndex);\n\t\t\t\t\tif (entry?.remoteUrl) {\n\t\t\t\t\t\tawait openTarget(entry.remoteUrl);\n\t\t\t\t\t}\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t\tcase 'cancel-active-request':\n\t\t\t\tdefault:\n\t\t\t\t\treturn [];\n\t\t\t}\n\t\t},\n\t};\n\n\tasync function emitTimeline(): Promise<TimelineInboundMessage[]> {\n\t\tconst fileFixture = await getActiveFileFixture();\n\t\tconst timelineData = withPersistedPreferences(fileFixture.timelineData);\n\t\tconst defaultFromIndex = Math.max(0, timelineData.defaultIndex - 1);\n\t\tconst messages: TimelineInboundMessage[] = [\n\t\t\t{ type: 'timeline-data', payload: timelineData },\n\t\t\t{\n\t\t\t\ttype: 'diff-preview',\n\t\t\t\tpayload: getFixturePreview({\n\t\t\t\t\tfileFixture,\n\t\t\t\t\tfromIndex: defaultFromIndex,\n\t\t\t\t\ttoIndex: timelineData.defaultIndex,\n\t\t\t\t\tcomparisonSource: timelineData.preferences.comparisonSource || 'revision',\n\t\t\t\t}),\n\t\t\t},\n\t\t];\n\n\t\tif (timelineData.backend === 'jj') {\n\t\t\tmessages.push({\n\t\t\t\ttype: 'snapshot-entries',\n\t\t\t\tpayload: {\n\t\t\t\t\tsnapshotEntries: clone(fileFixture.timelineData.snapshotEntries || []),\n\t\t\t\t\tsnapshotState: clone(fileFixture.timelineData.snapshotState || { loadedChangeIds: [] }),\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\treturn messages;\n\t}\n\n\tasync function getActiveFileFixture(): Promise<TimelineFixtureFile> {\n\t\treturn getFileFixture(activeRelativePath);\n\t}\n\n\tasync function getFileFixture(relativeFilePath: string): Promise<TimelineFixtureFile> {\n\t\tconst normalizedRelativePath = normalizePath(relativeFilePath);\n\t\tif (!fileCache.has(normalizedRelativePath)) {\n\t\t\tconst nextFixture = await buildFileFixture({\n\t\t\t\tbackend: repoContext.backend,\n\t\t\t\trelativePath: normalizedRelativePath,\n\t\t\t\trepoRoot: repoContext.repoRoot,\n\t\t\t\tremoteBaseUrl: repoContext.remoteBaseUrl,\n\t\t\t});\n\t\t\tfileCache.set(normalizedRelativePath, nextFixture);\n\t\t}\n\n\t\treturn fileCache.get(normalizedRelativePath)!;\n\t}\n\n\tfunction withPersistedPreferences(timelineData: TimelineData): TimelineData {\n\t\tconst persistedPreferences = preferencesByPath.get(timelineData.relativePath) || {};\n\t\treturn {\n\t\t\t...clone(timelineData),\n\t\t\tpreferences: {\n\t\t\t\t...clone(timelineData.preferences),\n\t\t\t\t...persistedPreferences,\n\t\t\t},\n\t\t};\n\t}\n\n\tfunction clearRangeOverviewCache(relativeFilePath: string): void {\n\t\tfor (const cacheKey of rangeOverviewCache.keys()) {\n\t\t\tif (cacheKey.startsWith(`${relativeFilePath}:`)) {\n\t\t\t\trangeOverviewCache.delete(cacheKey);\n\t\t\t}\n\t\t}\n\t}\n}\n\nasync function handleRequest(args: {\n\trequest: IncomingMessage;\n\tresponse: ServerResponse;\n\truntime: StandaloneRuntime;\n\tverbose: boolean;\n}): Promise<void> {\n\ttry {\n\t\tconst requestUrl = new URL(args.request.url || '/', 'http://127.0.0.1');\n\t\tif (args.request.method === 'POST' && requestUrl.pathname === '/api/command') {\n\t\t\tconst command = (await readJsonBody(args.request)) as TimelineCommand;\n\t\t\tconst messages = await args.runtime.handleCommand(command);\n\t\t\twriteJson(args.response, 200, { messages });\n\t\t\treturn;\n\t\t}\n\n\t\tif (args.request.method !== 'GET' && args.request.method !== 'HEAD') {\n\t\t\twriteJson(args.response, 405, { error: 'Method Not Allowed' });\n\t\t\treturn;\n\t\t}\n\n\t\tconst targetPath = resolveStaticPath(requestUrl.pathname);\n\t\tif (!targetPath) {\n\t\t\twriteJson(args.response, 403, { error: 'Forbidden' });\n\t\t\treturn;\n\t\t}\n\n\t\tif (!fsSync.existsSync(targetPath) || !fsSync.statSync(targetPath).isFile()) {\n\t\t\twriteJson(args.response, 404, { error: 'Not Found' });\n\t\t\treturn;\n\t\t}\n\n\t\tconst body = await fs.readFile(targetPath);\n\t\targs.response.writeHead(200, {\n\t\t\t'content-type': getContentType(targetPath),\n\t\t\t'cache-control': 'no-store',\n\t\t});\n\n\t\tif (args.request.method === 'HEAD') {\n\t\t\targs.response.end();\n\t\t\treturn;\n\t\t}\n\n\t\targs.response.end(body);\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tif (args.verbose) {\n\t\t\tprocess.stderr.write(`Standalone timeline request failed: ${message}\\n`);\n\t\t}\n\t\twriteJson(args.response, 500, { error: message });\n\t}\n}\n\nasync function buildFileFixture(args: FileFixtureBuildArgs): Promise<TimelineFixtureFile> {\n\tconst workspaceFiles = await getWorkspaceFiles(args.repoRoot);\n\tconst entries =\n\t\targs.backend === 'jj'\n\t\t\t? await getJjEntries({\n\t\t\t\t\trepoRoot: args.repoRoot,\n\t\t\t\t\trelativePath: args.relativePath,\n\t\t\t\t\tremoteBaseUrl: args.remoteBaseUrl,\n\t\t\t\t})\n\t\t\t: await getGitEntries({\n\t\t\t\t\trepoRoot: args.repoRoot,\n\t\t\t\t\trelativePath: args.relativePath,\n\t\t\t\t\tremoteBaseUrl: args.remoteBaseUrl,\n\t\t\t\t});\n\tconst snapshotEntries =\n\t\targs.backend === 'jj'\n\t\t\t? await getJjSnapshotEntries({\n\t\t\t\t\trepoRoot: args.repoRoot,\n\t\t\t\t\trelativePath: args.relativePath,\n\t\t\t\t\trevisionEntries: entries,\n\t\t\t\t\tremoteBaseUrl: args.remoteBaseUrl,\n\t\t\t\t})\n\t\t\t: [];\n\tconst loadedChangeIds =\n\t\targs.backend === 'jj' ? [...new Set(entries.map((entry) => entry.changeId).filter(Boolean) as string[])] : [];\n\tconst snapshotSourceEntries =\n\t\targs.backend === 'jj'\n\t\t\t? composeSnapshotEntries({ revisionEntries: entries, snapshotEntries, loadedChangeIds: new Set(loadedChangeIds) })\n\t\t\t: entries;\n\tconst defaultIndex = Math.max(0, entries.length - 1);\n\tconst pathCache = new Map<string, string>();\n\tconst contentCache = new Map<string, string>();\n\n\treturn {\n\t\ttimelineData: {\n\t\t\tbackend: args.backend,\n\t\t\tworkspacePath: args.repoRoot,\n\t\t\trelativePath: args.relativePath,\n\t\t\tfileName: path.basename(args.relativePath),\n\t\t\tversion: packageJson.version,\n\t\t\tpresets: timelinePresets,\n\t\t\tdefaultIndex,\n\t\t\tlatestIndex: defaultIndex,\n\t\t\tpreferences: {\n\t\t\t\tsidebarWidth: 280,\n\t\t\t\tlayoutMode: 'split',\n\t\t\t\tcontentMode: 'diffs',\n\t\t\t\tcomparisonMode: 'range',\n\t\t\t\tcomparisonSource: args.backend === 'jj' ? 'snapshot' : 'revision',\n\t\t\t\tpreset: '90d',\n\t\t\t\tshowIntermediateRevisions: true,\n\t\t\t},\n\t\t\tworkspaceFiles,\n\t\t\thasIntermediateRevisions: entries.some((entry) => !entry.touchesFile),\n\t\t\tentries,\n\t\t\tsnapshotEntries,\n\t\t\tsnapshotState: {\n\t\t\t\tloadedChangeIds,\n\t\t\t},\n\t\t},\n\t\tpreviews: {\n\t\t\trevision: await buildPreviewMap({\n\t\t\t\trepoRoot: args.repoRoot,\n\t\t\t\tentries,\n\t\t\t\tbackend: args.backend,\n\t\t\t\trelativePath: args.relativePath,\n\t\t\t\tcomparisonSource: 'revision',\n\t\t\t\tpathCache,\n\t\t\t\tcontentCache,\n\t\t\t}),\n\t\t\tsnapshot:\n\t\t\t\targs.backend === 'jj'\n\t\t\t\t\t? await buildPreviewMap({\n\t\t\t\t\t\t\trepoRoot: args.repoRoot,\n\t\t\t\t\t\t\tentries: snapshotSourceEntries,\n\t\t\t\t\t\t\tbackend: args.backend,\n\t\t\t\t\t\t\trelativePath: args.relativePath,\n\t\t\t\t\t\t\tcomparisonSource: 'snapshot',\n\t\t\t\t\t\t\tpathCache,\n\t\t\t\t\t\t\tcontentCache,\n\t\t\t\t\t\t})\n\t\t\t\t\t: await buildPreviewMap({\n\t\t\t\t\t\t\trepoRoot: args.repoRoot,\n\t\t\t\t\t\t\tentries,\n\t\t\t\t\t\t\tbackend: args.backend,\n\t\t\t\t\t\t\trelativePath: args.relativePath,\n\t\t\t\t\t\t\tcomparisonSource: 'revision',\n\t\t\t\t\t\t\tpathCache,\n\t\t\t\t\t\t\tcontentCache,\n\t\t\t\t\t\t}),\n\t\t},\n\t};\n}\n\nasync function getGitEntries(args: {\n\trepoRoot: string;\n\trelativePath: string;\n\tremoteBaseUrl?: string;\n}): Promise<FileRevisionEntry[]> {\n\tconst touchingEntries = await getGitHistoryEntries(args);\n\tconst entries =\n\t\ttouchingEntries.length >= 2\n\t\t\t? mergeTimelineEntries(await getGitRepositoryEntries(args), touchingEntries)\n\t\t\t: touchingEntries;\n\tseedLatestEntryPath(entries, args.relativePath);\n\tconst workingTreeEntry = await makeWorkingTreeEntry({\n\t\trepoRoot: args.repoRoot,\n\t\tpreviousEntry: entries.at(-1),\n\t\trelativePath: args.relativePath,\n\t\tbackend: 'git',\n\t\tremoteBaseUrl: args.remoteBaseUrl,\n\t});\n\tif (workingTreeEntry) {\n\t\tentries.push(workingTreeEntry);\n\t}\n\n\treturn reindexEntries(entries);\n}\n\nasync function getGitHistoryEntries(args: {\n\trepoRoot: string;\n\trelativePath: string;\n\tremoteBaseUrl?: string;\n}): Promise<FileRevisionEntry[]> {\n\tconst { stdout } = await run({\n\t\tcommand: 'git',\n\t\targs: [\n\t\t\t'log',\n\t\t\t'--follow',\n\t\t\t'--reverse',\n\t\t\t'--decorate=short',\n\t\t\t'--date=iso-strict',\n\t\t\t'--format=%H%x09%ad%x09%an%x09%D%x09%s',\n\t\t\t'--max-count=200',\n\t\t\t'--',\n\t\t\targs.relativePath,\n\t\t],\n\t\tcwd: args.repoRoot,\n\t});\n\tconst revisions = stdout.trim().split(/\\r?\\n/).filter(Boolean);\n\tconst entries: FileRevisionEntry[] = [];\n\tfor (const [index, line] of revisions.entries()) {\n\t\tconst [revision, authorDate, authorName, branchNames, description] = line.split('\\t');\n\t\tentries.push(\n\t\t\tmakeEntry({\n\t\t\t\tid: revision || '',\n\t\t\t\tindex,\n\t\t\t\trevision: revision || '',\n\t\t\t\tshortRevision: (revision || '').slice(0, 8),\n\t\t\t\tchangeId: undefined,\n\t\t\t\tbranchNames: parseGitBranchNames(branchNames || ''),\n\t\t\t\tauthorDate: authorDate || '',\n\t\t\t\tauthorName: authorName || '',\n\t\t\t\tdescription: description || '',\n\t\t\t\ttouchesFile: true,\n\t\t\t\tisWorkingTree: false,\n\t\t\t\tfilePath: args.relativePath,\n\t\t\t\tremoteBaseUrl: args.remoteBaseUrl,\n\t\t\t}),\n\t\t);\n\t}\n\n\treturn entries;\n}\n\nasync function getGitRepositoryEntries(args: {\n\trepoRoot: string;\n\trelativePath: string;\n\tremoteBaseUrl?: string;\n}): Promise<FileRevisionEntry[]> {\n\tconst { stdout } = await run({\n\t\tcommand: 'git',\n\t\targs: [\n\t\t\t'log',\n\t\t\t'--reverse',\n\t\t\t'--decorate=short',\n\t\t\t'--date=iso-strict',\n\t\t\t'--format=%H%x09%ad%x09%an%x09%D%x09%s',\n\t\t\t'--max-count=200',\n\t\t],\n\t\tcwd: args.repoRoot,\n\t});\n\tconst revisions = stdout.trim().split(/\\r?\\n/).filter(Boolean);\n\tconst entries: FileRevisionEntry[] = [];\n\n\tfor (const [index, line] of revisions.entries()) {\n\t\tconst [revision, authorDate, authorName, branchNames, description] = line.split('\\t');\n\t\tentries.push(\n\t\t\tmakeEntry({\n\t\t\t\tid: revision || '',\n\t\t\t\tindex,\n\t\t\t\trevision: revision || '',\n\t\t\t\tshortRevision: (revision || '').slice(0, 8),\n\t\t\t\tchangeId: undefined,\n\t\t\t\tbranchNames: parseGitBranchNames(branchNames || ''),\n\t\t\t\tauthorDate: authorDate || '',\n\t\t\t\tauthorName: authorName || '',\n\t\t\t\tdescription: description || '',\n\t\t\t\ttouchesFile: false,\n\t\t\t\tisWorkingTree: false,\n\t\t\t\tfilePath: undefined,\n\t\t\t\tremoteBaseUrl: args.remoteBaseUrl,\n\t\t\t}),\n\t\t);\n\t}\n\n\treturn entries;\n}\n\nasync function getJjEntries(args: {\n\trepoRoot: string;\n\trelativePath: string;\n\tremoteBaseUrl?: string;\n}): Promise<FileRevisionEntry[]> {\n\tconst template = buildJjHistoryLogTemplate();\n\tconst { stdout } = await run({\n\t\tcommand: 'jj',\n\t\targs: ['log', '--no-graph', '--reversed', '--limit', '100', '-T', template],\n\t\tcwd: args.repoRoot,\n\t});\n\tconst revisions = stdout.trim().split(/\\r?\\n/).filter(Boolean);\n\tconst entries: FileRevisionEntry[] = [];\n\tfor (const [index, line] of revisions.entries()) {\n\t\tconst parsed = parseJjHistoryLine(line);\n\t\tif (/^0+$/u.test(parsed.revision || '')) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst touchesFile = await jjTouchesFile({\n\t\t\trepoRoot: args.repoRoot,\n\t\t\trevision: parsed.revision || '',\n\t\t\trelativePath: args.relativePath,\n\t\t});\n\t\tentries.push(\n\t\t\tmakeEntry({\n\t\t\t\t...parsed,\n\t\t\t\tindex,\n\t\t\t\ttouchesFile,\n\t\t\t\tfilePath: args.relativePath,\n\t\t\t\tremoteBaseUrl: args.remoteBaseUrl,\n\t\t\t}),\n\t\t);\n\t}\n\n\tconst lastEntry = entries.at(-1);\n\tif (lastEntry && !lastEntry.description) {\n\t\tlastEntry.revision = 'WORKTREE';\n\t\tlastEntry.shortRevision = 'Current';\n\t\tlastEntry.description = 'Working tree';\n\t\tlastEntry.isWorkingTree = true;\n\t\tlastEntry.changeId = undefined;\n\t\tlastEntry.remoteUrl = undefined;\n\t}\n\n\tseedLatestEntryPath(entries, args.relativePath);\n\n\tconst workingTreeEntry = await makeWorkingTreeEntry({\n\t\trepoRoot: args.repoRoot,\n\t\tpreviousEntry: entries.at(-1),\n\t\trelativePath: args.relativePath,\n\t\tbackend: 'jj',\n\t\tremoteBaseUrl: args.remoteBaseUrl,\n\t});\n\tif (workingTreeEntry) {\n\t\tentries.push(workingTreeEntry);\n\t}\n\n\treturn reindexEntries(dedupeAdjacentTimelineEntries(entries));\n}\n\nasync function getJjSnapshotEntries(args: {\n\trepoRoot: string;\n\trelativePath: string;\n\trevisionEntries: FileRevisionEntry[];\n\tremoteBaseUrl?: string;\n}): Promise<FileRevisionEntry[]> {\n\tconst snapshotEntries: FileRevisionEntry[] = [];\n\n\tfor (const entry of args.revisionEntries) {\n\t\tif (!entry.changeId || entry.isWorkingTree || !entry.touchesFile) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tlet stdout = '';\n\t\ttry {\n\t\t\t({ stdout } = await run({\n\t\t\t\tcommand: 'jj',\n\t\t\t\targs: ['evolog', '--no-graph', '--summary', '--limit', '100', '-r', entry.revision],\n\t\t\t\tcwd: args.repoRoot,\n\t\t\t}));\n\t\t} catch {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst evolutionEntries = parseJjEvolutionSummaryEntries(stdout)\n\t\t\t.filter((evolutionEntry) => parseJjSummaryChangedPaths(evolutionEntry.summaryLines).includes(args.relativePath))\n\t\t\t.map((evolutionEntry, evolutionIndex) =>\n\t\t\t\tmakeEntry({\n\t\t\t\t\tid: `snapshot:${entry.changeId}:${evolutionEntry.operationId || evolutionEntry.changeKey || evolutionEntry.revision}:${evolutionIndex}`,\n\t\t\t\t\tindex: 0,\n\t\t\t\t\trevision: evolutionEntry.revision,\n\t\t\t\t\tshortRevision: normalizeSnapshotOperationKey(evolutionEntry.changeKey) || evolutionEntry.revision.slice(0, 8),\n\t\t\t\t\tchangeId: entry.changeId,\n\t\t\t\t\tbookmarkNames: evolutionEntry.bookmarkNames,\n\t\t\t\t\tauthorDate: normalizeSnapshotAuthorDate(evolutionEntry.authorDate, entry.authorDate),\n\t\t\t\t\tauthorName: evolutionEntry.authorName || entry.authorName,\n\t\t\t\t\tdescription: normalizeSnapshotDescription(evolutionEntry.description, evolutionEntry.operationDescription),\n\t\t\t\t\ttouchesFile: true,\n\t\t\t\t\tisWorkingTree: false,\n\t\t\t\t\tfilePath: args.relativePath,\n\t\t\t\t\toperationId: evolutionEntry.operationId,\n\t\t\t\t\toperationIndex: evolutionEntry.operationIndex,\n\t\t\t\t\toperationKey: evolutionEntry.changeKey,\n\t\t\t\t\tremoteBaseUrl: args.remoteBaseUrl,\n\t\t\t\t}),\n\t\t\t);\n\n\t\tsnapshotEntries.push(...evolutionEntries);\n\t}\n\n\tsnapshotEntries.sort(\n\t\t(left, right) => left.timestamp - right.timestamp || left.revision.localeCompare(right.revision),\n\t);\n\treturn reindexEntries(snapshotEntries);\n}\n\nfunction composeSnapshotEntries(args: {\n\trevisionEntries: FileRevisionEntry[];\n\tsnapshotEntries: FileRevisionEntry[];\n\tloadedChangeIds: Set<string>;\n}): FileRevisionEntry[] {\n\tif (!args.loadedChangeIds.size) {\n\t\treturn args.revisionEntries;\n\t}\n\n\tconst snapshotEntriesByChangeId = args.snapshotEntries.reduce((groups, entry) => {\n\t\tif (!entry.changeId) {\n\t\t\treturn groups;\n\t\t}\n\t\tconst existing = groups.get(entry.changeId) || [];\n\t\texisting.push(entry);\n\t\tgroups.set(entry.changeId, existing);\n\t\treturn groups;\n\t}, new Map<string, FileRevisionEntry[]>());\n\n\treturn reindexEntries(\n\t\targs.revisionEntries.flatMap((entry) => {\n\t\t\tif (!entry.changeId || entry.isWorkingTree || !entry.touchesFile || !args.loadedChangeIds.has(entry.changeId)) {\n\t\t\t\treturn [entry];\n\t\t\t}\n\n\t\t\treturn snapshotEntriesByChangeId.get(entry.changeId) || [entry];\n\t\t}),\n\t);\n}\n\nfunction seedLatestEntryPath(entries: FileRevisionEntry[], relativePath: string): void {\n\tfor (const entry of entries) {\n\t\tif (!entry.isWorkingTree && entry.filePath) {\n\t\t\tdelete entry.filePath;\n\t\t}\n\t}\n\n\tfor (let index = entries.length - 1; index >= 0; index -= 1) {\n\t\tconst entry = entries[index];\n\t\tif (!entry || entry.isWorkingTree || !entry.touchesFile) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tentry.filePath = relativePath;\n\t\tbreak;\n\t}\n}\n\nfunction mergeTimelineEntries(\n\trepositoryEntries: FileRevisionEntry[],\n\tfileEntries: FileRevisionEntry[],\n): FileRevisionEntry[] {\n\tconst touchingByRevision = new Map(fileEntries.map((entry) => [entry.revision, entry]));\n\tconst repoIndexes = fileEntries\n\t\t.map((entry) => repositoryEntries.findIndex((candidate) => candidate.revision === entry.revision))\n\t\t.filter((index) => index >= 0);\n\n\tif (!repoIndexes.length) {\n\t\treturn fileEntries;\n\t}\n\n\tconst startIndex = Math.min(...repoIndexes);\n\tconst endIndex = Math.max(...repoIndexes);\n\tconst merged = repositoryEntries\n\t\t.slice(startIndex, endIndex + 1)\n\t\t.map((entry) => touchingByRevision.get(entry.revision) || entry);\n\n\tfor (const entry of fileEntries) {\n\t\tif (!merged.some((candidate) => candidate.revision === entry.revision)) {\n\t\t\tmerged.push(entry);\n\t\t}\n\t}\n\n\treturn merged.toSorted(\n\t\t(left, right) => left.timestamp - right.timestamp || left.revision.localeCompare(right.revision),\n\t);\n}\n\nfunction dedupeAdjacentTimelineEntries(entries: FileRevisionEntry[]): FileRevisionEntry[] {\n\treturn entries.reduce<FileRevisionEntry[]>((deduped, entry) => {\n\t\tconst previousEntry = deduped.at(-1);\n\t\tif (!previousEntry?.changeId || previousEntry.changeId !== entry.changeId) {\n\t\t\tdeduped.push(entry);\n\t\t\treturn deduped;\n\t\t}\n\n\t\tif (!previousEntry.touchesFile && entry.touchesFile) {\n\t\t\tdeduped[deduped.length - 1] = entry;\n\t\t}\n\n\t\treturn deduped;\n\t}, []);\n}\n\nasync function buildPreviewMap(args: {\n\trepoRoot: string;\n\tentries: FileRevisionEntry[];\n\tbackend: HistoryBackend;\n\trelativePath: string;\n\tcomparisonSource: ComparisonSource;\n\tpathCache: Map<string, string>;\n\tcontentCache: Map<string, string>;\n}): Promise<Record<string, DiffPreview>> {\n\tconst previews: Record<string, DiffPreview> = {};\n\tfor (let toIndex = 1; toIndex < args.entries.length; toIndex += 1) {\n\t\tfor (let fromIndex = 0; fromIndex < toIndex; fromIndex += 1) {\n\t\t\tpreviews[`${fromIndex}:${toIndex}`] = await buildPreview({\n\t\t\t\trepoRoot: args.repoRoot,\n\t\t\t\tentries: args.entries,\n\t\t\t\tbackend: args.backend,\n\t\t\t\trelativePath: args.relativePath,\n\t\t\t\tcomparisonSource: args.comparisonSource,\n\t\t\t\tfromIndex,\n\t\t\t\ttoIndex,\n\t\t\t\tpathCache: args.pathCache,\n\t\t\t\tcontentCache: args.contentCache,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn previews;\n}\n\nasync function buildPreview(args: {\n\trepoRoot: string;\n\tentries: FileRevisionEntry[];\n\tbackend: HistoryBackend;\n\trelativePath: string;\n\tcomparisonSource: ComparisonSource;\n\tfromIndex: number;\n\ttoIndex: number;\n\tpathCache: Map<string, string>;\n\tcontentCache: Map<string, string>;\n}): Promise<DiffPreview> {\n\tconst fromEntry = args.entries[args.fromIndex];\n\tconst toEntry = args.entries[args.toIndex];\n\tconst beforePath = await resolveEntryFilePath({\n\t\trepoRoot: args.repoRoot,\n\t\tbackend: args.backend,\n\t\tentries: args.entries,\n\t\tentryIndex: args.fromIndex,\n\t\trelativePath: args.relativePath,\n\t\tpathCache: args.pathCache,\n\t});\n\tconst afterPath = await resolveEntryFilePath({\n\t\trepoRoot: args.repoRoot,\n\t\tbackend: args.backend,\n\t\tentries: args.entries,\n\t\tentryIndex: args.toIndex,\n\t\trelativePath: args.relativePath,\n\t\tpathCache: args.pathCache,\n\t});\n\tconst beforeText = await getEntryContent({\n\t\trepoRoot: args.repoRoot,\n\t\tbackend: args.backend,\n\t\tentries: args.entries,\n\t\tentryIndex: args.fromIndex,\n\t\trelativePath: args.relativePath,\n\t\tpathCache: args.pathCache,\n\t\tcontentCache: args.contentCache,\n\t});\n\tconst afterText = await getEntryContent({\n\t\trepoRoot: args.repoRoot,\n\t\tbackend: args.backend,\n\t\tentries: args.entries,\n\t\tentryIndex: args.toIndex,\n\t\trelativePath: args.relativePath,\n\t\tpathCache: args.pathCache,\n\t\tcontentCache: args.contentCache,\n\t});\n\tconst stats = computeDiffStats(beforeText, afterText);\n\n\treturn {\n\t\tindex: args.toIndex,\n\t\ttitle: `${fromEntry?.shortRevision || ''} -> ${toEntry?.shortRevision || ''}`,\n\t\tsubtitle: toEntry?.isWorkingTree\n\t\t\t? 'Working tree'\n\t\t\t: `${subtitleDateFormatter.format(new Date(toEntry?.authorDate || 0))} · ${toEntry?.description || ''}`,\n\t\tdiffCount: 0,\n\t\tadditions: stats.additions,\n\t\tdeletions: stats.deletions,\n\t\thunkCount: stats.hunkCount,\n\t\thasChanges: stats.hasChanges,\n\t\tfromIndex: args.fromIndex,\n\t\ttoIndex: args.toIndex,\n\t\tcomparisonSource: args.comparisonSource,\n\t\tbeforePath,\n\t\tafterPath,\n\t\tbeforeText,\n\t\tafterText,\n\t\tnonTextualDetails: stats.hasChanges\n\t\t\t? []\n\t\t\t: buildNonTextualDetails({\n\t\t\t\t\tbeforeText,\n\t\t\t\t\tafterText,\n\t\t\t\t\tbeforePath,\n\t\t\t\t\tafterPath,\n\t\t\t\t\tisWorkingTree: toEntry?.isWorkingTree,\n\t\t\t\t}),\n\t};\n}\n\nasync function getEntryContent(args: {\n\trepoRoot: string;\n\tbackend: HistoryBackend;\n\tentries: FileRevisionEntry[];\n\tentryIndex: number;\n\trelativePath: string;\n\tpathCache: Map<string, string>;\n\tcontentCache: Map<string, string>;\n}): Promise<string> {\n\tconst entry = args.entries[args.entryIndex];\n\tif (!entry) {\n\t\treturn '';\n\t}\n\n\tconst resolvedPath = entry.isWorkingTree ? args.relativePath : await resolveEntryFilePath(args);\n\tconst cacheKey = `${entry.revision}:${resolvedPath}`;\n\tif (args.contentCache.has(cacheKey)) {\n\t\treturn args.contentCache.get(cacheKey) || '';\n\t}\n\n\tlet content = '';\n\tif (entry.isWorkingTree) {\n\t\ttry {\n\t\t\tcontent = await fs.readFile(path.join(args.repoRoot, args.relativePath), 'utf8');\n\t\t} catch (error) {\n\t\t\tif (!isMissingFileError(error)) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t\targs.contentCache.set(cacheKey, content);\n\t\treturn content;\n\t}\n\n\tcontent =\n\t\targs.backend === 'jj'\n\t\t\t? await showJjFileAtRevision({ repoRoot: args.repoRoot, revision: entry.revision, relativePath: resolvedPath })\n\t\t\t: await showGitFileAtRevision({ repoRoot: args.repoRoot, revision: entry.revision, relativePath: resolvedPath });\n\targs.contentCache.set(cacheKey, content);\n\treturn content;\n}\n\nasync function resolveEntryFilePath(args: {\n\trepoRoot: string;\n\tbackend: HistoryBackend;\n\tentries: FileRevisionEntry[];\n\tentryIndex: number;\n\trelativePath: string;\n\tpathCache: Map<string, string>;\n}): Promise<string> {\n\tconst entry = args.entries[args.entryIndex];\n\tif (!entry || entry.isWorkingTree) {\n\t\treturn args.relativePath;\n\t}\n\n\tif (entry.filePath) {\n\t\treturn entry.filePath;\n\t}\n\n\tawait ensureEntryFilePath(args);\n\treturn entry.filePath || args.relativePath;\n}\n\nasync function ensureEntryFilePath(args: {\n\trepoRoot: string;\n\tbackend: HistoryBackend;\n\tentries: FileRevisionEntry[];\n\tentryIndex: number;\n\trelativePath: string;\n\tpathCache: Map<string, string>;\n}): Promise<void> {\n\tconst targetEntry = args.entries[args.entryIndex];\n\tif (!targetEntry || targetEntry.filePath || targetEntry.isWorkingTree) {\n\t\treturn;\n\t}\n\n\tlet knownIndex = -1;\n\tfor (let index = args.entryIndex + 1; index < args.entries.length; index += 1) {\n\t\tif (args.entries[index]?.filePath) {\n\t\t\tknownIndex = index;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (knownIndex < 0) {\n\t\ttargetEntry.filePath = args.relativePath;\n\t\treturn;\n\t}\n\n\tlet currentPath = args.entries[knownIndex].filePath || args.relativePath;\n\tfor (let index = knownIndex; index > args.entryIndex; index -= 1) {\n\t\tconst currentEntry = args.entries[index];\n\t\tconst previousEntry = args.entries[index - 1];\n\t\tif (!previousEntry) {\n\t\t\tbreak;\n\t\t}\n\n\t\tif (!previousEntry.filePath) {\n\t\t\tlet previousPath = currentPath;\n\t\t\tif (currentEntry.touchesFile && !currentEntry.isWorkingTree) {\n\t\t\t\tpreviousPath = await resolvePreviousPathAcrossRevision({\n\t\t\t\t\trepoRoot: args.repoRoot,\n\t\t\t\t\tbackend: args.backend,\n\t\t\t\t\trevision: currentEntry.revision,\n\t\t\t\t\tcurrentPath,\n\t\t\t\t\tpathCache: args.pathCache,\n\t\t\t\t});\n\t\t\t}\n\t\t\tpreviousEntry.filePath = previousPath;\n\t\t}\n\n\t\tcurrentPath = previousEntry.filePath || currentPath;\n\t}\n}\n\nasync function resolvePreviousPathAcrossRevision(args: {\n\trepoRoot: string;\n\tbackend: HistoryBackend;\n\trevision: string;\n\tcurrentPath: string;\n\tpathCache: Map<string, string>;\n}): Promise<string> {\n\tconst cacheKey = `${args.revision}:${args.currentPath}`;\n\tif (args.pathCache.has(cacheKey)) {\n\t\treturn args.pathCache.get(cacheKey) || args.currentPath;\n\t}\n\n\tconst previousPath =\n\t\targs.backend === 'git'\n\t\t\t? await resolveGitPreviousPath({\n\t\t\t\t\trepoRoot: args.repoRoot,\n\t\t\t\t\trevision: args.revision,\n\t\t\t\t\tcurrentPath: args.currentPath,\n\t\t\t\t})\n\t\t\t: await resolveJjPreviousPath({\n\t\t\t\t\trepoRoot: args.repoRoot,\n\t\t\t\t\trevision: args.revision,\n\t\t\t\t\tcurrentPath: args.currentPath,\n\t\t\t\t});\n\targs.pathCache.set(cacheKey, previousPath);\n\treturn previousPath;\n}\n\nasync function resolveGitPreviousPath(args: {\n\trepoRoot: string;\n\trevision: string;\n\tcurrentPath: string;\n}): Promise<string> {\n\tconst { stdout } = await run({\n\t\tcommand: 'git',\n\t\targs: ['diff-tree', '--root', '--no-commit-id', '--name-status', '--find-renames', '-r', args.revision],\n\t\tcwd: args.repoRoot,\n\t});\n\tfor (const line of stdout\n\t\t.split(/\\r?\\n/u)\n\t\t.map((value) => value.trim())\n\t\t.filter(Boolean)) {\n\t\tconst [, fromPath = '', toPath = ''] = line.split('\\t');\n\t\tif (toPath === args.currentPath) {\n\t\t\treturn fromPath || args.currentPath;\n\t\t}\n\t}\n\n\treturn args.currentPath;\n}\n\nasync function resolveJjPreviousPath(args: {\n\trepoRoot: string;\n\trevision: string;\n\tcurrentPath: string;\n}): Promise<string> {\n\ttry {\n\t\tconst { stdout } = await run({\n\t\t\tcommand: 'jj',\n\t\t\targs: ['diff', '--summary', '-r', args.revision],\n\t\t\tcwd: args.repoRoot,\n\t\t});\n\t\tconst rename = parseJjSummaryRenameLines(stdout).find((entry) => entry.toPath === args.currentPath);\n\t\treturn rename ? rename.fromPath : args.currentPath;\n\t} catch {\n\t\treturn args.currentPath;\n\t}\n}\n\nasync function showGitFileAtRevision(args: {\n\trepoRoot: string;\n\trevision: string;\n\trelativePath: string;\n}): Promise<string> {\n\ttry {\n\t\tconst { stdout } = await run({\n\t\t\tcommand: 'git',\n\t\t\targs: ['show', `${args.revision}:${args.relativePath}`],\n\t\t\tcwd: args.repoRoot,\n\t\t});\n\t\treturn stdout;\n\t} catch (error) {\n\t\tif (isMissingFileAtRevisionError(error)) {\n\t\t\treturn '';\n\t\t}\n\t\tthrow error;\n\t}\n}\n\nasync function showJjFileAtRevision(args: {\n\trepoRoot: string;\n\trevision: string;\n\trelativePath: string;\n}): Promise<string> {\n\ttry {\n\t\tconst { stdout } = await run({\n\t\t\tcommand: 'jj',\n\t\t\targs: ['file', 'show', '-r', args.revision, toJjRootFileFileset(args.relativePath)],\n\t\t\tcwd: args.repoRoot,\n\t\t});\n\t\treturn stdout;\n\t} catch (error) {\n\t\tif (isMissingFileAtRevisionError(error)) {\n\t\t\treturn '';\n\t\t}\n\t\tthrow error;\n\t}\n}\n\nasync function jjTouchesFile(args: { repoRoot: string; revision: string; relativePath: string }): Promise<boolean> {\n\tconst { stdout } = await run({\n\t\tcommand: 'jj',\n\t\targs: ['diff', '--name-only', '-r', args.revision],\n\t\tcwd: args.repoRoot,\n\t});\n\treturn stdout\n\t\t.split(/\\r?\\n/)\n\t\t.map((line) => line.trim())\n\t\t.filter(Boolean)\n\t\t.includes(args.relativePath);\n}\n\nasync function listGitRevisionFiles(args: { repoRoot: string; revision: string }): Promise<string[]> {\n\tconst { stdout } = await run({\n\t\tcommand: 'git',\n\t\targs: ['diff-tree', '--root', '--no-commit-id', '--name-only', '-r', args.revision],\n\t\tcwd: args.repoRoot,\n\t});\n\treturn stdout\n\t\t.split(/\\r?\\n/u)\n\t\t.map((line) => line.trim())\n\t\t.filter(Boolean);\n}\n\nasync function resolveGitParentRevision(args: { repoRoot: string; revision: string }): Promise<string | undefined> {\n\ttry {\n\t\tconst { stdout } = await run({\n\t\t\tcommand: 'git',\n\t\t\targs: ['rev-parse', `${args.revision}^`],\n\t\t\tcwd: args.repoRoot,\n\t\t});\n\t\tconst parentRevision = stdout.trim();\n\t\treturn parentRevision || undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nasync function listGitWorkingTreeFiles(args: { repoRoot: string }): Promise<string[]> {\n\tconst files = new Set<string>();\n\n\ttry {\n\t\tconst { stdout } = await run({ command: 'git', args: ['diff', '--name-only', 'HEAD', '--'], cwd: args.repoRoot });\n\t\tfor (const relativePath of stdout\n\t\t\t.split(/\\r?\\n/u)\n\t\t\t.map((line) => line.trim())\n\t\t\t.filter(Boolean)) {\n\t\t\tfiles.add(relativePath);\n\t\t}\n\t} catch {\n\t\t// Ignore.\n\t}\n\n\treturn [...files].toSorted((left, right) => left.localeCompare(right));\n}\n\nasync function listJjRevisionFiles(args: { repoRoot: string; revision: string }): Promise<string[]> {\n\tconst { stdout } = await run({\n\t\tcommand: 'jj',\n\t\targs: ['diff', '--name-only', '-r', args.revision],\n\t\tcwd: args.repoRoot,\n\t});\n\treturn stdout\n\t\t.split(/\\r?\\n/u)\n\t\t.map((line) => line.trim())\n\t\t.filter(Boolean);\n}\n\nasync function listJjChangedFiles(args: { repoRoot: string; base: string; target: string }): Promise<string[]> {\n\tconst { stdout } = await run({\n\t\tcommand: 'jj',\n\t\targs: ['diff', '--name-only', '--from', args.base, '--to', args.target],\n\t\tcwd: args.repoRoot,\n\t});\n\treturn stdout\n\t\t.split(/\\r?\\n/u)\n\t\t.map((line) => line.trim())\n\t\t.filter(Boolean);\n}\n\nasync function buildStandaloneEntryMultiDiffPlan(args: {\n\trepoRoot: string;\n\tfileFixture: TimelineFixtureFile;\n\tentryIndex: number;\n\tcomparisonSource: ComparisonSource;\n}): Promise<{\n\ttitle: string;\n\tfiles: Array<{\n\t\trelativePath: string;\n\t\toriginalRevset: string;\n\t\tmodifiedRevset: string;\n\t\tbackend: HistoryBackend;\n\t}>;\n}> {\n\tconst backend = args.fileFixture.timelineData.backend;\n\tconst sourceEntries = getEntriesForSource(args.fileFixture.timelineData, args.comparisonSource);\n\tconst entry = sourceEntries[args.entryIndex];\n\tif (!entry) {\n\t\treturn { title: '', files: [] };\n\t}\n\n\tif (backend === 'git') {\n\t\tif (entry.isWorkingTree) {\n\t\t\tconst previousEntry = sourceEntries[Math.max(0, args.entryIndex - 1)];\n\t\t\tif (!previousEntry) {\n\t\t\t\treturn { title: entry.shortRevision, files: [] };\n\t\t\t}\n\n\t\t\tconst files = await listGitWorkingTreeFiles({ repoRoot: args.repoRoot });\n\t\t\treturn {\n\t\t\t\ttitle: `${previousEntry.shortRevision}..${entry.shortRevision}`,\n\t\t\t\tfiles: files.map((relativePath) => ({\n\t\t\t\t\trelativePath,\n\t\t\t\t\toriginalRevset: previousEntry.revision,\n\t\t\t\t\tmodifiedRevset: '@',\n\t\t\t\t\tbackend,\n\t\t\t\t})),\n\t\t\t};\n\t\t}\n\n\t\tconst files = await listGitRevisionFiles({ repoRoot: args.repoRoot, revision: entry.revision });\n\t\tconst parentRevision = await resolveGitParentRevision({ repoRoot: args.repoRoot, revision: entry.revision });\n\t\treturn {\n\t\t\ttitle: entry.shortRevision,\n\t\t\tfiles: files.map((relativePath) => ({\n\t\t\t\trelativePath,\n\t\t\t\toriginalRevset: parentRevision || 'EMPTY',\n\t\t\t\tmodifiedRevset: entry.revision,\n\t\t\t\tbackend,\n\t\t\t})),\n\t\t};\n\t}\n\n\tif (entry.isWorkingTree) {\n\t\tconst previousEntry = sourceEntries[Math.max(0, args.entryIndex - 1)];\n\t\tif (!previousEntry) {\n\t\t\treturn { title: entry.shortRevision, files: [] };\n\t\t}\n\n\t\tconst files = await listJjChangedFiles({ repoRoot: args.repoRoot, base: previousEntry.revision, target: '@' });\n\t\treturn {\n\t\t\ttitle: `${previousEntry.shortRevision}..${entry.shortRevision}`,\n\t\t\tfiles: files.map((relativePath) => ({\n\t\t\t\trelativePath,\n\t\t\t\toriginalRevset: previousEntry.revision,\n\t\t\t\tmodifiedRevset: '@',\n\t\t\t\tbackend,\n\t\t\t})),\n\t\t};\n\t}\n\n\tconst baseRevision =\n\t\targs.comparisonSource === 'snapshot'\n\t\t\t? sourceEntries[Math.max(0, args.entryIndex - 1)]?.revision || `${entry.revision}-`\n\t\t\t: `${entry.revision}-`;\n\tconst files =\n\t\targs.comparisonSource === 'snapshot'\n\t\t\t? await listJjChangedFiles({ repoRoot: args.repoRoot, base: baseRevision, target: entry.revision })\n\t\t\t: await listJjRevisionFiles({ repoRoot: args.repoRoot, revision: entry.revision });\n\treturn {\n\t\ttitle: entry.shortRevision,\n\t\tfiles: files.map((relativePath) => ({\n\t\t\trelativePath,\n\t\t\toriginalRevset: baseRevision,\n\t\t\tmodifiedRevset: entry.revision,\n\t\t\tbackend,\n\t\t})),\n\t};\n}\n\nasync function buildStandaloneRangeMultiDiffPlan(args: {\n\trepoRoot: string;\n\tfileFixture: TimelineFixtureFile;\n\tfromIndex: number;\n\ttoIndex: number;\n\tcomparisonSource: ComparisonSource;\n\tselectedEntryIndexes: number[];\n}) {\n\tconst sourceEntries = getEntriesForSource(args.fileFixture.timelineData, args.comparisonSource);\n\tconst fromEntry = sourceEntries[Math.min(args.fromIndex, args.toIndex)];\n\tconst toEntry = sourceEntries[Math.max(args.fromIndex, args.toIndex)];\n\tconst title = fromEntry && toEntry ? `${fromEntry.shortRevision}..${toEntry.shortRevision}` : 'Selection';\n\tif (!args.selectedEntryIndexes.length) {\n\t\treturn { title, files: [] };\n\t}\n\n\tconst plans = await Promise.all(\n\t\targs.selectedEntryIndexes.map((entryIndex) =>\n\t\t\tbuildStandaloneEntryMultiDiffPlan({\n\t\t\t\trepoRoot: args.repoRoot,\n\t\t\t\tfileFixture: args.fileFixture,\n\t\t\t\tentryIndex,\n\t\t\t\tcomparisonSource: args.comparisonSource,\n\t\t\t}),\n\t\t),\n\t);\n\n\treturn {\n\t\ttitle,\n\t\tfiles: plans.flatMap((plan) => plan.files),\n\t};\n}\n\nasync function getStandaloneEntryDiffCount(args: {\n\trepoRoot: string;\n\tfileFixture: TimelineFixtureFile;\n\tentryIndex: number;\n\tcomparisonSource: ComparisonSource;\n}): Promise<number> {\n\tconst plan = await buildStandaloneEntryMultiDiffPlan(args);\n\treturn plan.files.length;\n}\n\nasync function openMultiDiffWithEditor(args: {\n\trepoRoot: string;\n\teditorCommand: string;\n\tfiles: Array<{\n\t\trelativePath: string;\n\t\toriginalRevset: string;\n\t\tmodifiedRevset: string;\n\t\tbackend: HistoryBackend;\n\t}>;\n}): Promise<void> {\n\tconst { command, args: baseArgs } = parseEditorCommand(args.editorCommand);\n\tconst tempRoot = path.join(os.tmpdir(), 'jj-plus-editor', `${Date.now()}`);\n\tawait fs.mkdir(tempRoot, { recursive: true });\n\n\tfor (const [index, file] of args.files.entries()) {\n\t\tconst originalPath = await materializeEditorDiffSide({\n\t\t\trepoRoot: args.repoRoot,\n\t\t\tbackend: file.backend,\n\t\t\trevset: file.originalRevset,\n\t\t\trelativePath: file.relativePath,\n\t\t\ttempRoot,\n\t\t\tsuffix: `${index}-original`,\n\t\t});\n\t\tconst modifiedPath = await materializeEditorDiffSide({\n\t\t\trepoRoot: args.repoRoot,\n\t\t\tbackend: file.backend,\n\t\t\trevset: file.modifiedRevset,\n\t\t\trelativePath: file.relativePath,\n\t\t\ttempRoot,\n\t\t\tsuffix: `${index}-modified`,\n\t\t});\n\n\t\tawait spawnDetached(command, [...baseArgs, '--reuse-window', '--diff', originalPath, modifiedPath]);\n\t}\n}\n\nasync function materializeEditorDiffSide(args: {\n\trepoRoot: string;\n\tbackend: HistoryBackend;\n\trevset: string;\n\trelativePath: string;\n\ttempRoot: string;\n\tsuffix: string;\n}): Promise<string> {\n\tconst safePath = args.relativePath.replace(/[^a-zA-Z0-9._/-]+/g, '_');\n\tconst targetPath = path.join(args.tempRoot, `${args.suffix}-${safePath}`);\n\tawait fs.mkdir(path.dirname(targetPath), { recursive: true });\n\tconst content = await readStandaloneRevsetFile({\n\t\trepoRoot: args.repoRoot,\n\t\tbackend: args.backend,\n\t\trevset: args.revset,\n\t\trelativePath: args.relativePath,\n\t});\n\tawait fs.writeFile(targetPath, content, 'utf8');\n\treturn targetPath;\n}\n\nasync function readStandaloneRevsetFile(args: {\n\trepoRoot: string;\n\tbackend: HistoryBackend;\n\trevset: string;\n\trelativePath: string;\n}): Promise<string> {\n\tif (args.revset === 'EMPTY') {\n\t\treturn '';\n\t}\n\n\tif (args.revset === '@') {\n\t\ttry {\n\t\t\treturn await fs.readFile(path.join(args.repoRoot, args.relativePath), 'utf8');\n\t\t} catch (error) {\n\t\t\tif (isMissingFileError(error)) {\n\t\t\t\treturn '';\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\treturn args.backend === 'jj'\n\t\t? showJjFileAtRevision({ repoRoot: args.repoRoot, revision: args.revset, relativePath: args.relativePath })\n\t\t: showGitFileAtRevision({ repoRoot: args.repoRoot, revision: args.revset, relativePath: args.relativePath });\n}\n\nfunction parseEditorCommand(editorCommand: string): { command: string; args: string[] } {\n\tconst parts = editorCommand.trim().split(/\\s+/u).filter(Boolean);\n\tif (!parts.length) {\n\t\tthrow new Error('Missing editor command.');\n\t}\n\n\treturn {\n\t\tcommand: parts[0],\n\t\targs: parts.slice(1),\n\t};\n}\n\nasync function spawnDetached(command: string, args: string[]): Promise<void> {\n\tawait new Promise<void>((resolve, reject) => {\n\t\tconst child = spawn(command, args, { detached: true, stdio: 'ignore' });\n\t\tchild.once('error', reject);\n\t\tchild.once('spawn', () => {\n\t\t\tchild.unref();\n\t\t\tresolve();\n\t\t});\n\t});\n}\n\nasync function buildRangeOverview(args: {\n\trepoRoot: string;\n\tfileFixture: TimelineFixtureFile;\n\tcurrentRelativePath: string;\n\tfromIndex: number;\n\ttoIndex: number;\n\tcomparisonSource: ComparisonSource;\n\tselectedEntryIndexes?: number[];\n}): Promise<RangeOverviewItem[]> {\n\tconst sourceEntries = getEntriesForSource(args.fileFixture.timelineData, args.comparisonSource);\n\tconst workspaceFileSet = new Set(args.fileFixture.timelineData.workspaceFiles || []);\n\tconst countedPaths = new Map<string, number>();\n\tconst entryIndexesToScan = args.selectedEntryIndexes?.length\n\t\t? args.selectedEntryIndexes\n\t\t: Array.from({ length: args.toIndex - args.fromIndex }, (_, index) => args.fromIndex + index + 1);\n\n\tfor (const index of entryIndexesToScan) {\n\t\tconst entry = sourceEntries[index];\n\t\tif (!entry) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst changedFiles =\n\t\t\targs.fileFixture.timelineData.backend === 'git'\n\t\t\t\t? entry.isWorkingTree\n\t\t\t\t\t? await listGitWorkingTreeFiles({ repoRoot: args.repoRoot })\n\t\t\t\t\t: await listGitRevisionFiles({ repoRoot: args.repoRoot, revision: entry.revision })\n\t\t\t\t: entry.isWorkingTree\n\t\t\t\t\t? await listJjRevisionFiles({ repoRoot: args.repoRoot, revision: '@' })\n\t\t\t\t\t: await listJjRevisionFiles({ repoRoot: args.repoRoot, revision: entry.revision });\n\n\t\tfor (const relativePath of changedFiles) {\n\t\t\tif (!relativePath || (!workspaceFileSet.has(relativePath) && relativePath !== args.currentRelativePath)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcountedPaths.set(relativePath, (countedPaths.get(relativePath) || 0) + 1);\n\t\t}\n\t}\n\n\treturn [...countedPaths.entries()]\n\t\t.map(([relativePath, changeCount]) => ({\n\t\t\trelativePath,\n\t\t\tchangeCount,\n\t\t\tisCurrentFile: relativePath === args.currentRelativePath,\n\t\t}))\n\t\t.toSorted((left, right) => {\n\t\t\tif (left.changeCount !== right.changeCount) {\n\t\t\t\treturn right.changeCount - left.changeCount;\n\t\t\t}\n\n\t\t\tif (left.isCurrentFile !== right.isCurrentFile) {\n\t\t\t\treturn Number(right.isCurrentFile) - Number(left.isCurrentFile);\n\t\t\t}\n\n\t\t\treturn left.relativePath.localeCompare(right.relativePath);\n\t\t})\n\t\t.slice(0, 150);\n}\n\nasync function getWorkspaceFiles(repoRoot: string): Promise<string[]> {\n\ttry {\n\t\tconst { stdout } = await run({ command: 'jj', args: ['file', 'list'], cwd: repoRoot });\n\t\treturn stdout\n\t\t\t.split(/\\r?\\n/)\n\t\t\t.filter(Boolean)\n\t\t\t.toSorted((left, right) => left.localeCompare(right));\n\t} catch {\n\t\ttry {\n\t\t\tconst { stdout } = await run({\n\t\t\t\tcommand: 'git',\n\t\t\t\targs: ['ls-files', '--cached'],\n\t\t\t\tcwd: repoRoot,\n\t\t\t});\n\t\t\treturn stdout\n\t\t\t\t.split(/\\r?\\n/)\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.toSorted((left, right) => left.localeCompare(right));\n\t\t} catch {\n\t\t\tconst files: string[] = [];\n\t\t\tawait collectWorkspaceFiles({ repoRoot, currentDir: repoRoot, files });\n\t\t\treturn files.toSorted((left, right) => left.localeCompare(right));\n\t\t}\n\t}\n}\n\nasync function collectWorkspaceFiles(args: { repoRoot: string; currentDir: string; files: string[] }): Promise<void> {\n\tconst entries = await fs.readdir(args.currentDir, { withFileTypes: true });\n\tfor (const entry of entries) {\n\t\tif (ignoredWorkspaceEntries.has(entry.name)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst absolutePath = path.join(args.currentDir, entry.name);\n\t\tif (entry.isDirectory()) {\n\t\t\tawait collectWorkspaceFiles({ repoRoot: args.repoRoot, currentDir: absolutePath, files: args.files });\n\t\t\tcontinue;\n\t\t}\n\t\tif (!entry.isFile()) {\n\t\t\tcontinue;\n\t\t}\n\n\t\targs.files.push(normalizePath(path.relative(args.repoRoot, absolutePath)));\n\t}\n}\n\nasync function makeWorkingTreeEntry(args: {\n\trepoRoot: string;\n\tpreviousEntry?: FileRevisionEntry;\n\trelativePath: string;\n\tbackend: HistoryBackend;\n\tremoteBaseUrl?: string;\n}): Promise<FileRevisionEntry | null> {\n\tlet content = '';\n\tlet stats: Awaited<ReturnType<typeof fs.stat>> | null = null;\n\ttry {\n\t\tstats = await fs.stat(path.join(args.repoRoot, args.relativePath));\n\t\tcontent = await fs.readFile(path.join(args.repoRoot, args.relativePath), 'utf8');\n\t} catch (error) {\n\t\tif (!isMissingFileError(error)) {\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tconst previousContent = args.previousEntry\n\t\t? args.previousEntry.isWorkingTree\n\t\t\t? content\n\t\t\t: args.backend === 'jj'\n\t\t\t\t? await showJjFileAtRevision({\n\t\t\t\t\t\trepoRoot: args.repoRoot,\n\t\t\t\t\t\trevision: args.previousEntry.revision,\n\t\t\t\t\t\trelativePath: args.previousEntry.filePath || args.relativePath,\n\t\t\t\t\t})\n\t\t\t\t: await showGitFileAtRevision({\n\t\t\t\t\t\trepoRoot: args.repoRoot,\n\t\t\t\t\t\trevision: args.previousEntry.revision,\n\t\t\t\t\t\trelativePath: args.previousEntry.filePath || args.relativePath,\n\t\t\t\t\t})\n\t\t: '';\n\tif (content === previousContent) {\n\t\treturn null;\n\t}\n\n\treturn makeEntry({\n\t\tid: `working-tree:${args.relativePath}`,\n\t\tindex: args.previousEntry ? (args.previousEntry.index || 0) + 1 : 0,\n\t\trevision: 'WORKTREE',\n\t\tshortRevision: 'Current',\n\t\tchangeId: undefined,\n\t\tauthorDate: (stats?.mtime || new Date()).toISOString(),\n\t\tauthorName: process.env.GIT_AUTHOR_NAME || process.env.USER || 'CLI User',\n\t\tdescription: 'Working tree',\n\t\ttouchesFile: true,\n\t\tisWorkingTree: true,\n\t\tfilePath: args.relativePath,\n\t\tremoteBaseUrl: args.remoteBaseUrl,\n\t});\n}\n\nfunction makeEntry(args: {\n\tid: string;\n\tindex: number;\n\trevision: string;\n\tshortRevision: string;\n\tchangeId?: string;\n\tbookmarkNames?: string[];\n\tbranchNames?: string[];\n\tauthorDate: string;\n\tauthorName: string;\n\tdescription: string;\n\ttouchesFile: boolean;\n\tisWorkingTree: boolean;\n\tfilePath?: string;\n\toperationId?: string;\n\toperationIndex?: number;\n\toperationKey?: string;\n\tremoteBaseUrl?: string;\n\tisEmpty?: boolean;\n\thasConflict?: boolean;\n\tisImmutable?: boolean;\n}): FileRevisionEntry {\n\tconst timestamp = Date.parse(args.authorDate);\n\treturn {\n\t\tid: args.id,\n\t\tindex: args.index,\n\t\trevision: args.revision,\n\t\tshortRevision: args.shortRevision,\n\t\tchangeId: args.changeId,\n\t\tbookmarkNames: args.bookmarkNames,\n\t\tbranchNames: args.branchNames,\n\t\tauthorDate: args.authorDate,\n\t\tauthorName: args.authorName,\n\t\tdescription: args.description || '',\n\t\tisWorkingTree: args.isWorkingTree,\n\t\ttouchesFile: args.touchesFile,\n\t\ttimestamp,\n\t\tfilePath: args.filePath,\n\t\toperationId: args.operationId,\n\t\toperationIndex: args.operationIndex,\n\t\toperationKey: args.operationKey,\n\t\tmonthLabel: monthFormatter.format(timestamp),\n\t\tshortDate: shortDateFormatter.format(timestamp),\n\t\trelativeDate: relativeTime(timestamp),\n\t\thasPreviousEntry: args.index > 0,\n\t\tremoteUrl: args.isWorkingTree || !args.remoteBaseUrl ? undefined : `${args.remoteBaseUrl}/commit/${args.revision}`,\n\t\t...(args.isEmpty ? { isEmpty: true } : {}),\n\t\t...(args.hasConflict ? { hasConflict: true } : {}),\n\t\t...(args.isImmutable ? { isImmutable: true } : {}),\n\t};\n}\n\nfunction reindexEntries(entries: FileRevisionEntry[]): FileRevisionEntry[] {\n\treturn entries.map((entry, index) => ({ ...entry, index, hasPreviousEntry: index > 0 }));\n}\n\nfunction normalizeSnapshotAuthorDate(authorDate: string, fallbackAuthorDate: string): string {\n\tconst value = String(authorDate || '').trim();\n\tif (value && !Number.isNaN(Date.parse(value))) {\n\t\treturn value;\n\t}\n\n\treturn fallbackAuthorDate;\n}\n\nfunction normalizeSnapshotDescription(description: string, operationDescription: string): string {\n\tconst trimmed = String(description || '').trim();\n\tif (!trimmed || trimmed === '(no description set)' || trimmed === '(empty) (no description set)') {\n\t\treturn operationDescription || 'Snapshot';\n\t}\n\n\treturn trimmed;\n}\n\nfunction relativeTime(timestamp: number): string {\n\tconst deltaHours = Math.round((Date.now() - timestamp) / (1000 * 60 * 60));\n\tif (deltaHours <= 1) {\n\t\treturn 'this minute';\n\t}\n\tif (deltaHours < 36) {\n\t\treturn 'yesterday';\n\t}\n\tif (deltaHours < 24 * 30) {\n\t\treturn `${Math.round(deltaHours / 24)} days ago`;\n\t}\n\n\treturn `${Math.round(deltaHours / (24 * 30))} months ago`;\n}\n\nasync function resolveRepoContext(workspacePath: string): Promise<RepoContext> {\n\tconst [gitResult, jjResult] = await Promise.allSettled([\n\t\trun({ command: 'git', args: ['rev-parse', '--show-toplevel'], cwd: workspacePath }),\n\t\trun({ command: 'jj', args: ['root'], cwd: workspacePath }),\n\t]);\n\tconst gitRoot = gitResult.status === 'fulfilled' ? gitResult.value.stdout.trim() : undefined;\n\tconst jjRoot = jjResult.status === 'fulfilled' ? jjResult.value.stdout.trim() : undefined;\n\tconst backend = resolvePreferredHistoryBackend({ workspacePath, gitRoot, jjRoot });\n\n\tif (backend === 'jj' && jjRoot) {\n\t\treturn { backend: 'jj', repoRoot: jjRoot, remoteBaseUrl: await resolveRemoteBaseUrl(jjRoot) };\n\t}\n\n\tif (backend === 'git' && gitRoot) {\n\t\treturn { backend: 'git', repoRoot: gitRoot, remoteBaseUrl: await resolveRemoteBaseUrl(gitRoot) };\n\t}\n\n\tthrow new Error('Standalone timeline requires a Git or JJ repository.');\n}\n\nasync function resolveRemoteBaseUrl(repoRoot: string): Promise<string | undefined> {\n\ttry {\n\t\tconst { stdout } = await run({ command: 'git', args: ['remote', 'get-url', 'origin'], cwd: repoRoot });\n\t\treturn getGitHubRemoteBaseUrl(stdout.trim());\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction extractPersistedPreferences(\n\tcommand: Extract<TimelineCommand, { command: 'persist-state' }>,\n): Partial<TimelinePreferences> {\n\treturn {\n\t\tsidebarWidth: command.sidebarWidth,\n\t\tsidebarCollapsed: command.sidebarCollapsed,\n\t\ttimelinePaneHeight: command.timelinePaneHeight,\n\t\ttimelinePaneCollapsed: command.timelinePaneCollapsed,\n\t\tlayoutMode: command.layoutMode,\n\t\tcontentMode: command.contentMode,\n\t\tcomparisonMode: command.comparisonMode,\n\t\tcomparisonSource: command.comparisonSource,\n\t\tshowIntermediateRevisions: command.showIntermediateRevisions,\n\t\tpreset: command.preset,\n\t\tthemePreference: command.themePreference,\n\t\theatmapOpen: command.heatmapOpen === true,\n\t\tlineDiffType: command.lineDiffType,\n\t};\n}\n\nfunction getFixturePreview(args: {\n\tfileFixture: TimelineFixtureFile;\n\tfromIndex: number;\n\ttoIndex: number;\n\tcomparisonSource: ComparisonSource;\n}): DiffPreview {\n\tconst normalizedFromIndex = Math.min(args.fromIndex, args.toIndex);\n\tconst normalizedToIndex = Math.max(args.fromIndex, args.toIndex);\n\tconst key = `${normalizedFromIndex}:${normalizedToIndex}`;\n\tconst previewMap = args.fileFixture.previews[args.comparisonSource] || args.fileFixture.previews.revision || {};\n\tconst preview = previewMap[key];\n\tif (preview) {\n\t\treturn clone(preview);\n\t}\n\n\treturn {\n\t\tindex: normalizedToIndex,\n\t\ttitle: 'No diff available',\n\t\tsubtitle: '',\n\t\tdiffCount: 0,\n\t\tadditions: 0,\n\t\tdeletions: 0,\n\t\thunkCount: 0,\n\t\thasChanges: false,\n\t\tfromIndex: normalizedFromIndex,\n\t\ttoIndex: normalizedToIndex,\n\t\tcomparisonSource: args.comparisonSource,\n\t\tbeforePath: '',\n\t\tafterPath: '',\n\t\tbeforeText: '',\n\t\tafterText: '',\n\t\tnonTextualDetails: [],\n\t};\n}\n\nfunction resolveNonEmptyRange(\n\tfileFixture: TimelineFixtureFile,\n\tcandidateIndexes: number[],\n): { fromIndex: number; toIndex: number } | null {\n\tconst previewMap = fileFixture.previews.revision || {};\n\tfor (let index = candidateIndexes.length - 1; index > 0; index -= 1) {\n\t\tconst fromIndex = candidateIndexes[index - 1];\n\t\tconst toIndex = candidateIndexes[index];\n\t\tconst key = `${Math.min(fromIndex, toIndex)}:${Math.max(fromIndex, toIndex)}`;\n\t\tif (previewMap[key]?.hasChanges) {\n\t\t\treturn { fromIndex, toIndex };\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction getUnitPreview(args: {\n\tfileFixture: TimelineFixtureFile;\n\tentryIndex: number;\n\tcomparisonSource: ComparisonSource;\n}): DiffPreview | null {\n\tconst sourceEntries = getEntriesForSource(args.fileFixture.timelineData, args.comparisonSource);\n\tconst currentIndex = sourceEntries.findIndex((entry) => entry.index === args.entryIndex);\n\tif (currentIndex <= 0) {\n\t\treturn null;\n\t}\n\n\treturn getFixturePreview({\n\t\tfileFixture: args.fileFixture,\n\t\tfromIndex: sourceEntries[currentIndex - 1].index || 0,\n\t\ttoIndex: sourceEntries[currentIndex].index || 0,\n\t\tcomparisonSource: args.comparisonSource,\n\t});\n}\n\nasync function openPreviewDocument(args: { preview: DiffPreview; relativePath: string }): Promise<void> {\n\tconst previewDirectory = path.join(os.tmpdir(), 'jj-plus-previews');\n\tawait fs.mkdir(previewDirectory, { recursive: true });\n\tconst sanitizedPath = args.relativePath.replace(/[^a-zA-Z0-9._-]+/g, '_');\n\tconst previewPath = path.join(previewDirectory, `${Date.now()}-${sanitizedPath}.diff.txt`);\n\tawait fs.writeFile(previewPath, renderPreviewText(args.preview, args.relativePath), 'utf8');\n\tawait openTarget(previewPath);\n}\n\nexport function renderPreviewText(preview: DiffPreview, relativePath: string): string {\n\tconst summary = `+${preview.additions} -${preview.deletions} ${preview.hunkCount} hunks`;\n\tconst detailLines = preview.nonTextualDetails?.length ? [...preview.nonTextualDetails, ''] : [];\n\tconst pathLines = [`--- ${preview.beforePath || relativePath}`, `+++ ${preview.afterPath || relativePath}`, ''];\n\tconst contentLines = ['===== before =====', preview.beforeText, '===== after =====', preview.afterText];\n\n\treturn [\n\t\trelativePath,\n\t\tpreview.title,\n\t\tpreview.subtitle,\n\t\tsummary,\n\t\t'',\n\t\t...detailLines,\n\t\t...pathLines,\n\t\t...contentLines,\n\t\t'',\n\t].join('\\n');\n}\n\nasync function openTarget(target: string): Promise<void> {\n\tconst launcher = getSystemLauncher(target);\n\tawait new Promise<void>((resolve, reject) => {\n\t\tconst child = spawn(launcher.command, launcher.args, { detached: true, stdio: 'ignore' });\n\t\tchild.once('error', reject);\n\t\tchild.once('spawn', () => {\n\t\t\tchild.unref();\n\t\t\tresolve();\n\t\t});\n\t});\n}\n\nfunction getSystemLauncher(target: string): { command: string; args: string[] } {\n\tif (process.platform === 'darwin') {\n\t\treturn { command: 'open', args: [target] };\n\t}\n\tif (process.platform === 'win32') {\n\t\treturn { command: 'cmd', args: ['/c', 'start', '', target] };\n\t}\n\treturn { command: 'xdg-open', args: [target] };\n}\n\nasync function ensureDistReady(): Promise<void> {\n\tconst assetPaths = distAssets.map((assetPath) => path.join(distDir, assetPath));\n\tconst hasAllAssets = assetPaths.every((assetPath) => fsSync.existsSync(assetPath));\n\tif (!hasAllAssets || (await isDistStale(assetPaths))) {\n\t\tawait buildWebviewDist();\n\t}\n\n\tif (!assetPaths.every((assetPath) => fsSync.existsSync(assetPath))) {\n\t\tthrow new Error('Missing webview-dist assets. Run pnpm build:webview before launching the standalone timeline.');\n\t}\n}\n\nasync function isDistStale(assetPaths: string[]): Promise<boolean> {\n\tconst sourcePaths = await collectBuildInputFiles(path.join(rootDir, 'webview'));\n\tconst newestSourceTime = sourcePaths.length\n\t\t? Math.max(...(await Promise.all(sourcePaths.map((filePath) => fs.stat(filePath).then((stats) => stats.mtimeMs)))))\n\t\t: 0;\n\tconst oldestDistTime = Math.min(\n\t\t...(await Promise.all(assetPaths.map((assetPath) => fs.stat(assetPath).then((stats) => stats.mtimeMs)))),\n\t);\n\treturn newestSourceTime > oldestDistTime;\n}\n\nasync function collectBuildInputFiles(currentPath: string): Promise<string[]> {\n\tconst entries = await fs.readdir(currentPath, { withFileTypes: true });\n\tconst filePaths: string[] = [];\n\n\tfor (const entry of entries) {\n\t\tconst absolutePath = path.join(currentPath, entry.name);\n\t\tif (entry.isDirectory()) {\n\t\t\tfilePaths.push(...(await collectBuildInputFiles(absolutePath)));\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (entry.isFile()) {\n\t\t\tfilePaths.push(absolutePath);\n\t\t}\n\t}\n\n\treturn filePaths;\n}\n\nasync function buildWebviewDist(): Promise<void> {\n\tconst pnpmCommand = process.platform === 'win32' ? 'pnpm.cmd' : 'pnpm';\n\ttry {\n\t\tawait run({ command: pnpmCommand, args: ['build:webview'], cwd: rootDir });\n\t\treturn;\n\t} catch (error) {\n\t\tconst spawnError =\n\t\t\terror && typeof error === 'object' && 'code' in error ? (error as NodeJS.ErrnoException).code : undefined;\n\t\tif (spawnError === 'ENOENT') {\n\t\t\ttry {\n\t\t\t\tawait run({ command: 'corepack', args: ['pnpm', 'build:webview'], cwd: rootDir });\n\t\t\t\treturn;\n\t\t\t} catch {\n\t\t\t\t// Fall through to wrapped error.\n\t\t\t}\n\t\t}\n\n\t\tconst cause = error instanceof Error ? error : new Error(String(error));\n\t\tcause.message = `Failed to build the standalone webview assets automatically: ${cause.message}`;\n\t\tthrow cause;\n\t}\n}\n\nfunction resolveStaticPath(requestPath: string): string | null {\n\tconst rawPath = requestPath === '/' ? '/index.html' : requestPath;\n\tconst decodedPath = decodeURIComponent(rawPath);\n\tconst candidatePath = path.normalize(path.join(distDir, decodedPath));\n\tif (candidatePath !== distDir && !candidatePath.startsWith(`${distDir}${path.sep}`)) {\n\t\treturn null;\n\t}\n\treturn candidatePath;\n}\n\nfunction getContentType(filePath: string): string {\n\tconst extension = path.extname(filePath).toLowerCase();\n\tif (extension === '.html') {\n\t\treturn 'text/html; charset=utf-8';\n\t}\n\tif (extension === '.js') {\n\t\treturn 'application/javascript; charset=utf-8';\n\t}\n\tif (extension === '.css') {\n\t\treturn 'text/css; charset=utf-8';\n\t}\n\tif (extension === '.json') {\n\t\treturn 'application/json; charset=utf-8';\n\t}\n\tif (extension === '.svg') {\n\t\treturn 'image/svg+xml';\n\t}\n\treturn 'application/octet-stream';\n}\n\nasync function readJsonBody(request: IncomingMessage): Promise<unknown> {\n\tconst chunks: Buffer[] = [];\n\tlet totalBytes = 0;\n\tfor await (const chunk of request) {\n\t\tconst bufferChunk = typeof chunk === 'string' ? Buffer.from(chunk) : Buffer.from(chunk);\n\t\ttotalBytes += bufferChunk.length;\n\t\tif (totalBytes > 1024 * 1024) {\n\t\t\tthrow new Error('Request body is too large.');\n\t\t}\n\t\tchunks.push(bufferChunk);\n\t}\n\n\tconst text = Buffer.concat(chunks).toString('utf8');\n\treturn text ? JSON.parse(text) : {};\n}\n\nfunction writeJson(response: ServerResponse, statusCode: number, payload: unknown): void {\n\tresponse.writeHead(statusCode, {\n\t\t'content-type': 'application/json; charset=utf-8',\n\t\t'cache-control': 'no-store',\n\t});\n\tresponse.end(JSON.stringify(payload));\n}\n\nfunction isMissingFileAtRevisionError(error: unknown): boolean {\n\tconst message = error instanceof Error ? error.message : String(error);\n\treturn (\n\t\t/exists on disk, but not in/i.test(message) ||\n\t\t/path .* does not exist in/i.test(message) ||\n\t\t/no such path/i.test(message) ||\n\t\t/no matching entries/i.test(message) ||\n\t\t/No such file or directory/i.test(message) ||\n\t\t/Path .* not found/i.test(message)\n\t);\n}\n\nfunction isMissingFileError(error: unknown): boolean {\n\treturn Boolean(\n\t\terror && typeof error === 'object' && 'code' in error && (error as NodeJS.ErrnoException).code === 'ENOENT',\n\t);\n}\n\nfunction normalizePath(relativePath: string): string {\n\treturn relativePath.split(path.sep).join('/');\n}\n\nfunction clone<T>(value: T): T {\n\treturn JSON.parse(JSON.stringify(value)) as T;\n}\n\nasync function run(args: {\n\tcommand: string;\n\targs: string[];\n\tcwd: string;\n\tenv?: NodeJS.ProcessEnv;\n}): Promise<{ stdout: string; stderr: string }> {\n\treturn execFileAsync(args.command, args.args, {\n\t\tcwd: args.cwd,\n\t\tenv: { ...process.env, ...args.env },\n\t}) as Promise<{ stdout: string; stderr: string }>;\n}\n"],"mappings":"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"}
@@ -0,0 +1,214 @@
1
+ //#region src/webview/timeline-template.ts
2
+ function renderTimelineBodyHtml() {
3
+ return `<div class="app">
4
+ <section class="workspace" id="workspace">
5
+ <aside class="panel sidebar" id="sidebar">
6
+ <div class="sidebar-head">
7
+ <div class="sidebar-head-main">
8
+ <div class="eyebrow">Revisions</div>
9
+ <div class="sidebar-hint" id="sidebarHint"></div>
10
+ </div>
11
+ <button class="sidebar-head-action" id="openSidebarRangeDiffButton" type="button">Open selection diffs</button>
12
+ </div>
13
+ <div class="sidebar-search-wrap">
14
+ <input class="sidebar-search-input" id="sidebarSearchInput" type="search" placeholder="Search revisions" autocomplete="off" />
15
+ </div>
16
+ <div class="history-list" id="historyList"></div>
17
+ </aside>
18
+ <div class="resize-handle" id="resizeHandle"></div>
19
+ <section class="panel diff-panel">
20
+ <div class="timeline-pane" id="timelinePane">
21
+ <div class="timeline-pane-head">
22
+ <button class="sidebar-toggle-button" id="sidebarToggleButton" type="button" aria-label="Toggle sidebar">&#x25C2;</button>
23
+ <div class="timeline-pane-title">
24
+ <div class="eyebrow">Revision Timeline</div>
25
+ <span class="version-badge" id="timelineVersion"></span>
26
+ </div>
27
+ <div class="timeline-head-summary">
28
+ <div class="range-label" id="rangeLabel">Loading revisions...</div>
29
+ <div class="range-subtitle" id="rangeSubtitle"></div>
30
+ </div>
31
+ <button class="collapse-button" id="toggleTimelinePaneButton" type="button">Timeline only</button>
32
+ </div>
33
+ <div class="diff-head" id="timelineChrome">
34
+ <div class="diff-head-top">
35
+ <div class="file-switcher-row">
36
+ <input class="file-input" id="fileSwitcher" list="workspaceFilesList" placeholder="Switch file..." autocomplete="off" />
37
+ <datalist id="workspaceFilesList"></datalist>
38
+ </div>
39
+ <div class="head-actions">
40
+ <button class="menu-button" id="toggleHotkeysButton" type="button" aria-label="Show hotkeys">?</button>
41
+ <div class="menu-wrap">
42
+ <button class="menu-button" id="actionsButton" type="button">...</button>
43
+ <div class="menu" id="actionsMenu">
44
+ <button class="menu-item" id="toggleSidebarAction" type="button">Hide Sidebar</button>
45
+ <button class="menu-item" id="openCurrentFileAction" type="button">Open File</button>
46
+ <button class="menu-item" id="openEditorButton" type="button">Open single-file diff</button>
47
+ <button class="menu-item" id="openRangeFilesButton" type="button">Open multi-file diffs</button>
48
+ <button class="menu-item" id="cancelActiveRequestAction" type="button">Cancel request</button>
49
+ <button class="menu-item" id="refreshButton" type="button">Refresh</button>
50
+ </div>
51
+ </div>
52
+ </div>
53
+ </div>
54
+
55
+ <div class="timeline-head">
56
+ <div class="revision-picker-row">
57
+ <div class="revision-picker-col">
58
+ <input class="revision-input" id="fromRevisionInput" list="revisionOptionsList" placeholder="From revision" autocomplete="off" />
59
+ <div class="revision-picker-meta">
60
+ <button class="handle-pill from" id="fromHandleLabel" type="button">From</button>
61
+ <span class="revision-picker-relative" id="fromRelativeLabel"></span>
62
+ </div>
63
+ </div>
64
+ <span class="revision-arrow">&#8594;</span>
65
+ <div class="revision-picker-col">
66
+ <input class="revision-input" id="toRevisionInput" list="revisionOptionsList" placeholder="To revision" autocomplete="off" />
67
+ <div class="revision-picker-meta">
68
+ <button class="handle-pill to" id="toHandleLabel" type="button">To</button>
69
+ <span class="revision-picker-relative" id="toRelativeLabel"></span>
70
+ </div>
71
+ </div>
72
+ <datalist id="revisionOptionsList"></datalist>
73
+ </div>
74
+ <div class="control-row">
75
+ <div class="segmented" id="comparisonModes"></div>
76
+ <div class="segmented" id="comparisonSources"></div>
77
+ <div class="segmented" id="layoutModes"></div>
78
+ <div class="segmented" id="contentModes"></div>
79
+ <button class="toggle-chip" id="intermediateToggle" type="button" aria-label="In-Between revisions">In-Between</button>
80
+ <div class="segmented" id="presets"></div>
81
+ </div>
82
+ </div>
83
+
84
+ <div class="timeline-row">
85
+ <button class="step-button" id="stepFastBackwardButton" type="button" aria-label="Jump backward">&#171;</button>
86
+ <button class="step-button" id="stepBackwardButton" type="button" aria-label="Previous range">&#x2039;</button>
87
+ <div class="timeline">
88
+ <div class="selection-meta" id="selectionMeta"></div>
89
+ <div class="track" id="track"></div>
90
+ <div class="range-fill" id="rangeFill"></div>
91
+ <button class="handle-marker from" id="fromMarker" type="button" aria-label="Adjust from revision"></button>
92
+ <button class="handle-marker to" id="toMarker" type="button" aria-label="Adjust to revision"></button>
93
+ <div class="timeline-hover-axis" id="timelineHoverAxis" aria-hidden="true"></div>
94
+ </div>
95
+ <button class="step-button" id="stepForwardButton" type="button" aria-label="Next range">&#x203A;</button>
96
+ <button class="step-button" id="stepFastForwardButton" type="button" aria-label="Jump forward">&#187;</button>
97
+ </div>
98
+
99
+ <div class="step-status-row" id="stepStatusRow">
100
+ <div class="step-status" id="stepStatus"></div>
101
+ <div class="loading-indicator" id="snapshotLoadingIndicator" hidden>Loading snapshots&#8230;</div>
102
+ </div>
103
+ </div>
104
+ </div>
105
+ <div class="anchor-tooltip" id="anchorTooltip" hidden></div>
106
+ <div class="timeline-resize-handle" id="timelineResizeHandle"></div>
107
+ <div class="diff-content">
108
+ <div class="diff-summary">
109
+ <div class="diff-title-row">
110
+ <div class="diff-summary-left">
111
+ <div class="diff-title-block">
112
+ <h3 class="diff-title" id="diffTitle">Loading diff...</h3>
113
+ <div class="diff-title-meta" id="diffTitleMeta"></div>
114
+ </div>
115
+ <div class="diff-subtitle" id="diffSubtitle"></div>
116
+ </div>
117
+ <div class="diff-actions">
118
+ <div class="eyebrow diff-mode-eyebrow" id="diffModeEyebrow">Diff</div>
119
+ <div class="history-stats" id="diffStats"></div>
120
+ <button class="collapse-button" id="toggleDiffFocusButton" type="button">Focus diff</button>
121
+ </div>
122
+ </div>
123
+ </div>
124
+ <div class="diff-rows" id="diffRows"></div>
125
+ </div>
126
+ <div class="hotkeys-popover" id="hotkeysPopover" hidden>
127
+ <div class="hotkeys-card">
128
+ <div class="hotkeys-head">
129
+ <div>
130
+ <div style="display:flex;align-items:baseline;gap:6px;">
131
+ <div class="eyebrow">Shortcuts</div>
132
+ <div class="hotkeys-version" id="hotkeysVersion"></div>
133
+ </div>
134
+ <div class="hotkeys-subtitle">Range selection, sidebar navigation, and diff actions</div>
135
+ </div>
136
+ <button class="collapse-button" id="closeHotkeysButton" type="button">Close</button>
137
+ </div>
138
+ <div class="hotkeys-grid">
139
+ <div class="hotkey-section">
140
+ <div class="hotkey-section-title">Selection</div>
141
+ <div class="hotkey-row"><span class="hotkey-label">Move range</span><span class="hotkey-value"><kbd>←</kbd><kbd>→</kbd></span></div>
142
+ <div class="hotkey-row"><span class="hotkey-label">Fast move range</span><span class="hotkey-value"><kbd>Shift</kbd><kbd>←</kbd><kbd>→</kbd></span></div>
143
+ <div class="hotkey-row"><span class="hotkey-label">Move range vertically</span><span class="hotkey-value"><kbd>↑</kbd><kbd>↓</kbd></span></div>
144
+ <div class="hotkey-row"><span class="hotkey-label">Adjust to marker</span><span class="hotkey-value"><kbd>Option</kbd><kbd>←</kbd><kbd>→</kbd></span></div>
145
+ <div class="hotkey-row"><span class="hotkey-label">Adjust from marker</span><span class="hotkey-value"><kbd>Ctrl</kbd><kbd>←</kbd><kbd>→</kbd></span></div>
146
+ <div class="hotkey-row"><span class="hotkey-label">Dock range to start/end</span><span class="hotkey-value"><kbd>Cmd</kbd><kbd>←</kbd><kbd>→</kbd></span></div>
147
+ </div>
148
+ <div class="hotkey-section">
149
+ <div class="hotkey-section-title">Actions</div>
150
+ <div class="hotkey-row"><span class="hotkey-label">Open cumulative diff</span><span class="hotkey-value"><kbd>Space</kbd></span></div>
151
+ <div class="hotkey-row"><span class="hotkey-label">Toggle help</span><span class="hotkey-value"><kbd>?</kbd></span></div>
152
+ <div class="hotkey-row"><span class="hotkey-label">Toggle sidebar</span><span class="hotkey-value"><kbd>B</kbd></span></div>
153
+ <div class="hotkey-row"><span class="hotkey-label">Pick range by click</span><span class="hotkey-note">Click one revision, then another</span></div>
154
+ <div class="hotkey-row"><span class="hotkey-label">Drag markers</span><span class="hotkey-note">Adjust range directly on the timeline</span></div>
155
+ </div>
156
+ </div>
157
+ </div>
158
+ </div>
159
+ </section>
160
+ </section>
161
+ </div>`;
162
+ }
163
+ function renderTimelineDocumentHtml(options) {
164
+ const title = escapeHtml(options.title || "Revision Timeline");
165
+ const styleHref = escapeAttribute(options.styleHref || "./timeline.css");
166
+ const appSrc = escapeAttribute(options.appSrc || "");
167
+ const modelSrc = escapeAttribute(options.modelSrc || "");
168
+ const scriptSrc = escapeAttribute(options.scriptSrc || "");
169
+ const workerSrc = escapeAttribute(options.workerSrc || "");
170
+ const cspSource = options.cspSource;
171
+ const csp = cspSource ? `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src ${cspSource} https: data:; style-src ${cspSource}; script-src ${cspSource}; worker-src ${cspSource} blob:; connect-src ${cspSource};" />` : "";
172
+ const workerBoot = workerSrc.length > 0 ? `<script>window.WORKER_URI=${JSON.stringify(options.workerSrc)};<\/script>` : "";
173
+ if (appSrc) return `<!DOCTYPE html>
174
+ <html lang="en">
175
+ <head>
176
+ <meta charset="UTF-8" />
177
+ ${csp}
178
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
179
+ <title>${title}</title>
180
+ <link rel="stylesheet" href="${styleHref}" />
181
+ </head>
182
+ <body>
183
+ <div id="timelineApp"></div>
184
+ ${workerBoot}
185
+ <script type="module" src="${appSrc}"><\/script>
186
+ </body>
187
+ </html>`;
188
+ return `<!DOCTYPE html>
189
+ <html lang="en">
190
+ <head>
191
+ <meta charset="UTF-8" />
192
+ ${csp}
193
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
194
+ <title>${title}</title>
195
+ <link rel="stylesheet" href="${styleHref}" />
196
+ </head>
197
+ <body>
198
+ ${renderTimelineBodyHtml()}
199
+ ${workerBoot}
200
+ ${modelSrc ? `<script src="${modelSrc}"><\/script>` : ""}
201
+ ${scriptSrc ? `<script src="${scriptSrc}"><\/script>` : ""}
202
+ </body>
203
+ </html>`;
204
+ }
205
+ function escapeHtml(value) {
206
+ return String(value).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
207
+ }
208
+ function escapeAttribute(value) {
209
+ return escapeHtml(value).replace(/"/g, "&quot;");
210
+ }
211
+ //#endregion
212
+ exports.renderTimelineDocumentHtml = renderTimelineDocumentHtml;
213
+
214
+ //# sourceMappingURL=timeline-template.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline-template.cjs","names":[],"sources":["../../src/webview/timeline-template.ts"],"sourcesContent":["type TimelineDocumentHtmlOptions = {\n\ttitle?: string;\n\tstyleHref?: string;\n\tappSrc?: string;\n\tmodelSrc?: string;\n\tscriptSrc?: string;\n\tcspSource?: string;\n\tworkerSrc?: string;\n};\n\nfunction renderTimelineBodyHtml(): string {\n\treturn `<div class=\"app\">\n <section class=\"workspace\" id=\"workspace\">\n <aside class=\"panel sidebar\" id=\"sidebar\">\n <div class=\"sidebar-head\">\n <div class=\"sidebar-head-main\">\n <div class=\"eyebrow\">Revisions</div>\n <div class=\"sidebar-hint\" id=\"sidebarHint\"></div>\n </div>\n <button class=\"sidebar-head-action\" id=\"openSidebarRangeDiffButton\" type=\"button\">Open selection diffs</button>\n </div>\n <div class=\"sidebar-search-wrap\">\n <input class=\"sidebar-search-input\" id=\"sidebarSearchInput\" type=\"search\" placeholder=\"Search revisions\" autocomplete=\"off\" />\n </div>\n <div class=\"history-list\" id=\"historyList\"></div>\n </aside>\n <div class=\"resize-handle\" id=\"resizeHandle\"></div>\n <section class=\"panel diff-panel\">\n <div class=\"timeline-pane\" id=\"timelinePane\">\n <div class=\"timeline-pane-head\">\n <button class=\"sidebar-toggle-button\" id=\"sidebarToggleButton\" type=\"button\" aria-label=\"Toggle sidebar\">&#x25C2;</button>\n <div class=\"timeline-pane-title\">\n <div class=\"eyebrow\">Revision Timeline</div>\n <span class=\"version-badge\" id=\"timelineVersion\"></span>\n </div>\n <div class=\"timeline-head-summary\">\n <div class=\"range-label\" id=\"rangeLabel\">Loading revisions...</div>\n <div class=\"range-subtitle\" id=\"rangeSubtitle\"></div>\n </div>\n <button class=\"collapse-button\" id=\"toggleTimelinePaneButton\" type=\"button\">Timeline only</button>\n </div>\n <div class=\"diff-head\" id=\"timelineChrome\">\n <div class=\"diff-head-top\">\n <div class=\"file-switcher-row\">\n <input class=\"file-input\" id=\"fileSwitcher\" list=\"workspaceFilesList\" placeholder=\"Switch file...\" autocomplete=\"off\" />\n <datalist id=\"workspaceFilesList\"></datalist>\n </div>\n <div class=\"head-actions\">\n <button class=\"menu-button\" id=\"toggleHotkeysButton\" type=\"button\" aria-label=\"Show hotkeys\">?</button>\n <div class=\"menu-wrap\">\n <button class=\"menu-button\" id=\"actionsButton\" type=\"button\">...</button>\n <div class=\"menu\" id=\"actionsMenu\">\n <button class=\"menu-item\" id=\"toggleSidebarAction\" type=\"button\">Hide Sidebar</button>\n <button class=\"menu-item\" id=\"openCurrentFileAction\" type=\"button\">Open File</button>\n <button class=\"menu-item\" id=\"openEditorButton\" type=\"button\">Open single-file diff</button>\n <button class=\"menu-item\" id=\"openRangeFilesButton\" type=\"button\">Open multi-file diffs</button>\n <button class=\"menu-item\" id=\"cancelActiveRequestAction\" type=\"button\">Cancel request</button>\n <button class=\"menu-item\" id=\"refreshButton\" type=\"button\">Refresh</button>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"timeline-head\">\n <div class=\"revision-picker-row\">\n <div class=\"revision-picker-col\">\n <input class=\"revision-input\" id=\"fromRevisionInput\" list=\"revisionOptionsList\" placeholder=\"From revision\" autocomplete=\"off\" />\n <div class=\"revision-picker-meta\">\n <button class=\"handle-pill from\" id=\"fromHandleLabel\" type=\"button\">From</button>\n <span class=\"revision-picker-relative\" id=\"fromRelativeLabel\"></span>\n </div>\n </div>\n <span class=\"revision-arrow\">&#8594;</span>\n <div class=\"revision-picker-col\">\n <input class=\"revision-input\" id=\"toRevisionInput\" list=\"revisionOptionsList\" placeholder=\"To revision\" autocomplete=\"off\" />\n <div class=\"revision-picker-meta\">\n <button class=\"handle-pill to\" id=\"toHandleLabel\" type=\"button\">To</button>\n <span class=\"revision-picker-relative\" id=\"toRelativeLabel\"></span>\n </div>\n </div>\n <datalist id=\"revisionOptionsList\"></datalist>\n </div>\n <div class=\"control-row\">\n <div class=\"segmented\" id=\"comparisonModes\"></div>\n <div class=\"segmented\" id=\"comparisonSources\"></div>\n <div class=\"segmented\" id=\"layoutModes\"></div>\n <div class=\"segmented\" id=\"contentModes\"></div>\n <button class=\"toggle-chip\" id=\"intermediateToggle\" type=\"button\" aria-label=\"In-Between revisions\">In-Between</button>\n <div class=\"segmented\" id=\"presets\"></div>\n </div>\n </div>\n\n <div class=\"timeline-row\">\n <button class=\"step-button\" id=\"stepFastBackwardButton\" type=\"button\" aria-label=\"Jump backward\">&#171;</button>\n <button class=\"step-button\" id=\"stepBackwardButton\" type=\"button\" aria-label=\"Previous range\">&#x2039;</button>\n <div class=\"timeline\">\n <div class=\"selection-meta\" id=\"selectionMeta\"></div>\n <div class=\"track\" id=\"track\"></div>\n <div class=\"range-fill\" id=\"rangeFill\"></div>\n <button class=\"handle-marker from\" id=\"fromMarker\" type=\"button\" aria-label=\"Adjust from revision\"></button>\n <button class=\"handle-marker to\" id=\"toMarker\" type=\"button\" aria-label=\"Adjust to revision\"></button>\n <div class=\"timeline-hover-axis\" id=\"timelineHoverAxis\" aria-hidden=\"true\"></div>\n </div>\n <button class=\"step-button\" id=\"stepForwardButton\" type=\"button\" aria-label=\"Next range\">&#x203A;</button>\n <button class=\"step-button\" id=\"stepFastForwardButton\" type=\"button\" aria-label=\"Jump forward\">&#187;</button>\n </div>\n\n <div class=\"step-status-row\" id=\"stepStatusRow\">\n <div class=\"step-status\" id=\"stepStatus\"></div>\n <div class=\"loading-indicator\" id=\"snapshotLoadingIndicator\" hidden>Loading snapshots&#8230;</div>\n </div>\n </div>\n </div>\n <div class=\"anchor-tooltip\" id=\"anchorTooltip\" hidden></div>\n <div class=\"timeline-resize-handle\" id=\"timelineResizeHandle\"></div>\n <div class=\"diff-content\">\n <div class=\"diff-summary\">\n <div class=\"diff-title-row\">\n <div class=\"diff-summary-left\">\n <div class=\"diff-title-block\">\n <h3 class=\"diff-title\" id=\"diffTitle\">Loading diff...</h3>\n <div class=\"diff-title-meta\" id=\"diffTitleMeta\"></div>\n </div>\n <div class=\"diff-subtitle\" id=\"diffSubtitle\"></div>\n </div>\n <div class=\"diff-actions\">\n <div class=\"eyebrow diff-mode-eyebrow\" id=\"diffModeEyebrow\">Diff</div>\n <div class=\"history-stats\" id=\"diffStats\"></div>\n <button class=\"collapse-button\" id=\"toggleDiffFocusButton\" type=\"button\">Focus diff</button>\n </div>\n </div>\n </div>\n <div class=\"diff-rows\" id=\"diffRows\"></div>\n </div>\n <div class=\"hotkeys-popover\" id=\"hotkeysPopover\" hidden>\n <div class=\"hotkeys-card\">\n <div class=\"hotkeys-head\">\n <div>\n <div style=\"display:flex;align-items:baseline;gap:6px;\">\n <div class=\"eyebrow\">Shortcuts</div>\n <div class=\"hotkeys-version\" id=\"hotkeysVersion\"></div>\n </div>\n <div class=\"hotkeys-subtitle\">Range selection, sidebar navigation, and diff actions</div>\n </div>\n <button class=\"collapse-button\" id=\"closeHotkeysButton\" type=\"button\">Close</button>\n </div>\n <div class=\"hotkeys-grid\">\n <div class=\"hotkey-section\">\n <div class=\"hotkey-section-title\">Selection</div>\n <div class=\"hotkey-row\"><span class=\"hotkey-label\">Move range</span><span class=\"hotkey-value\"><kbd>←</kbd><kbd>→</kbd></span></div>\n <div class=\"hotkey-row\"><span class=\"hotkey-label\">Fast move range</span><span class=\"hotkey-value\"><kbd>Shift</kbd><kbd>←</kbd><kbd>→</kbd></span></div>\n <div class=\"hotkey-row\"><span class=\"hotkey-label\">Move range vertically</span><span class=\"hotkey-value\"><kbd>↑</kbd><kbd>↓</kbd></span></div>\n <div class=\"hotkey-row\"><span class=\"hotkey-label\">Adjust to marker</span><span class=\"hotkey-value\"><kbd>Option</kbd><kbd>←</kbd><kbd>→</kbd></span></div>\n <div class=\"hotkey-row\"><span class=\"hotkey-label\">Adjust from marker</span><span class=\"hotkey-value\"><kbd>Ctrl</kbd><kbd>←</kbd><kbd>→</kbd></span></div>\n <div class=\"hotkey-row\"><span class=\"hotkey-label\">Dock range to start/end</span><span class=\"hotkey-value\"><kbd>Cmd</kbd><kbd>←</kbd><kbd>→</kbd></span></div>\n </div>\n <div class=\"hotkey-section\">\n <div class=\"hotkey-section-title\">Actions</div>\n <div class=\"hotkey-row\"><span class=\"hotkey-label\">Open cumulative diff</span><span class=\"hotkey-value\"><kbd>Space</kbd></span></div>\n <div class=\"hotkey-row\"><span class=\"hotkey-label\">Toggle help</span><span class=\"hotkey-value\"><kbd>?</kbd></span></div>\n <div class=\"hotkey-row\"><span class=\"hotkey-label\">Toggle sidebar</span><span class=\"hotkey-value\"><kbd>B</kbd></span></div>\n <div class=\"hotkey-row\"><span class=\"hotkey-label\">Pick range by click</span><span class=\"hotkey-note\">Click one revision, then another</span></div>\n <div class=\"hotkey-row\"><span class=\"hotkey-label\">Drag markers</span><span class=\"hotkey-note\">Adjust range directly on the timeline</span></div>\n </div>\n </div>\n </div>\n </div>\n </section>\n </section>\n </div>`;\n}\n\nexport function renderTimelineDocumentHtml(options: TimelineDocumentHtmlOptions): string {\n\tconst title = escapeHtml(options.title || 'Revision Timeline');\n\tconst styleHref = escapeAttribute(options.styleHref || './timeline.css');\n\tconst appSrc = escapeAttribute(options.appSrc || '');\n\tconst modelSrc = escapeAttribute(options.modelSrc || '');\n\tconst scriptSrc = escapeAttribute(options.scriptSrc || '');\n\tconst workerSrc = escapeAttribute(options.workerSrc || '');\n\tconst cspSource = options.cspSource;\n\tconst csp = cspSource\n\t\t? `<meta http-equiv=\"Content-Security-Policy\" content=\"default-src 'none'; img-src ${cspSource} https: data:; style-src ${cspSource}; script-src ${cspSource}; worker-src ${cspSource} blob:; connect-src ${cspSource};\" />`\n\t\t: '';\n\tconst workerBoot =\n\t\tworkerSrc.length > 0 ? `<script>window.WORKER_URI=${JSON.stringify(options.workerSrc)};</script>` : '';\n\n\tif (appSrc) {\n\t\treturn `<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n ${csp}\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>${title}</title>\n <link rel=\"stylesheet\" href=\"${styleHref}\" />\n </head>\n <body>\n <div id=\"timelineApp\"></div>\n ${workerBoot}\n <script type=\"module\" src=\"${appSrc}\"></script>\n </body>\n</html>`;\n\t}\n\n\treturn `<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n ${csp}\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>${title}</title>\n <link rel=\"stylesheet\" href=\"${styleHref}\" />\n </head>\n <body>\n ${renderTimelineBodyHtml()}\n ${workerBoot}\n ${modelSrc ? `<script src=\"${modelSrc}\"></script>` : ''}\n ${scriptSrc ? `<script src=\"${scriptSrc}\"></script>` : ''}\n </body>\n</html>`;\n}\n\nfunction escapeHtml(value: string): string {\n\treturn String(value).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n}\n\nfunction escapeAttribute(value: string): string {\n\treturn escapeHtml(value).replace(/\"/g, '&quot;');\n}\n"],"mappings":";AAUA,SAAS,yBAAiC;CACzC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+JR;AAEA,SAAgB,2BAA2B,SAA8C;CACxF,MAAM,QAAQ,WAAW,QAAQ,SAAS,mBAAmB;CAC7D,MAAM,YAAY,gBAAgB,QAAQ,aAAa,gBAAgB;CACvE,MAAM,SAAS,gBAAgB,QAAQ,UAAU,EAAE;CACnD,MAAM,WAAW,gBAAgB,QAAQ,YAAY,EAAE;CACvD,MAAM,YAAY,gBAAgB,QAAQ,aAAa,EAAE;CACzD,MAAM,YAAY,gBAAgB,QAAQ,aAAa,EAAE;CACzD,MAAM,YAAY,QAAQ;CAC1B,MAAM,MAAM,YACT,mFAAmF,UAAU,2BAA2B,UAAU,eAAe,UAAU,eAAe,UAAU,sBAAsB,UAAU,SACpN;CACH,MAAM,aACL,UAAU,SAAS,IAAI,6BAA6B,KAAK,UAAU,QAAQ,SAAS,EAAE,eAAc;CAErG,IAAI,QACH,OAAO;;;;MAIH,IAAI;;aAEG,MAAM;mCACgB,UAAU;;;;MAIvC,WAAW;iCACgB,OAAO;;;CAKvC,OAAO;;;;MAIF,IAAI;;aAEG,MAAM;mCACgB,UAAU;;;MAGvC,uBAAuB,EAAE;MACzB,WAAW;MACX,WAAW,gBAAgB,SAAS,gBAAe,GAAG;MACtD,YAAY,gBAAgB,UAAU,gBAAe,GAAG;;;AAG9D;AAEA,SAAS,WAAW,OAAuB;CAC1C,OAAO,OAAO,KAAK,CAAC,CAAC,QAAQ,MAAM,OAAO,CAAC,CAAC,QAAQ,MAAM,MAAM,CAAC,CAAC,QAAQ,MAAM,MAAM;AACvF;AAEA,SAAS,gBAAgB,OAAuB;CAC/C,OAAO,WAAW,KAAK,CAAC,CAAC,QAAQ,MAAM,QAAQ;AAChD"}