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.
- package/CHANGELOG.md +30 -0
- package/README.md +102 -0
- package/assets/jj-plus-icon.png +0 -0
- package/dist/_virtual/_rolldown/runtime.cjs +23 -0
- package/dist/bin.cjs +112 -0
- package/dist/bin.cjs.map +1 -0
- package/dist/cli/options.cjs +376 -0
- package/dist/cli/options.cjs.map +1 -0
- package/dist/cli/timeline-json.cjs +29 -0
- package/dist/cli/timeline-json.cjs.map +1 -0
- package/dist/extension/blame-codelens.cjs +228 -0
- package/dist/extension/blame-codelens.cjs.map +1 -0
- package/dist/extension/command-runner.cjs +99 -0
- package/dist/extension/command-runner.cjs.map +1 -0
- package/dist/extension/constants.cjs +56 -0
- package/dist/extension/constants.cjs.map +1 -0
- package/dist/extension/editor-extra-features.cjs +464 -0
- package/dist/extension/editor-extra-features.cjs.map +1 -0
- package/dist/extension/history-adapters.cjs +702 -0
- package/dist/extension/history-adapters.cjs.map +1 -0
- package/dist/extension/index.cjs +657 -0
- package/dist/extension/index.cjs.map +1 -0
- package/dist/extension/repo-timeline-panel.cjs +402 -0
- package/dist/extension/repo-timeline-panel.cjs.map +1 -0
- package/dist/extension/resolve-file-path.cjs +16 -0
- package/dist/extension/resolve-file-path.cjs.map +1 -0
- package/dist/extension/revision-diff-nav.cjs +169 -0
- package/dist/extension/revision-diff-nav.cjs.map +1 -0
- package/dist/extension/settings.cjs +41 -0
- package/dist/extension/settings.cjs.map +1 -0
- package/dist/extension/timeline-at-line.cjs +72 -0
- package/dist/extension/timeline-at-line.cjs.map +1 -0
- package/dist/extension/timeline-panel.cjs +1113 -0
- package/dist/extension/timeline-panel.cjs.map +1 -0
- package/dist/extension/timeline-service.cjs +1154 -0
- package/dist/extension/timeline-service.cjs.map +1 -0
- package/dist/extension/uri-utils.cjs +75 -0
- package/dist/extension/uri-utils.cjs.map +1 -0
- package/dist/package.cjs +11 -0
- package/dist/package.cjs.map +1 -0
- package/dist/shared/blame.cjs +211 -0
- package/dist/shared/blame.cjs.map +1 -0
- package/dist/shared/diff-content-search.cjs +23 -0
- package/dist/shared/diff-content-search.cjs.map +1 -0
- package/dist/shared/diff-helpers.cjs +12 -0
- package/dist/shared/diff-helpers.cjs.map +1 -0
- package/dist/shared/diff-stats.cjs +129 -0
- package/dist/shared/diff-stats.cjs.map +1 -0
- package/dist/shared/file-oplog.cjs +82 -0
- package/dist/shared/file-oplog.cjs.map +1 -0
- package/dist/shared/history-helpers.cjs +257 -0
- package/dist/shared/history-helpers.cjs.map +1 -0
- package/dist/shared/history-search.cjs +85 -0
- package/dist/shared/history-search.cjs.map +1 -0
- package/dist/shared/jj-revset-suggestions.cjs +41 -0
- package/dist/shared/jj-revset-suggestions.cjs.map +1 -0
- package/dist/shared/line-history.cjs +181 -0
- package/dist/shared/line-history.cjs.map +1 -0
- package/dist/shared/list-file-revisions.cjs +36 -0
- package/dist/shared/list-file-revisions.cjs.map +1 -0
- package/dist/shared/non-textual-details.cjs +43 -0
- package/dist/shared/non-textual-details.cjs.map +1 -0
- package/dist/shared/resolve-file-path.cjs +14 -0
- package/dist/shared/resolve-file-path.cjs.map +1 -0
- package/dist/shared/revision-diff-availability.cjs +18 -0
- package/dist/shared/revision-diff-availability.cjs.map +1 -0
- package/dist/shared/revision-diff-pair.cjs +42 -0
- package/dist/shared/revision-diff-pair.cjs.map +1 -0
- package/dist/shared/revset.cjs +16 -0
- package/dist/shared/revset.cjs.map +1 -0
- package/dist/shared/timeline-model.cjs +29 -0
- package/dist/shared/timeline-model.cjs.map +1 -0
- package/dist/standalone/server.cjs +1733 -0
- package/dist/standalone/server.cjs.map +1 -0
- package/dist/webview/timeline-template.cjs +214 -0
- package/dist/webview/timeline-template.cjs.map +1 -0
- package/package.json +320 -0
- package/webview-dist/assets/worker-DuV13XDT.js +161 -0
- package/webview-dist/chunks/abap-CLvhMVsD.js +1 -0
- package/webview-dist/chunks/actionscript-3-Cs6JJXT5.js +1 -0
- package/webview-dist/chunks/ada-C5qYipkI.js +1 -0
- package/webview-dist/chunks/ahk-CA9gdOdF.js +1 -0
- package/webview-dist/chunks/ahk2-_6rzW9BS.js +1 -0
- package/webview-dist/chunks/andromeeda-vGVdxbeo.js +1 -0
- package/webview-dist/chunks/angular-html-DTpR04n4.js +1 -0
- package/webview-dist/chunks/angular-ts-BCtbMvbl.js +1 -0
- package/webview-dist/chunks/apache-U0d_L8uA.js +1 -0
- package/webview-dist/chunks/apex-KFGFyKwG.js +1 -0
- package/webview-dist/chunks/apl-BMZuN1Ql.js +1 -0
- package/webview-dist/chunks/applescript-CCn79oCD.js +1 -0
- package/webview-dist/chunks/ara-4CJ0cIlV.js +1 -0
- package/webview-dist/chunks/asciidoc-SCjQUq34.js +1 -0
- package/webview-dist/chunks/asm-Cmm7eHzH.js +1 -0
- package/webview-dist/chunks/astro-DrbV4Z7r.js +1 -0
- package/webview-dist/chunks/aurora-x-CDeNXAV0.js +1 -0
- package/webview-dist/chunks/awk-BWXHIvNe.js +1 -0
- package/webview-dist/chunks/ayu-dark-DluEY0Gj.js +1 -0
- package/webview-dist/chunks/ayu-light-C3h-C4tm.js +1 -0
- package/webview-dist/chunks/ayu-mirage-Bqwy1Gya.js +1 -0
- package/webview-dist/chunks/ballerina-B7ZEbQpA.js +1 -0
- package/webview-dist/chunks/bat-qdxAdBWQ.js +1 -0
- package/webview-dist/chunks/beancount-D-usSTwE.js +1 -0
- package/webview-dist/chunks/berry-DKpUyyne.js +1 -0
- package/webview-dist/chunks/bibtex-Ci_nEsc7.js +1 -0
- package/webview-dist/chunks/bicep-CUHmPFLl.js +1 -0
- package/webview-dist/chunks/bird2-CYIUgYqB.js +1 -0
- package/webview-dist/chunks/blade-oPV8S6rR.js +1 -0
- package/webview-dist/chunks/bsl-_VjlB9mv.js +1 -0
- package/webview-dist/chunks/c-DYf-3tob.js +1 -0
- package/webview-dist/chunks/c3-D0apG41V.js +1 -0
- package/webview-dist/chunks/cadence-CQ2zXKGN.js +1 -0
- package/webview-dist/chunks/cairo-DLTphjLi.js +1 -0
- package/webview-dist/chunks/catppuccin-frappe-C9Q5zVZY.js +1 -0
- package/webview-dist/chunks/catppuccin-latte-CtsyrtPq.js +1 -0
- package/webview-dist/chunks/catppuccin-macchiato-R8nAf1vR.js +1 -0
- package/webview-dist/chunks/catppuccin-mocha-DjuaAJKi.js +1 -0
- package/webview-dist/chunks/chapel-DY-WYB1D.js +1 -0
- package/webview-dist/chunks/clarity-CtfBBspg.js +1 -0
- package/webview-dist/chunks/clojure-DqKBuwfJ.js +1 -0
- package/webview-dist/chunks/cmake-Bj61d0ZC.js +1 -0
- package/webview-dist/chunks/cobol-DvdX_6CO.js +1 -0
- package/webview-dist/chunks/codeowners-C8r90Shi.js +1 -0
- package/webview-dist/chunks/codeql-oeQT6MSM.js +1 -0
- package/webview-dist/chunks/coffee-C1kO7jr_.js +1 -0
- package/webview-dist/chunks/common-lisp-Cv5bFMCO.js +1 -0
- package/webview-dist/chunks/coq-DuBRPxYg.js +1 -0
- package/webview-dist/chunks/cpp-CoSarUrI.js +1 -0
- package/webview-dist/chunks/crystal-SLJeZ5EP.js +1 -0
- package/webview-dist/chunks/csharp-oqKa8noW.js +1 -0
- package/webview-dist/chunks/css-cfScyrSP.js +1 -0
- package/webview-dist/chunks/csv-Dx-8-gkx.js +1 -0
- package/webview-dist/chunks/cue-CE9AQfxI.js +1 -0
- package/webview-dist/chunks/cypher-ClKdZ_lG.js +1 -0
- package/webview-dist/chunks/d-qD-0Kul2.js +1 -0
- package/webview-dist/chunks/dark-plus-Cs2F2srj.js +1 -0
- package/webview-dist/chunks/dart-CnvKMtbv.js +1 -0
- package/webview-dist/chunks/dax-BkyTk9wS.js +1 -0
- package/webview-dist/chunks/desktop-Dlh5hvp9.js +1 -0
- package/webview-dist/chunks/diff-woXpYk--.js +1 -0
- package/webview-dist/chunks/docker-IyjqRm3v.js +1 -0
- package/webview-dist/chunks/dotenv-_5a1GRtc.js +1 -0
- package/webview-dist/chunks/dracula-BHWKrbxM.js +1 -0
- package/webview-dist/chunks/dracula-soft-5eyTD99u.js +1 -0
- package/webview-dist/chunks/dream-maker-DW3nJb8Q.js +1 -0
- package/webview-dist/chunks/edge-lvBr3t3s.js +1 -0
- package/webview-dist/chunks/elixir-BLoPe0KG.js +1 -0
- package/webview-dist/chunks/elm-BveBINBn.js +1 -0
- package/webview-dist/chunks/emacs-lisp-c_oH4hRZ.js +1 -0
- package/webview-dist/chunks/erb-Bmf8z4ph.js +1 -0
- package/webview-dist/chunks/erlang-Cphh6RMH.js +1 -0
- package/webview-dist/chunks/everforest-dark-sB-x3p7T.js +1 -0
- package/webview-dist/chunks/everforest-light-Df2xbC6M.js +1 -0
- package/webview-dist/chunks/fennel-DQxkIbk2.js +1 -0
- package/webview-dist/chunks/fish-BJitypiv.js +1 -0
- package/webview-dist/chunks/fluent-C03EYrpw.js +1 -0
- package/webview-dist/chunks/fortran-fixed-form-DEKoE2YW.js +1 -0
- package/webview-dist/chunks/fortran-free-form-CYNrtFtB.js +1 -0
- package/webview-dist/chunks/fsharp-D13ZGOAj.js +1 -0
- package/webview-dist/chunks/gdresource-xMC7jr7x.js +1 -0
- package/webview-dist/chunks/gdscript-DYvRD3hg.js +1 -0
- package/webview-dist/chunks/gdshader-CBce3t8t.js +1 -0
- package/webview-dist/chunks/genie-CV2tkWYe.js +1 -0
- package/webview-dist/chunks/gherkin-DExj1W_8.js +1 -0
- package/webview-dist/chunks/git-commit-BSykSTBG.js +1 -0
- package/webview-dist/chunks/git-rebase-BBii7GBM.js +1 -0
- package/webview-dist/chunks/github-dark-C-LZuMrd.js +1 -0
- package/webview-dist/chunks/github-dark-default-DXG-b-1a.js +1 -0
- package/webview-dist/chunks/github-dark-dimmed-Bx1FflLF.js +1 -0
- package/webview-dist/chunks/github-dark-high-contrast-B_tTalzw.js +1 -0
- package/webview-dist/chunks/github-light-EUqPIrTm.js +1 -0
- package/webview-dist/chunks/github-light-default-BXViO-2h.js +1 -0
- package/webview-dist/chunks/github-light-high-contrast-B68TUdTA.js +1 -0
- package/webview-dist/chunks/gleam-CSRkHgEL.js +1 -0
- package/webview-dist/chunks/glimmer-js-CuCPna-X.js +1 -0
- package/webview-dist/chunks/glimmer-ts-DNAjZNDK.js +1 -0
- package/webview-dist/chunks/glsl-COQvRxdz.js +1 -0
- package/webview-dist/chunks/gn-ilITqXS6.js +1 -0
- package/webview-dist/chunks/gnuplot-7GGW24-e.js +1 -0
- package/webview-dist/chunks/go-rLFTqkRN.js +1 -0
- package/webview-dist/chunks/graphql-1cKCVreZ.js +1 -0
- package/webview-dist/chunks/groovy-CacY0gHj.js +1 -0
- package/webview-dist/chunks/gruvbox-dark-hard-C820rvS2.js +1 -0
- package/webview-dist/chunks/gruvbox-dark-medium-BPjhmG05.js +1 -0
- package/webview-dist/chunks/gruvbox-dark-soft-MrdJrrXF.js +1 -0
- package/webview-dist/chunks/gruvbox-light-hard-BC_s9l72.js +1 -0
- package/webview-dist/chunks/gruvbox-light-medium-BAWPOn9u.js +1 -0
- package/webview-dist/chunks/gruvbox-light-soft-BSMLrYjP.js +1 -0
- package/webview-dist/chunks/hack-7CXYxWGO.js +1 -0
- package/webview-dist/chunks/haml-CeE16iG9.js +1 -0
- package/webview-dist/chunks/handlebars-CLm7Miue.js +1 -0
- package/webview-dist/chunks/haskell-D8IpX4py.js +1 -0
- package/webview-dist/chunks/haxe-C8oCnwJJ.js +1 -0
- package/webview-dist/chunks/hcl-Dh228itO.js +1 -0
- package/webview-dist/chunks/hjson-CxZEssPk.js +1 -0
- package/webview-dist/chunks/hlsl-Cvrh5tZx.js +1 -0
- package/webview-dist/chunks/horizon-CE9ld1lL.js +1 -0
- package/webview-dist/chunks/horizon-bright-DSNQnXHK.js +1 -0
- package/webview-dist/chunks/houston-CsvMBhTu.js +1 -0
- package/webview-dist/chunks/html-EbCri-_j.js +1 -0
- package/webview-dist/chunks/html-derivative-DGcE2kQi.js +1 -0
- package/webview-dist/chunks/http-DpnqgCg2.js +1 -0
- package/webview-dist/chunks/hurl-B6NGpamo.js +1 -0
- package/webview-dist/chunks/hxml-Dcm88srW.js +1 -0
- package/webview-dist/chunks/hy-CZbG8q4J.js +1 -0
- package/webview-dist/chunks/imba-DsUTQ-LC.js +1 -0
- package/webview-dist/chunks/ini-B5eOa1yu.js +1 -0
- package/webview-dist/chunks/java-ZkUoUSJy.js +1 -0
- package/webview-dist/chunks/javascript-DLd0EIw7.js +1 -0
- package/webview-dist/chunks/jinja-WhIqNp3q.js +1 -0
- package/webview-dist/chunks/jison-CIn1t7S8.js +1 -0
- package/webview-dist/chunks/json-AHG_JuKN.js +1 -0
- package/webview-dist/chunks/json5-BR5RXkoi.js +1 -0
- package/webview-dist/chunks/jsonc-CYpm1nAK.js +1 -0
- package/webview-dist/chunks/jsonl-CmCQp5Yx.js +1 -0
- package/webview-dist/chunks/jsonnet-CJTPZ8u_.js +1 -0
- package/webview-dist/chunks/jssm-DXw9l8Rf.js +1 -0
- package/webview-dist/chunks/jsx-BLy2KGb2.js +1 -0
- package/webview-dist/chunks/julia-XrhdGMY0.js +1 -0
- package/webview-dist/chunks/just-CiO9rOBq.js +1 -0
- package/webview-dist/chunks/kanagawa-dragon-Bozd7klA.js +1 -0
- package/webview-dist/chunks/kanagawa-lotus-BmuOG9ZW.js +1 -0
- package/webview-dist/chunks/kanagawa-wave-BML5mF2J.js +1 -0
- package/webview-dist/chunks/kdl-CsD5j6eV.js +1 -0
- package/webview-dist/chunks/kotlin-DhhofPvG.js +1 -0
- package/webview-dist/chunks/kusto-C7mF5XQf.js +1 -0
- package/webview-dist/chunks/laserwave-C_8bwKvT.js +1 -0
- package/webview-dist/chunks/latex-4tqdYtbu.js +1 -0
- package/webview-dist/chunks/lean-CewbzKMR.js +1 -0
- package/webview-dist/chunks/less-DVTAwKKz.js +1 -0
- package/webview-dist/chunks/light-plus-DVQuIRkW.js +1 -0
- package/webview-dist/chunks/liquid-BiiWRCLG.js +1 -0
- package/webview-dist/chunks/llvm-DqHOMS-s.js +1 -0
- package/webview-dist/chunks/log-BNLmms1o.js +1 -0
- package/webview-dist/chunks/logo-Cluzi2Zq.js +1 -0
- package/webview-dist/chunks/lua-BPFdS2Mc.js +1 -0
- package/webview-dist/chunks/luau-C2pBCSgt.js +1 -0
- package/webview-dist/chunks/make-Dixweg8N.js +1 -0
- package/webview-dist/chunks/markdown-BYOwaDjH.js +1 -0
- package/webview-dist/chunks/marko-BLi1Yy1V.js +1 -0
- package/webview-dist/chunks/material-theme-Bm3Qr25_.js +1 -0
- package/webview-dist/chunks/material-theme-darker-2IIEA8gg.js +1 -0
- package/webview-dist/chunks/material-theme-lighter-uhdI0v04.js +1 -0
- package/webview-dist/chunks/material-theme-ocean-CHQ94UKr.js +1 -0
- package/webview-dist/chunks/material-theme-palenight-B5W6OYN7.js +1 -0
- package/webview-dist/chunks/matlab-D7qyCx1q.js +1 -0
- package/webview-dist/chunks/mdc-Dx-qyM1x.js +1 -0
- package/webview-dist/chunks/mdx-DQZ5AkYe.js +1 -0
- package/webview-dist/chunks/mermaid-BxpfTIzt.js +1 -0
- package/webview-dist/chunks/min-dark-BSWPekZh.js +1 -0
- package/webview-dist/chunks/min-light-DDpmG2fV.js +1 -0
- package/webview-dist/chunks/mipsasm-BMqwQI7S.js +1 -0
- package/webview-dist/chunks/mojo-fg40_ntQ.js +1 -0
- package/webview-dist/chunks/monokai-B_bV9PQ9.js +1 -0
- package/webview-dist/chunks/moonbit-DgjMoLWr.js +1 -0
- package/webview-dist/chunks/move-BYnGhZoM.js +1 -0
- package/webview-dist/chunks/narrat-_X_XdTYD.js +1 -0
- package/webview-dist/chunks/nextflow-BJtWHP5T.js +1 -0
- package/webview-dist/chunks/nextflow-groovy-DJMQeKeT.js +1 -0
- package/webview-dist/chunks/nginx-rnpjAIVq.js +1 -0
- package/webview-dist/chunks/night-owl-DhmEMT88.js +1 -0
- package/webview-dist/chunks/night-owl-light-eJ-hLW7d.js +1 -0
- package/webview-dist/chunks/nim-kKTJ2fIs.js +1 -0
- package/webview-dist/chunks/nix-IvuFDN5E.js +1 -0
- package/webview-dist/chunks/nord-Cb4Vim4T.js +1 -0
- package/webview-dist/chunks/nsis-CjNLYCLg.js +1 -0
- package/webview-dist/chunks/nushell-DHYfO66s.js +1 -0
- package/webview-dist/chunks/objective-c-D1A_Heim.js +1 -0
- package/webview-dist/chunks/objective-cpp-BsSzOQcm.js +1 -0
- package/webview-dist/chunks/ocaml-O90oeIOV.js +1 -0
- package/webview-dist/chunks/odin-B1RWQWA5.js +1 -0
- package/webview-dist/chunks/one-dark-pro-CLwyXe_n.js +1 -0
- package/webview-dist/chunks/one-light-D7Lr4KcI.js +1 -0
- package/webview-dist/chunks/openscad-BUDT5pXO.js +1 -0
- package/webview-dist/chunks/org-BGWCjkJX.js +1 -0
- package/webview-dist/chunks/pascal-4ZHwLPI5.js +1 -0
- package/webview-dist/chunks/perl-DEimDILQ.js +1 -0
- package/webview-dist/chunks/php-QnaNN--1.js +1 -0
- package/webview-dist/chunks/pierre-dark-CpLgRqie.js +1 -0
- package/webview-dist/chunks/pierre-dark-protanopia-deuteranopia-B35FxJx-.js +1 -0
- package/webview-dist/chunks/pierre-dark-soft-kZQmAZld.js +1 -0
- package/webview-dist/chunks/pierre-dark-tritanopia-CpjhbsIL.js +1 -0
- package/webview-dist/chunks/pierre-dark-vibrant-CpQYzh95.js +1 -0
- package/webview-dist/chunks/pierre-light-CoaEpmwp.js +1 -0
- package/webview-dist/chunks/pierre-light-protanopia-deuteranopia-0fSaH845.js +1 -0
- package/webview-dist/chunks/pierre-light-soft-lWLdNTOI.js +1 -0
- package/webview-dist/chunks/pierre-light-tritanopia-CEbqgOJL.js +1 -0
- package/webview-dist/chunks/pierre-light-vibrant-D80Fkn33.js +1 -0
- package/webview-dist/chunks/pkl-ot-7Btpt.js +1 -0
- package/webview-dist/chunks/plastic-DQwYfKfQ.js +1 -0
- package/webview-dist/chunks/plsql-DGHpHOYJ.js +1 -0
- package/webview-dist/chunks/po-BiJDBrnU.js +1 -0
- package/webview-dist/chunks/poimandres-DRFjx7u4.js +1 -0
- package/webview-dist/chunks/polar-C7UOKdEL.js +1 -0
- package/webview-dist/chunks/postcss-BXeXVLqQ.js +1 -0
- package/webview-dist/chunks/powerquery-DNMTfnFr.js +1 -0
- package/webview-dist/chunks/powershell-CCSX75yM.js +1 -0
- package/webview-dist/chunks/prisma-DMgNhnYS.js +1 -0
- package/webview-dist/chunks/prolog-iXnhIJG7.js +1 -0
- package/webview-dist/chunks/proto-DB4EqR-F.js +1 -0
- package/webview-dist/chunks/pug-D5rsKmMX.js +1 -0
- package/webview-dist/chunks/puppet-CDv2pdJW.js +1 -0
- package/webview-dist/chunks/purescript-9MfHhQsQ.js +1 -0
- package/webview-dist/chunks/python-gzcpVVnB.js +1 -0
- package/webview-dist/chunks/qml-wvbZb8UE.js +1 -0
- package/webview-dist/chunks/qmldir-DCQb3MpD.js +1 -0
- package/webview-dist/chunks/qss-Fe1Jh2GI.js +1 -0
- package/webview-dist/chunks/r-BNyBFaU1.js +1 -0
- package/webview-dist/chunks/racket-DcIDlBhZ.js +1 -0
- package/webview-dist/chunks/raku-B3gFvitq.js +1 -0
- package/webview-dist/chunks/razor-bKaHS6Kz.js +1 -0
- package/webview-dist/chunks/rbs-C0MpOrj4.js +1 -0
- package/webview-dist/chunks/red-DX1BQOs8.js +1 -0
- package/webview-dist/chunks/reg-CRGYupPL.js +1 -0
- package/webview-dist/chunks/regexp-B-mZuWUh.js +1 -0
- package/webview-dist/chunks/rel-BtDbiS_P.js +1 -0
- package/webview-dist/chunks/riscv-Ckw8ddFX.js +1 -0
- package/webview-dist/chunks/ron-VUp2lXgN.js +1 -0
- package/webview-dist/chunks/rose-pine-aMsaMD1D.js +1 -0
- package/webview-dist/chunks/rose-pine-dawn-8PwUyIlP.js +1 -0
- package/webview-dist/chunks/rose-pine-moon-DO-qXg-I.js +1 -0
- package/webview-dist/chunks/rosmsg-CAekHB0j.js +1 -0
- package/webview-dist/chunks/rst-Qq8ybXHe.js +1 -0
- package/webview-dist/chunks/ruby-U659LEwU.js +1 -0
- package/webview-dist/chunks/rust-Cfkwpbl8.js +1 -0
- package/webview-dist/chunks/sas-C4NtLApe.js +1 -0
- package/webview-dist/chunks/sass-DXrisJhu.js +1 -0
- package/webview-dist/chunks/scala-BiFt_7mu.js +1 -0
- package/webview-dist/chunks/scheme-DQCgrYNe.js +1 -0
- package/webview-dist/chunks/scss-KAaA4sHk.js +1 -0
- package/webview-dist/chunks/sdbl-bTVj8UrX.js +1 -0
- package/webview-dist/chunks/shaderlab-TOUzSsQk.js +1 -0
- package/webview-dist/chunks/shellscript-_7bOVsRC.js +1 -0
- package/webview-dist/chunks/shellsession-Bs_5k0qk.js +1 -0
- package/webview-dist/chunks/slack-dark-DnToyrRv.js +1 -0
- package/webview-dist/chunks/slack-ochin-B2OO5cIa.js +1 -0
- package/webview-dist/chunks/smalltalk-BHpQb5nM.js +1 -0
- package/webview-dist/chunks/smithy-Dgaz7aur.js +1 -0
- package/webview-dist/chunks/snazzy-light-4G7pJPwS.js +1 -0
- package/webview-dist/chunks/solarized-dark-UdsmMDCL.js +1 -0
- package/webview-dist/chunks/solarized-light-C1IUL_tW.js +1 -0
- package/webview-dist/chunks/solidity-Bj7E1mRn.js +1 -0
- package/webview-dist/chunks/soy-C5iuoFCh.js +1 -0
- package/webview-dist/chunks/sparql-D_iOobhT.js +1 -0
- package/webview-dist/chunks/splunk-BC2Px7Mm.js +1 -0
- package/webview-dist/chunks/sql-JX305rZh.js +1 -0
- package/webview-dist/chunks/ssh-config-BgfXC-Er.js +1 -0
- package/webview-dist/chunks/stata-2Rtik3TV.js +1 -0
- package/webview-dist/chunks/stylus-B6D30XZt.js +1 -0
- package/webview-dist/chunks/surrealql-IvpiLAIH.js +1 -0
- package/webview-dist/chunks/svelte-DeZcV_1u.js +1 -0
- package/webview-dist/chunks/swift-CyEgAFGc.js +1 -0
- package/webview-dist/chunks/synthwave-84-nFMaYfgc.js +1 -0
- package/webview-dist/chunks/system-verilog-Dh5ihWbf.js +1 -0
- package/webview-dist/chunks/systemd-BxMlprV5.js +1 -0
- package/webview-dist/chunks/talonscript-CohzipZa.js +1 -0
- package/webview-dist/chunks/tasl-DMoTqEGO.js +1 -0
- package/webview-dist/chunks/tcl-CZd0xW_V.js +1 -0
- package/webview-dist/chunks/templ-CcwjPXJr.js +1 -0
- package/webview-dist/chunks/terraform-DswuEJGm.js +1 -0
- package/webview-dist/chunks/tex-CZYHgHl8.js +1 -0
- package/webview-dist/chunks/tokyo-night-oM2G3aXe.js +1 -0
- package/webview-dist/chunks/toml-CcmNWLt0.js +1 -0
- package/webview-dist/chunks/ts-tags-DPINfEO_.js +1 -0
- package/webview-dist/chunks/tsv-sltzmVWM.js +1 -0
- package/webview-dist/chunks/tsx-Dq7pSIyE.js +1 -0
- package/webview-dist/chunks/turtle-ByJddavk.js +1 -0
- package/webview-dist/chunks/twig-DFpC8yDL.js +1 -0
- package/webview-dist/chunks/typescript-CN-guYmK.js +1 -0
- package/webview-dist/chunks/typespec-BRdr0IET.js +1 -0
- package/webview-dist/chunks/typst-hgW4q6mN.js +1 -0
- package/webview-dist/chunks/v-DBj4K9d_.js +1 -0
- package/webview-dist/chunks/vala-zf12oZj6.js +1 -0
- package/webview-dist/chunks/vb-DOwzaHZ0.js +1 -0
- package/webview-dist/chunks/verilog-B2gwz-sJ.js +1 -0
- package/webview-dist/chunks/vesper-DdrHHSXu.js +1 -0
- package/webview-dist/chunks/vhdl-BroJfC0k.js +1 -0
- package/webview-dist/chunks/viml-DvXPmvsu.js +1 -0
- package/webview-dist/chunks/vitesse-black-fwtXNY1n.js +1 -0
- package/webview-dist/chunks/vitesse-dark-BZCL-v6S.js +1 -0
- package/webview-dist/chunks/vitesse-light-VbXTXTou.js +1 -0
- package/webview-dist/chunks/vue-Dkz9ntel.js +1 -0
- package/webview-dist/chunks/vue-html-Dg8LQ5v3.js +1 -0
- package/webview-dist/chunks/vue-vine-CIEXICEN.js +1 -0
- package/webview-dist/chunks/vyper-CgoNMtux.js +1 -0
- package/webview-dist/chunks/wasm-BnjxR4X6.js +1 -0
- package/webview-dist/chunks/wasm-ByWQv1Qj.js +1 -0
- package/webview-dist/chunks/wenyan-C8pVoKbM.js +1 -0
- package/webview-dist/chunks/wgsl-BsKzXJz4.js +1 -0
- package/webview-dist/chunks/wikitext-ClFFjSW2.js +1 -0
- package/webview-dist/chunks/wit-DdvCle-K.js +1 -0
- package/webview-dist/chunks/wolfram-DLL8P-h_.js +1 -0
- package/webview-dist/chunks/worker-D52zl71O.js +1 -0
- package/webview-dist/chunks/worker-pool-lOjh8Q2A.js +1543 -0
- package/webview-dist/chunks/xml-X7YOen_c.js +1 -0
- package/webview-dist/chunks/xsl-h4d_Px-X.js +1 -0
- package/webview-dist/chunks/yaml-BRDpsfaj.js +1 -0
- package/webview-dist/chunks/zenscript-BnlCZFoB.js +1 -0
- package/webview-dist/chunks/zig-CMLA9XwU.js +1 -0
- package/webview-dist/index.html +18 -0
- package/webview-dist/pierre-worker-portable.js +13633 -0
- package/webview-dist/repo-timeline-app.js +7 -0
- package/webview-dist/repo-timeline.html +14 -0
- package/webview-dist/timeline-app.css +2 -0
- package/webview-dist/timeline-app.js +85 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
const require_diff_helpers = require("./diff-helpers.cjs");
|
|
2
|
+
//#region src/shared/diff-stats.ts
|
|
3
|
+
function computeDiffStats(beforeText, afterText) {
|
|
4
|
+
if (require_diff_helpers.textsMatchIgnoringLineEndings(beforeText, afterText)) return {
|
|
5
|
+
additions: 0,
|
|
6
|
+
deletions: 0,
|
|
7
|
+
hunkCount: 0,
|
|
8
|
+
hasChanges: false
|
|
9
|
+
};
|
|
10
|
+
const operations = diffLineOperations({
|
|
11
|
+
beforeLines: splitIntoLines(beforeText),
|
|
12
|
+
afterLines: splitIntoLines(afterText)
|
|
13
|
+
});
|
|
14
|
+
const additions = operations.filter((operation) => operation.type === "add").length;
|
|
15
|
+
const deletions = operations.filter((operation) => operation.type === "remove").length;
|
|
16
|
+
return {
|
|
17
|
+
additions,
|
|
18
|
+
deletions,
|
|
19
|
+
hunkCount: countDiffHunks(operations),
|
|
20
|
+
hasChanges: additions > 0 || deletions > 0
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function countDiffHunks(operations) {
|
|
24
|
+
let hunks = 0;
|
|
25
|
+
let inChange = false;
|
|
26
|
+
for (const operation of operations) {
|
|
27
|
+
const isChange = operation.type === "add" || operation.type === "remove";
|
|
28
|
+
if (isChange && !inChange) {
|
|
29
|
+
hunks += 1;
|
|
30
|
+
inChange = true;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (!isChange) inChange = false;
|
|
34
|
+
}
|
|
35
|
+
return hunks;
|
|
36
|
+
}
|
|
37
|
+
function splitIntoLines(value) {
|
|
38
|
+
if (!value) return [];
|
|
39
|
+
const lines = value.replace(/\r\n/g, "\n").split("\n");
|
|
40
|
+
if (lines.at(-1) === "") lines.pop();
|
|
41
|
+
return lines;
|
|
42
|
+
}
|
|
43
|
+
function diffLineOperations(args) {
|
|
44
|
+
if (!args.beforeLines.length) return args.afterLines.map((text) => ({
|
|
45
|
+
type: "add",
|
|
46
|
+
text
|
|
47
|
+
}));
|
|
48
|
+
if (!args.afterLines.length) return args.beforeLines.map((text) => ({
|
|
49
|
+
type: "remove",
|
|
50
|
+
text
|
|
51
|
+
}));
|
|
52
|
+
if (args.beforeLines.length * args.afterLines.length > 12e5) return buildFallbackOperations(args);
|
|
53
|
+
const matrix = Array.from({ length: args.beforeLines.length + 1 }, () => new Uint32Array(args.afterLines.length + 1));
|
|
54
|
+
for (let leftIndex = args.beforeLines.length - 1; leftIndex >= 0; leftIndex -= 1) for (let rightIndex = args.afterLines.length - 1; rightIndex >= 0; rightIndex -= 1) matrix[leftIndex][rightIndex] = args.beforeLines[leftIndex] === args.afterLines[rightIndex] ? matrix[leftIndex + 1][rightIndex + 1] + 1 : Math.max(matrix[leftIndex + 1][rightIndex], matrix[leftIndex][rightIndex + 1]);
|
|
55
|
+
const operations = [];
|
|
56
|
+
let leftIndex = 0;
|
|
57
|
+
let rightIndex = 0;
|
|
58
|
+
while (leftIndex < args.beforeLines.length && rightIndex < args.afterLines.length) {
|
|
59
|
+
if (args.beforeLines[leftIndex] === args.afterLines[rightIndex]) {
|
|
60
|
+
operations.push({
|
|
61
|
+
type: "context",
|
|
62
|
+
text: args.beforeLines[leftIndex]
|
|
63
|
+
});
|
|
64
|
+
leftIndex += 1;
|
|
65
|
+
rightIndex += 1;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (matrix[leftIndex + 1][rightIndex] >= matrix[leftIndex][rightIndex + 1]) {
|
|
69
|
+
operations.push({
|
|
70
|
+
type: "remove",
|
|
71
|
+
text: args.beforeLines[leftIndex]
|
|
72
|
+
});
|
|
73
|
+
leftIndex += 1;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
operations.push({
|
|
77
|
+
type: "add",
|
|
78
|
+
text: args.afterLines[rightIndex]
|
|
79
|
+
});
|
|
80
|
+
rightIndex += 1;
|
|
81
|
+
}
|
|
82
|
+
while (leftIndex < args.beforeLines.length) {
|
|
83
|
+
operations.push({
|
|
84
|
+
type: "remove",
|
|
85
|
+
text: args.beforeLines[leftIndex]
|
|
86
|
+
});
|
|
87
|
+
leftIndex += 1;
|
|
88
|
+
}
|
|
89
|
+
while (rightIndex < args.afterLines.length) {
|
|
90
|
+
operations.push({
|
|
91
|
+
type: "add",
|
|
92
|
+
text: args.afterLines[rightIndex]
|
|
93
|
+
});
|
|
94
|
+
rightIndex += 1;
|
|
95
|
+
}
|
|
96
|
+
return operations;
|
|
97
|
+
}
|
|
98
|
+
function buildFallbackOperations(args) {
|
|
99
|
+
const operations = [];
|
|
100
|
+
let prefix = 0;
|
|
101
|
+
while (prefix < args.beforeLines.length && prefix < args.afterLines.length && args.beforeLines[prefix] === args.afterLines[prefix]) prefix += 1;
|
|
102
|
+
let beforeSuffix = args.beforeLines.length - 1;
|
|
103
|
+
let afterSuffix = args.afterLines.length - 1;
|
|
104
|
+
while (beforeSuffix >= prefix && afterSuffix >= prefix && args.beforeLines[beforeSuffix] === args.afterLines[afterSuffix]) {
|
|
105
|
+
beforeSuffix -= 1;
|
|
106
|
+
afterSuffix -= 1;
|
|
107
|
+
}
|
|
108
|
+
for (const text of args.beforeLines.slice(0, prefix)) operations.push({
|
|
109
|
+
type: "context",
|
|
110
|
+
text
|
|
111
|
+
});
|
|
112
|
+
for (const text of args.beforeLines.slice(prefix, beforeSuffix + 1)) operations.push({
|
|
113
|
+
type: "remove",
|
|
114
|
+
text
|
|
115
|
+
});
|
|
116
|
+
for (const text of args.afterLines.slice(prefix, afterSuffix + 1)) operations.push({
|
|
117
|
+
type: "add",
|
|
118
|
+
text
|
|
119
|
+
});
|
|
120
|
+
for (const text of args.beforeLines.slice(beforeSuffix + 1)) operations.push({
|
|
121
|
+
type: "context",
|
|
122
|
+
text
|
|
123
|
+
});
|
|
124
|
+
return operations;
|
|
125
|
+
}
|
|
126
|
+
//#endregion
|
|
127
|
+
exports.computeDiffStats = computeDiffStats;
|
|
128
|
+
|
|
129
|
+
//# sourceMappingURL=diff-stats.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-stats.cjs","names":["textsMatchIgnoringLineEndings"],"sources":["../../src/shared/diff-stats.ts"],"sourcesContent":["import { textsMatchIgnoringLineEndings } from './diff-helpers.ts';\n\nexport type DiffStats = {\n\tadditions: number;\n\tdeletions: number;\n\thunkCount: number;\n\thasChanges: boolean;\n};\n\ntype DiffOperation = { type: 'context' | 'add' | 'remove'; text: string };\n\nexport function computeDiffStats(beforeText: string, afterText: string): DiffStats {\n\tif (textsMatchIgnoringLineEndings(beforeText, afterText)) {\n\t\treturn { additions: 0, deletions: 0, hunkCount: 0, hasChanges: false };\n\t}\n\n\tconst operations = diffLineOperations({\n\t\tbeforeLines: splitIntoLines(beforeText),\n\t\tafterLines: splitIntoLines(afterText),\n\t});\n\tconst additions = operations.filter((operation) => operation.type === 'add').length;\n\tconst deletions = operations.filter((operation) => operation.type === 'remove').length;\n\treturn {\n\t\tadditions,\n\t\tdeletions,\n\t\thunkCount: countDiffHunks(operations),\n\t\thasChanges: additions > 0 || deletions > 0,\n\t};\n}\n\nfunction countDiffHunks(operations: DiffOperation[]): number {\n\tlet hunks = 0;\n\tlet inChange = false;\n\n\tfor (const operation of operations) {\n\t\tconst isChange = operation.type === 'add' || operation.type === 'remove';\n\t\tif (isChange && !inChange) {\n\t\t\thunks += 1;\n\t\t\tinChange = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!isChange) {\n\t\t\tinChange = false;\n\t\t}\n\t}\n\n\treturn hunks;\n}\n\nfunction splitIntoLines(value: string): string[] {\n\tif (!value) {\n\t\treturn [];\n\t}\n\n\tconst normalized = value.replace(/\\r\\n/g, '\\n');\n\tconst lines = normalized.split('\\n');\n\tif (lines.at(-1) === '') {\n\t\tlines.pop();\n\t}\n\treturn lines;\n}\n\nfunction diffLineOperations(args: { beforeLines: string[]; afterLines: string[] }): DiffOperation[] {\n\tif (!args.beforeLines.length) {\n\t\treturn args.afterLines.map((text) => ({ type: 'add' as const, text }));\n\t}\n\n\tif (!args.afterLines.length) {\n\t\treturn args.beforeLines.map((text) => ({ type: 'remove' as const, text }));\n\t}\n\n\tif (args.beforeLines.length * args.afterLines.length > 1_200_000) {\n\t\treturn buildFallbackOperations(args);\n\t}\n\n\tconst matrix = Array.from({ length: args.beforeLines.length + 1 }, () => new Uint32Array(args.afterLines.length + 1));\n\n\tfor (let leftIndex = args.beforeLines.length - 1; leftIndex >= 0; leftIndex -= 1) {\n\t\tfor (let rightIndex = args.afterLines.length - 1; rightIndex >= 0; rightIndex -= 1) {\n\t\t\tmatrix[leftIndex][rightIndex] =\n\t\t\t\targs.beforeLines[leftIndex] === args.afterLines[rightIndex]\n\t\t\t\t\t? matrix[leftIndex + 1][rightIndex + 1] + 1\n\t\t\t\t\t: Math.max(matrix[leftIndex + 1][rightIndex], matrix[leftIndex][rightIndex + 1]);\n\t\t}\n\t}\n\n\tconst operations: DiffOperation[] = [];\n\tlet leftIndex = 0;\n\tlet rightIndex = 0;\n\n\twhile (leftIndex < args.beforeLines.length && rightIndex < args.afterLines.length) {\n\t\tif (args.beforeLines[leftIndex] === args.afterLines[rightIndex]) {\n\t\t\toperations.push({ type: 'context', text: args.beforeLines[leftIndex] });\n\t\t\tleftIndex += 1;\n\t\t\trightIndex += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (matrix[leftIndex + 1][rightIndex] >= matrix[leftIndex][rightIndex + 1]) {\n\t\t\toperations.push({ type: 'remove', text: args.beforeLines[leftIndex] });\n\t\t\tleftIndex += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\toperations.push({ type: 'add', text: args.afterLines[rightIndex] });\n\t\trightIndex += 1;\n\t}\n\n\twhile (leftIndex < args.beforeLines.length) {\n\t\toperations.push({ type: 'remove', text: args.beforeLines[leftIndex] });\n\t\tleftIndex += 1;\n\t}\n\n\twhile (rightIndex < args.afterLines.length) {\n\t\toperations.push({ type: 'add', text: args.afterLines[rightIndex] });\n\t\trightIndex += 1;\n\t}\n\n\treturn operations;\n}\n\nfunction buildFallbackOperations(args: { beforeLines: string[]; afterLines: string[] }): DiffOperation[] {\n\tconst operations: DiffOperation[] = [];\n\tlet prefix = 0;\n\twhile (\n\t\tprefix < args.beforeLines.length &&\n\t\tprefix < args.afterLines.length &&\n\t\targs.beforeLines[prefix] === args.afterLines[prefix]\n\t) {\n\t\tprefix += 1;\n\t}\n\n\tlet beforeSuffix = args.beforeLines.length - 1;\n\tlet afterSuffix = args.afterLines.length - 1;\n\twhile (\n\t\tbeforeSuffix >= prefix &&\n\t\tafterSuffix >= prefix &&\n\t\targs.beforeLines[beforeSuffix] === args.afterLines[afterSuffix]\n\t) {\n\t\tbeforeSuffix -= 1;\n\t\tafterSuffix -= 1;\n\t}\n\n\tfor (const text of args.beforeLines.slice(0, prefix)) {\n\t\toperations.push({ type: 'context', text });\n\t}\n\tfor (const text of args.beforeLines.slice(prefix, beforeSuffix + 1)) {\n\t\toperations.push({ type: 'remove', text });\n\t}\n\tfor (const text of args.afterLines.slice(prefix, afterSuffix + 1)) {\n\t\toperations.push({ type: 'add', text });\n\t}\n\tfor (const text of args.beforeLines.slice(beforeSuffix + 1)) {\n\t\toperations.push({ type: 'context', text });\n\t}\n\n\treturn operations;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
//#region src/shared/file-oplog.ts
|
|
2
|
+
function parseJjOpLogLine(line) {
|
|
3
|
+
const [operationId = "", description = "", authorDate = ""] = line.split(" ");
|
|
4
|
+
const id = operationId.trim();
|
|
5
|
+
if (!id) return null;
|
|
6
|
+
return {
|
|
7
|
+
operationId: id,
|
|
8
|
+
description: description.trim() || "Operation",
|
|
9
|
+
authorDate: authorDate.trim() || void 0
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function parseJjOpLogOutput(output) {
|
|
13
|
+
const seen = /* @__PURE__ */ new Set();
|
|
14
|
+
const entries = [];
|
|
15
|
+
for (const raw of output.split(/\r?\n/u)) {
|
|
16
|
+
const line = raw.trim();
|
|
17
|
+
if (!line) continue;
|
|
18
|
+
const parsed = parseJjOpLogLine(line);
|
|
19
|
+
if (!parsed || seen.has(parsed.operationId)) continue;
|
|
20
|
+
seen.add(parsed.operationId);
|
|
21
|
+
entries.push(parsed);
|
|
22
|
+
}
|
|
23
|
+
return entries;
|
|
24
|
+
}
|
|
25
|
+
/** Prefer longer prefix matches so short op ids still link. */
|
|
26
|
+
function findEntryForOperation(entries, operationId) {
|
|
27
|
+
const needle = operationId.toLowerCase();
|
|
28
|
+
let best;
|
|
29
|
+
let bestLen = -1;
|
|
30
|
+
for (const entry of entries) {
|
|
31
|
+
const id = (entry.operationId || "").toLowerCase();
|
|
32
|
+
if (!id) continue;
|
|
33
|
+
if (id === needle || id.startsWith(needle) || needle.startsWith(id)) {
|
|
34
|
+
const len = Math.min(id.length, needle.length);
|
|
35
|
+
if (len > bestLen) {
|
|
36
|
+
best = entry;
|
|
37
|
+
bestLen = len;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return best;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Keep recent ops that touched the file (linked via known snapshot/revision ops),
|
|
45
|
+
* or whose description mentions the relative path.
|
|
46
|
+
*/
|
|
47
|
+
function filterFileOpLogPeek(args) {
|
|
48
|
+
const limit = args.limit ?? 12;
|
|
49
|
+
const pathNeedle = args.relativePath.trim().toLowerCase();
|
|
50
|
+
const fileName = pathNeedle.includes("/") ? pathNeedle.slice(pathNeedle.lastIndexOf("/") + 1) : pathNeedle;
|
|
51
|
+
const result = [];
|
|
52
|
+
for (const op of args.opLog) {
|
|
53
|
+
const linked = findEntryForOperation(args.fileEntries, op.operationId);
|
|
54
|
+
const desc = op.description.toLowerCase();
|
|
55
|
+
const pathHit = Boolean(pathNeedle) && (desc.includes(pathNeedle) || fileName.length > 2 && desc.includes(fileName));
|
|
56
|
+
if (!linked && !pathHit) continue;
|
|
57
|
+
result.push({
|
|
58
|
+
...op,
|
|
59
|
+
entryIndex: linked?.index,
|
|
60
|
+
changeId: linked?.changeId,
|
|
61
|
+
operationIndex: linked?.operationIndex,
|
|
62
|
+
description: op.description || linked?.description || "Operation"
|
|
63
|
+
});
|
|
64
|
+
if (result.length >= limit) break;
|
|
65
|
+
}
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
const JJ_OP_LOG_TEMPLATE = [
|
|
69
|
+
"self.id().short(12)",
|
|
70
|
+
"\"\\t\"",
|
|
71
|
+
"description.first_line()",
|
|
72
|
+
"\"\\t\"",
|
|
73
|
+
"time.end().local().format(\"%Y-%m-%dT%H:%M:%S\")",
|
|
74
|
+
"\"\\n\""
|
|
75
|
+
].join(" ++ ");
|
|
76
|
+
//#endregion
|
|
77
|
+
exports.JJ_OP_LOG_TEMPLATE = JJ_OP_LOG_TEMPLATE;
|
|
78
|
+
exports.filterFileOpLogPeek = filterFileOpLogPeek;
|
|
79
|
+
exports.parseJjOpLogLine = parseJjOpLogLine;
|
|
80
|
+
exports.parseJjOpLogOutput = parseJjOpLogOutput;
|
|
81
|
+
|
|
82
|
+
//# sourceMappingURL=file-oplog.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-oplog.cjs","names":[],"sources":["../../src/shared/file-oplog.ts"],"sourcesContent":["import type { FileRevisionEntry } from './timeline-types.ts';\n\nexport type FileOpLogEntry = {\n\toperationId: string;\n\tdescription: string;\n\tauthorDate?: string;\n\t/** Snapshot/revision entry index to jump to when present. */\n\tentryIndex?: number;\n\tchangeId?: string;\n\toperationIndex?: number;\n};\n\nexport function parseJjOpLogLine(line: string): FileOpLogEntry | null {\n\tconst [operationId = '', description = '', authorDate = ''] = line.split('\\t');\n\tconst id = operationId.trim();\n\tif (!id) {\n\t\treturn null;\n\t}\n\treturn {\n\t\toperationId: id,\n\t\tdescription: description.trim() || 'Operation',\n\t\tauthorDate: authorDate.trim() || undefined,\n\t};\n}\n\nexport function parseJjOpLogOutput(output: string): FileOpLogEntry[] {\n\tconst seen = new Set<string>();\n\tconst entries: FileOpLogEntry[] = [];\n\tfor (const raw of output.split(/\\r?\\n/u)) {\n\t\tconst line = raw.trim();\n\t\tif (!line) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst parsed = parseJjOpLogLine(line);\n\t\tif (!parsed || seen.has(parsed.operationId)) {\n\t\t\tcontinue;\n\t\t}\n\t\tseen.add(parsed.operationId);\n\t\tentries.push(parsed);\n\t}\n\treturn entries;\n}\n\n/** Prefer longer prefix matches so short op ids still link. */\nfunction findEntryForOperation(\n\tentries: ReadonlyArray<FileRevisionEntry>,\n\toperationId: string,\n): FileRevisionEntry | undefined {\n\tconst needle = operationId.toLowerCase();\n\tlet best: FileRevisionEntry | undefined;\n\tlet bestLen = -1;\n\tfor (const entry of entries) {\n\t\tconst id = (entry.operationId || '').toLowerCase();\n\t\tif (!id) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (id === needle || id.startsWith(needle) || needle.startsWith(id)) {\n\t\t\tconst len = Math.min(id.length, needle.length);\n\t\t\tif (len > bestLen) {\n\t\t\t\tbest = entry;\n\t\t\t\tbestLen = len;\n\t\t\t}\n\t\t}\n\t}\n\treturn best;\n}\n\n/**\n * Keep recent ops that touched the file (linked via known snapshot/revision ops),\n * or whose description mentions the relative path.\n */\nexport function filterFileOpLogPeek(args: {\n\topLog: ReadonlyArray<FileOpLogEntry>;\n\tfileEntries: ReadonlyArray<FileRevisionEntry>;\n\trelativePath: string;\n\tlimit?: number;\n}): FileOpLogEntry[] {\n\tconst limit = args.limit ?? 12;\n\tconst pathNeedle = args.relativePath.trim().toLowerCase();\n\tconst fileName = pathNeedle.includes('/') ? pathNeedle.slice(pathNeedle.lastIndexOf('/') + 1) : pathNeedle;\n\tconst result: FileOpLogEntry[] = [];\n\n\tfor (const op of args.opLog) {\n\t\tconst linked = findEntryForOperation(args.fileEntries, op.operationId);\n\t\tconst desc = op.description.toLowerCase();\n\t\tconst pathHit =\n\t\t\tBoolean(pathNeedle) && (desc.includes(pathNeedle) || (fileName.length > 2 && desc.includes(fileName)));\n\t\tif (!linked && !pathHit) {\n\t\t\tcontinue;\n\t\t}\n\t\tresult.push({\n\t\t\t...op,\n\t\t\tentryIndex: linked?.index,\n\t\t\tchangeId: linked?.changeId,\n\t\t\toperationIndex: linked?.operationIndex,\n\t\t\tdescription: op.description || linked?.description || 'Operation',\n\t\t});\n\t\tif (result.length >= limit) {\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn result;\n}\n\nexport const JJ_OP_LOG_TEMPLATE = [\n\t'self.id().short(12)',\n\t'\"\\\\t\"',\n\t'description.first_line()',\n\t'\"\\\\t\"',\n\t'time.end().local().format(\"%Y-%m-%dT%H:%M:%S\")',\n\t'\"\\\\n\"',\n].join(' ++ ');\n"],"mappings":";AAYA,SAAgB,iBAAiB,MAAqC;CACrE,MAAM,CAAC,cAAc,IAAI,cAAc,IAAI,aAAa,MAAM,KAAK,MAAM,GAAI;CAC7E,MAAM,KAAK,YAAY,KAAK;CAC5B,IAAI,CAAC,IACJ,OAAO;CAER,OAAO;EACN,aAAa;EACb,aAAa,YAAY,KAAK,KAAK;EACnC,YAAY,WAAW,KAAK,KAAK,KAAA;CAClC;AACD;AAEA,SAAgB,mBAAmB,QAAkC;CACpE,MAAM,uBAAO,IAAI,IAAY;CAC7B,MAAM,UAA4B,CAAC;CACnC,KAAK,MAAM,OAAO,OAAO,MAAM,QAAQ,GAAG;EACzC,MAAM,OAAO,IAAI,KAAK;EACtB,IAAI,CAAC,MACJ;EAED,MAAM,SAAS,iBAAiB,IAAI;EACpC,IAAI,CAAC,UAAU,KAAK,IAAI,OAAO,WAAW,GACzC;EAED,KAAK,IAAI,OAAO,WAAW;EAC3B,QAAQ,KAAK,MAAM;CACpB;CACA,OAAO;AACR;;AAGA,SAAS,sBACR,SACA,aACgC;CAChC,MAAM,SAAS,YAAY,YAAY;CACvC,IAAI;CACJ,IAAI,UAAU;CACd,KAAK,MAAM,SAAS,SAAS;EAC5B,MAAM,MAAM,MAAM,eAAe,GAAA,CAAI,YAAY;EACjD,IAAI,CAAC,IACJ;EAED,IAAI,OAAO,UAAU,GAAG,WAAW,MAAM,KAAK,OAAO,WAAW,EAAE,GAAG;GACpE,MAAM,MAAM,KAAK,IAAI,GAAG,QAAQ,OAAO,MAAM;GAC7C,IAAI,MAAM,SAAS;IAClB,OAAO;IACP,UAAU;GACX;EACD;CACD;CACA,OAAO;AACR;;;;;AAMA,SAAgB,oBAAoB,MAKf;CACpB,MAAM,QAAQ,KAAK,SAAS;CAC5B,MAAM,aAAa,KAAK,aAAa,KAAK,CAAC,CAAC,YAAY;CACxD,MAAM,WAAW,WAAW,SAAS,GAAG,IAAI,WAAW,MAAM,WAAW,YAAY,GAAG,IAAI,CAAC,IAAI;CAChG,MAAM,SAA2B,CAAC;CAElC,KAAK,MAAM,MAAM,KAAK,OAAO;EAC5B,MAAM,SAAS,sBAAsB,KAAK,aAAa,GAAG,WAAW;EACrE,MAAM,OAAO,GAAG,YAAY,YAAY;EACxC,MAAM,UACL,QAAQ,UAAU,MAAM,KAAK,SAAS,UAAU,KAAM,SAAS,SAAS,KAAK,KAAK,SAAS,QAAQ;EACpG,IAAI,CAAC,UAAU,CAAC,SACf;EAED,OAAO,KAAK;GACX,GAAG;GACH,YAAY,QAAQ;GACpB,UAAU,QAAQ;GAClB,gBAAgB,QAAQ;GACxB,aAAa,GAAG,eAAe,QAAQ,eAAe;EACvD,CAAC;EACD,IAAI,OAAO,UAAU,OACpB;CAEF;CACA,OAAO;AACR;AAEA,MAAa,qBAAqB;CACjC;CACA;CACA;CACA;CACA;CACA;AACD,CAAC,CAAC,KAAK,MAAM"}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
let node_path = require("node:path");
|
|
3
|
+
node_path = require_runtime.__toESM(node_path, 1);
|
|
4
|
+
//#region src/shared/history-helpers.ts
|
|
5
|
+
function parseMarkerNames(rawValue) {
|
|
6
|
+
const names = rawValue.split(",").map((value) => value.trim()).filter(Boolean);
|
|
7
|
+
return names.length ? [...new Set(names)] : void 0;
|
|
8
|
+
}
|
|
9
|
+
function parseGitBranchNames(decorations) {
|
|
10
|
+
const names = decorations.split(",").map((value) => value.trim()).flatMap((value) => {
|
|
11
|
+
if (!value || value === "HEAD" || value.startsWith("tag: ")) return [];
|
|
12
|
+
const [left, right] = value.split("->").map((part) => part.trim());
|
|
13
|
+
if (right) return right === "HEAD" ? [] : [right];
|
|
14
|
+
return left ? [left] : [];
|
|
15
|
+
}).filter(Boolean);
|
|
16
|
+
return names.length ? [...new Set(names)] : void 0;
|
|
17
|
+
}
|
|
18
|
+
function parseJjSummaryRenameLines(output) {
|
|
19
|
+
return output.split(/\r?\n/u).map((line) => line.trim()).filter(Boolean).reduce((entries, line) => {
|
|
20
|
+
const match = /^R\s+(.+?)\s+=>\s+(.+)$/u.exec(line);
|
|
21
|
+
if (!match) return entries;
|
|
22
|
+
const fromPath = match[1].trim();
|
|
23
|
+
const toPath = match[2].trim();
|
|
24
|
+
const braceStart = fromPath.indexOf("{");
|
|
25
|
+
const braceEnd = toPath.lastIndexOf("}");
|
|
26
|
+
if (braceStart >= 0 && braceEnd >= 0) {
|
|
27
|
+
const prefix = fromPath.slice(0, braceStart);
|
|
28
|
+
const fromSuffix = fromPath.slice(braceStart + 1);
|
|
29
|
+
const toPrefix = toPath.slice(0, braceEnd);
|
|
30
|
+
const suffix = toPath.slice(braceEnd + 1);
|
|
31
|
+
entries.push({
|
|
32
|
+
fromPath: `${prefix}${fromSuffix}${suffix}`,
|
|
33
|
+
toPath: `${prefix}${toPrefix}${suffix}`
|
|
34
|
+
});
|
|
35
|
+
return entries;
|
|
36
|
+
}
|
|
37
|
+
entries.push({
|
|
38
|
+
fromPath,
|
|
39
|
+
toPath
|
|
40
|
+
});
|
|
41
|
+
return entries;
|
|
42
|
+
}, []);
|
|
43
|
+
}
|
|
44
|
+
function parseJjEvolutionSummaryHeader(line) {
|
|
45
|
+
const tokens = line.trim().split(/\s+/u);
|
|
46
|
+
if (tokens.length < 5) return null;
|
|
47
|
+
const dateIndex = tokens.findIndex((token) => /^\d{4}-\d{2}-\d{2}$/u.test(token));
|
|
48
|
+
if (dateIndex < 2 || dateIndex + 2 >= tokens.length) return null;
|
|
49
|
+
const timeToken = tokens[dateIndex + 1];
|
|
50
|
+
if (!/^\d{2}:\d{2}:\d{2}$/u.test(timeToken)) return null;
|
|
51
|
+
const revisionIndex = tokens.findLastIndex((token) => /^[0-9a-f]{8,}$/u.test(token));
|
|
52
|
+
if (revisionIndex <= dateIndex + 1) return null;
|
|
53
|
+
const changeKey = tokens[0];
|
|
54
|
+
const [changeId = "", operationIndexRaw = ""] = changeKey.split("/");
|
|
55
|
+
const operationIndex = Number.parseInt(operationIndexRaw, 10);
|
|
56
|
+
const bookmarkNames = tokens.slice(dateIndex + 2, revisionIndex).filter(Boolean);
|
|
57
|
+
return {
|
|
58
|
+
changeKey,
|
|
59
|
+
changeId: changeId || void 0,
|
|
60
|
+
operationIndex: Number.isInteger(operationIndex) ? operationIndex : void 0,
|
|
61
|
+
...bookmarkNames.length ? { bookmarkNames } : {},
|
|
62
|
+
authorDate: `${tokens[dateIndex]}T${timeToken}`,
|
|
63
|
+
authorName: tokens.slice(1, dateIndex).join(" ") || "Unknown author",
|
|
64
|
+
revision: tokens[revisionIndex] || ""
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function normalizeSnapshotOperationKey(changeKey) {
|
|
68
|
+
const trimmed = String(changeKey || "").trim();
|
|
69
|
+
if (!trimmed) return;
|
|
70
|
+
return trimmed.includes("/") ? trimmed : `${trimmed}/0`;
|
|
71
|
+
}
|
|
72
|
+
function toJjRootFileFileset(relativePath) {
|
|
73
|
+
return `root-file:${JSON.stringify(relativePath)}`;
|
|
74
|
+
}
|
|
75
|
+
function resolvePreferredHistoryBackend(args) {
|
|
76
|
+
const workspacePath = normalizeFilesystemPath(args.workspacePath);
|
|
77
|
+
const gitRoot = normalizeCandidateRoot(args.gitRoot, workspacePath);
|
|
78
|
+
const jjRoot = normalizeCandidateRoot(args.jjRoot, workspacePath);
|
|
79
|
+
if (gitRoot && jjRoot) {
|
|
80
|
+
if (gitRoot === jjRoot) return "jj";
|
|
81
|
+
if (isPathWithinRoot({
|
|
82
|
+
candidatePath: gitRoot,
|
|
83
|
+
rootPath: jjRoot
|
|
84
|
+
})) return "git";
|
|
85
|
+
if (isPathWithinRoot({
|
|
86
|
+
candidatePath: jjRoot,
|
|
87
|
+
rootPath: gitRoot
|
|
88
|
+
})) return "jj";
|
|
89
|
+
return gitRoot.length >= jjRoot.length ? "git" : "jj";
|
|
90
|
+
}
|
|
91
|
+
if (jjRoot) return "jj";
|
|
92
|
+
if (gitRoot) return "git";
|
|
93
|
+
}
|
|
94
|
+
function normalizeCandidateRoot(root, workspacePath) {
|
|
95
|
+
const trimmed = String(root || "").trim();
|
|
96
|
+
if (!trimmed) return;
|
|
97
|
+
const normalizedRoot = normalizeFilesystemPath(trimmed);
|
|
98
|
+
return isPathWithinRoot({
|
|
99
|
+
candidatePath: workspacePath,
|
|
100
|
+
rootPath: normalizedRoot
|
|
101
|
+
}) ? normalizedRoot : void 0;
|
|
102
|
+
}
|
|
103
|
+
function normalizeFilesystemPath(value) {
|
|
104
|
+
return node_path.default.resolve(value.trim());
|
|
105
|
+
}
|
|
106
|
+
function isPathWithinRoot(args) {
|
|
107
|
+
const relativePath = node_path.default.relative(args.rootPath, args.candidatePath);
|
|
108
|
+
return relativePath === "" || !relativePath.startsWith("..") && !node_path.default.isAbsolute(relativePath);
|
|
109
|
+
}
|
|
110
|
+
function parseJjEvolutionSummaryEntries(output) {
|
|
111
|
+
const lines = output.split(/\r?\n/u);
|
|
112
|
+
const entries = [];
|
|
113
|
+
let current = null;
|
|
114
|
+
let descriptionCaptured = false;
|
|
115
|
+
const pushCurrent = () => {
|
|
116
|
+
if (!current) return;
|
|
117
|
+
entries.push(current);
|
|
118
|
+
current = null;
|
|
119
|
+
descriptionCaptured = false;
|
|
120
|
+
};
|
|
121
|
+
for (const rawLine of lines) {
|
|
122
|
+
const line = rawLine.trim();
|
|
123
|
+
if (!line) continue;
|
|
124
|
+
const header = parseJjEvolutionSummaryHeader(line);
|
|
125
|
+
if (header) {
|
|
126
|
+
pushCurrent();
|
|
127
|
+
current = {
|
|
128
|
+
...header,
|
|
129
|
+
description: "Snapshot",
|
|
130
|
+
operationId: void 0,
|
|
131
|
+
operationDescription: "snapshot working copy",
|
|
132
|
+
summaryLines: []
|
|
133
|
+
};
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (!current) continue;
|
|
137
|
+
if (!descriptionCaptured) {
|
|
138
|
+
current.description = line;
|
|
139
|
+
descriptionCaptured = true;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
const operationMatch = /^-- operation ([0-9a-f]+)\s*(.*)$/u.exec(line);
|
|
143
|
+
if (operationMatch) {
|
|
144
|
+
current.operationId = operationMatch[1] || void 0;
|
|
145
|
+
current.operationDescription = operationMatch[2] || "snapshot working copy";
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
current.summaryLines.push(line);
|
|
149
|
+
}
|
|
150
|
+
pushCurrent();
|
|
151
|
+
return entries;
|
|
152
|
+
}
|
|
153
|
+
function parseJjBookmarkNames(rawValue) {
|
|
154
|
+
return parseMarkerNames(rawValue);
|
|
155
|
+
}
|
|
156
|
+
/** jj template prints `true`/`false` for empty/conflict/immutable. */
|
|
157
|
+
function parseJjBooleanFlag(rawValue) {
|
|
158
|
+
const value = (rawValue || "").trim().toLowerCase();
|
|
159
|
+
return value === "true" || value === "1" || value === "yes";
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Shared jj log template fields for file/repo history lines:
|
|
163
|
+
* revision, changeId, date, author, bookmarks, empty, conflict, immutable, description
|
|
164
|
+
*/
|
|
165
|
+
function buildJjHistoryLogTemplate() {
|
|
166
|
+
return [
|
|
167
|
+
"commit_id.short()",
|
|
168
|
+
"\"\\t\"",
|
|
169
|
+
"change_id.shortest()",
|
|
170
|
+
"\"\\t\"",
|
|
171
|
+
"author.timestamp().format(\"%Y-%m-%dT%H:%M:%S%:z\")",
|
|
172
|
+
"\"\\t\"",
|
|
173
|
+
"author.name()",
|
|
174
|
+
"\"\\t\"",
|
|
175
|
+
"self.local_bookmarks().map(|b| b.name()).join(\",\")",
|
|
176
|
+
"\"\\t\"",
|
|
177
|
+
"if(empty, \"true\", \"false\")",
|
|
178
|
+
"\"\\t\"",
|
|
179
|
+
"if(conflict, \"true\", \"false\")",
|
|
180
|
+
"\"\\t\"",
|
|
181
|
+
"if(immutable, \"true\", \"false\")",
|
|
182
|
+
"\"\\t\"",
|
|
183
|
+
"description.first_line()",
|
|
184
|
+
"\"\\n\""
|
|
185
|
+
].join(" ++ ");
|
|
186
|
+
}
|
|
187
|
+
function parseJjHistoryLine(line) {
|
|
188
|
+
const parts = line.split(" ");
|
|
189
|
+
const revision = parts[0] || "";
|
|
190
|
+
const changeId = parts[1] || "";
|
|
191
|
+
const authorDate = parts[2] || "";
|
|
192
|
+
const authorName = parts[3] || "";
|
|
193
|
+
const bookmarkNames = parts[4] || "";
|
|
194
|
+
const looksLikeFlags = parts.length >= 8 && /^(true|false|0|1)$/iu.test((parts[5] || "").trim()) && /^(true|false|0|1)$/iu.test((parts[6] || "").trim()) && /^(true|false|0|1)$/iu.test((parts[7] || "").trim());
|
|
195
|
+
const isEmpty = looksLikeFlags ? parseJjBooleanFlag(parts[5]) : void 0;
|
|
196
|
+
const hasConflict = looksLikeFlags ? parseJjBooleanFlag(parts[6]) : void 0;
|
|
197
|
+
const isImmutable = looksLikeFlags ? parseJjBooleanFlag(parts[7]) : void 0;
|
|
198
|
+
const description = looksLikeFlags ? parts.slice(8).join(" ") : parts.slice(5).join(" ");
|
|
199
|
+
return {
|
|
200
|
+
id: revision,
|
|
201
|
+
revision,
|
|
202
|
+
shortRevision: changeId || revision.slice(0, 8),
|
|
203
|
+
changeId: changeId || void 0,
|
|
204
|
+
bookmarkNames: parseJjBookmarkNames(bookmarkNames),
|
|
205
|
+
authorDate,
|
|
206
|
+
authorName: authorName || "Unknown author",
|
|
207
|
+
description: description || "No description",
|
|
208
|
+
isWorkingTree: false,
|
|
209
|
+
touchesFile: true,
|
|
210
|
+
timestamp: Date.parse(authorDate) || 0,
|
|
211
|
+
...isEmpty ? { isEmpty: true } : {},
|
|
212
|
+
...hasConflict ? { hasConflict: true } : {},
|
|
213
|
+
...isImmutable ? { isImmutable: true } : {}
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
function parseJjSummaryChangedPaths(summaryLines) {
|
|
217
|
+
const lines = Array.isArray(summaryLines) ? summaryLines : String(summaryLines || "").split(/\r?\n/u);
|
|
218
|
+
const renamePaths = parseJjSummaryRenameLines(lines.join("\n")).flatMap((entry) => [entry.fromPath, entry.toPath]);
|
|
219
|
+
const directPaths = lines.reduce((paths, rawLine) => {
|
|
220
|
+
const line = rawLine.trim();
|
|
221
|
+
if (!line || /^R\s+/u.test(line)) return paths;
|
|
222
|
+
const match = /^[A-Z?]\s+(.+)$/u.exec(line);
|
|
223
|
+
if (match) paths.push(match[1].trim());
|
|
224
|
+
return paths;
|
|
225
|
+
}, []);
|
|
226
|
+
return [.../* @__PURE__ */ new Set([...directPaths, ...renamePaths])];
|
|
227
|
+
}
|
|
228
|
+
function getGitHubRemoteBaseUrl(remote) {
|
|
229
|
+
const trimmed = remote.trim();
|
|
230
|
+
if (!trimmed) return;
|
|
231
|
+
const httpsMatch = /^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/u.exec(trimmed);
|
|
232
|
+
if (httpsMatch) return `https://github.com/${httpsMatch[1]}/${httpsMatch[2]}`;
|
|
233
|
+
const sshMatch = /^(?:ssh:\/\/)?git@github\.com[:/]([^/]+)\/([^/]+?)(?:\.git)?$/u.exec(trimmed);
|
|
234
|
+
if (sshMatch) return `https://github.com/${sshMatch[1]}/${sshMatch[2]}`;
|
|
235
|
+
}
|
|
236
|
+
function dedupeAdjacentEntriesByChangeId(entries) {
|
|
237
|
+
return entries.filter((entry, index) => {
|
|
238
|
+
if (!entry.changeId || index === 0) return true;
|
|
239
|
+
return entries[index - 1]?.changeId !== entry.changeId;
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
//#endregion
|
|
243
|
+
exports.buildJjHistoryLogTemplate = buildJjHistoryLogTemplate;
|
|
244
|
+
exports.dedupeAdjacentEntriesByChangeId = dedupeAdjacentEntriesByChangeId;
|
|
245
|
+
exports.getGitHubRemoteBaseUrl = getGitHubRemoteBaseUrl;
|
|
246
|
+
exports.normalizeSnapshotOperationKey = normalizeSnapshotOperationKey;
|
|
247
|
+
exports.parseGitBranchNames = parseGitBranchNames;
|
|
248
|
+
exports.parseJjBookmarkNames = parseJjBookmarkNames;
|
|
249
|
+
exports.parseJjBooleanFlag = parseJjBooleanFlag;
|
|
250
|
+
exports.parseJjEvolutionSummaryEntries = parseJjEvolutionSummaryEntries;
|
|
251
|
+
exports.parseJjHistoryLine = parseJjHistoryLine;
|
|
252
|
+
exports.parseJjSummaryChangedPaths = parseJjSummaryChangedPaths;
|
|
253
|
+
exports.parseJjSummaryRenameLines = parseJjSummaryRenameLines;
|
|
254
|
+
exports.resolvePreferredHistoryBackend = resolvePreferredHistoryBackend;
|
|
255
|
+
exports.toJjRootFileFileset = toJjRootFileFileset;
|
|
256
|
+
|
|
257
|
+
//# sourceMappingURL=history-helpers.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-helpers.cjs","names":["path"],"sources":["../../src/shared/history-helpers.ts"],"sourcesContent":["import path from 'node:path';\n\nimport type { FileRevisionEntry } from './timeline-types.ts';\n\ntype RenameEntry = {\n\tfromPath: string;\n\ttoPath: string;\n};\n\ntype ParsedEvolutionLine = {\n\trevision: string;\n\tchangeId?: string;\n\tauthorDate: string;\n\tauthorName: string;\n\tdescription: string;\n\toperationDescription: string;\n};\n\ntype ParsedEvolutionSummaryEntry = {\n\tchangeKey: string;\n\tchangeId?: string;\n\toperationIndex?: number;\n\tbookmarkNames?: string[];\n\tauthorDate: string;\n\tauthorName: string;\n\trevision: string;\n\tdescription: string;\n\toperationId?: string;\n\toperationDescription: string;\n\tsummaryLines: string[];\n};\n\ntype ParsedEvolutionSummaryHeader = {\n\tchangeKey: string;\n\tchangeId?: string;\n\toperationIndex?: number;\n\tbookmarkNames?: string[];\n\tauthorDate: string;\n\tauthorName: string;\n\trevision: string;\n};\n\nfunction parseMarkerNames(rawValue: string): string[] | undefined {\n\tconst names = rawValue\n\t\t.split(',')\n\t\t.map((value) => value.trim())\n\t\t.filter(Boolean);\n\n\treturn names.length ? [...new Set(names)] : undefined;\n}\n\nexport function parseGitBranchNames(decorations: string): string[] | undefined {\n\tconst names = decorations\n\t\t.split(',')\n\t\t.map((value) => value.trim())\n\t\t.flatMap((value) => {\n\t\t\tif (!value || value === 'HEAD' || value.startsWith('tag: ')) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\tconst [left, right] = value.split('->').map((part) => part.trim());\n\t\t\tif (right) {\n\t\t\t\treturn right === 'HEAD' ? [] : [right];\n\t\t\t}\n\n\t\t\treturn left ? [left] : [];\n\t\t})\n\t\t.filter(Boolean);\n\n\treturn names.length ? [...new Set(names)] : undefined;\n}\n\nexport function parseJjSummaryRenameLines(output: string): RenameEntry[] {\n\treturn output\n\t\t.split(/\\r?\\n/u)\n\t\t.map((line) => line.trim())\n\t\t.filter(Boolean)\n\t\t.reduce<RenameEntry[]>((entries, line) => {\n\t\t\tconst match = /^R\\s+(.+?)\\s+=>\\s+(.+)$/u.exec(line);\n\t\t\tif (!match) {\n\t\t\t\treturn entries;\n\t\t\t}\n\n\t\t\tconst fromPath = match[1].trim();\n\t\t\tconst toPath = match[2].trim();\n\t\t\tconst braceStart = fromPath.indexOf('{');\n\t\t\tconst braceEnd = toPath.lastIndexOf('}');\n\n\t\t\tif (braceStart >= 0 && braceEnd >= 0) {\n\t\t\t\tconst prefix = fromPath.slice(0, braceStart);\n\t\t\t\tconst fromSuffix = fromPath.slice(braceStart + 1);\n\t\t\t\tconst toPrefix = toPath.slice(0, braceEnd);\n\t\t\t\tconst suffix = toPath.slice(braceEnd + 1);\n\n\t\t\t\tentries.push({\n\t\t\t\t\tfromPath: `${prefix}${fromSuffix}${suffix}`,\n\t\t\t\t\ttoPath: `${prefix}${toPrefix}${suffix}`,\n\t\t\t\t});\n\t\t\t\treturn entries;\n\t\t\t}\n\n\t\t\tentries.push({\n\t\t\t\tfromPath,\n\t\t\t\ttoPath,\n\t\t\t});\n\t\t\treturn entries;\n\t\t}, []);\n}\n\nexport function parseJjEvolutionLine(line: string): ParsedEvolutionLine {\n\tconst [\n\t\trevision = '',\n\t\tchangeId = '',\n\t\tauthorDate = '',\n\t\tauthorName = '',\n\t\toperationDescription = '',\n\t\t...descriptionParts\n\t] = line.split('\\t');\n\tconst description = descriptionParts.join('\\t') || operationDescription || 'Snapshot';\n\treturn {\n\t\trevision,\n\t\tchangeId: changeId || undefined,\n\t\tauthorDate,\n\t\tauthorName: authorName || 'Unknown author',\n\t\tdescription,\n\t\toperationDescription: operationDescription || 'snapshot working copy',\n\t};\n}\n\nfunction parseJjEvolutionSummaryHeader(line: string): ParsedEvolutionSummaryHeader | null {\n\tconst tokens = line.trim().split(/\\s+/u);\n\tif (tokens.length < 5) {\n\t\treturn null;\n\t}\n\n\tconst dateIndex = tokens.findIndex((token) => /^\\d{4}-\\d{2}-\\d{2}$/u.test(token));\n\tif (dateIndex < 2 || dateIndex + 2 >= tokens.length) {\n\t\treturn null;\n\t}\n\n\tconst timeToken = tokens[dateIndex + 1];\n\tif (!/^\\d{2}:\\d{2}:\\d{2}$/u.test(timeToken)) {\n\t\treturn null;\n\t}\n\n\tconst revisionIndex = tokens.findLastIndex((token) => /^[0-9a-f]{8,}$/u.test(token));\n\tif (revisionIndex <= dateIndex + 1) {\n\t\treturn null;\n\t}\n\n\tconst changeKey = tokens[0];\n\tconst [changeId = '', operationIndexRaw = ''] = changeKey.split('/');\n\tconst operationIndex = Number.parseInt(operationIndexRaw, 10);\n\tconst bookmarkNames = tokens.slice(dateIndex + 2, revisionIndex).filter(Boolean);\n\n\treturn {\n\t\tchangeKey,\n\t\tchangeId: changeId || undefined,\n\t\toperationIndex: Number.isInteger(operationIndex) ? operationIndex : undefined,\n\t\t...(bookmarkNames.length ? { bookmarkNames } : {}),\n\t\tauthorDate: `${tokens[dateIndex]}T${timeToken}`,\n\t\tauthorName: tokens.slice(1, dateIndex).join(' ') || 'Unknown author',\n\t\trevision: tokens[revisionIndex] || '',\n\t};\n}\n\nexport function normalizeSnapshotOperationKey(changeKey?: string): string | undefined {\n\tconst trimmed = String(changeKey || '').trim();\n\tif (!trimmed) {\n\t\treturn undefined;\n\t}\n\n\treturn trimmed.includes('/') ? trimmed : `${trimmed}/0`;\n}\n\nexport function toJjRootFileFileset(relativePath: string): string {\n\treturn `root-file:${JSON.stringify(relativePath)}`;\n}\n\nexport function resolvePreferredHistoryBackend(args: {\n\tworkspacePath: string;\n\tgitRoot?: string;\n\tjjRoot?: string;\n}): 'git' | 'jj' | undefined {\n\tconst workspacePath = normalizeFilesystemPath(args.workspacePath);\n\tconst gitRoot = normalizeCandidateRoot(args.gitRoot, workspacePath);\n\tconst jjRoot = normalizeCandidateRoot(args.jjRoot, workspacePath);\n\n\tif (gitRoot && jjRoot) {\n\t\tif (gitRoot === jjRoot) {\n\t\t\treturn 'jj';\n\t\t}\n\n\t\tif (isPathWithinRoot({ candidatePath: gitRoot, rootPath: jjRoot })) {\n\t\t\treturn 'git';\n\t\t}\n\n\t\tif (isPathWithinRoot({ candidatePath: jjRoot, rootPath: gitRoot })) {\n\t\t\treturn 'jj';\n\t\t}\n\n\t\treturn gitRoot.length >= jjRoot.length ? 'git' : 'jj';\n\t}\n\n\tif (jjRoot) {\n\t\treturn 'jj';\n\t}\n\n\tif (gitRoot) {\n\t\treturn 'git';\n\t}\n\n\treturn undefined;\n}\n\nfunction normalizeCandidateRoot(root: string | undefined, workspacePath: string): string | undefined {\n\tconst trimmed = String(root || '').trim();\n\tif (!trimmed) {\n\t\treturn undefined;\n\t}\n\n\tconst normalizedRoot = normalizeFilesystemPath(trimmed);\n\treturn isPathWithinRoot({ candidatePath: workspacePath, rootPath: normalizedRoot }) ? normalizedRoot : undefined;\n}\n\nfunction normalizeFilesystemPath(value: string): string {\n\treturn path.resolve(value.trim());\n}\n\nfunction isPathWithinRoot(args: { candidatePath: string; rootPath: string }): boolean {\n\tconst relativePath = path.relative(args.rootPath, args.candidatePath);\n\treturn relativePath === '' || (!relativePath.startsWith('..') && !path.isAbsolute(relativePath));\n}\n\nexport function parseJjEvolutionSummaryEntries(output: string): ParsedEvolutionSummaryEntry[] {\n\tconst lines = output.split(/\\r?\\n/u);\n\tconst entries: ParsedEvolutionSummaryEntry[] = [];\n\tlet current: ParsedEvolutionSummaryEntry | null = null;\n\tlet descriptionCaptured = false;\n\n\tconst pushCurrent = () => {\n\t\tif (!current) {\n\t\t\treturn;\n\t\t}\n\n\t\tentries.push(current);\n\t\tcurrent = null;\n\t\tdescriptionCaptured = false;\n\t};\n\n\tfor (const rawLine of lines) {\n\t\tconst line = rawLine.trim();\n\t\tif (!line) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst header = parseJjEvolutionSummaryHeader(line);\n\t\tif (header) {\n\t\t\tpushCurrent();\n\t\t\tcurrent = {\n\t\t\t\t...header,\n\t\t\t\tdescription: 'Snapshot',\n\t\t\t\toperationId: undefined,\n\t\t\t\toperationDescription: 'snapshot working copy',\n\t\t\t\tsummaryLines: [],\n\t\t\t};\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!current) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!descriptionCaptured) {\n\t\t\tcurrent.description = line;\n\t\t\tdescriptionCaptured = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst operationMatch = /^-- operation ([0-9a-f]+)\\s*(.*)$/u.exec(line);\n\t\tif (operationMatch) {\n\t\t\tcurrent.operationId = operationMatch[1] || undefined;\n\t\t\tcurrent.operationDescription = operationMatch[2] || 'snapshot working copy';\n\t\t\tcontinue;\n\t\t}\n\n\t\tcurrent.summaryLines.push(line);\n\t}\n\n\tpushCurrent();\n\treturn entries;\n}\n\nexport function parseJjBookmarkNames(rawValue: string): string[] | undefined {\n\treturn parseMarkerNames(rawValue);\n}\n\n/** jj template prints `true`/`false` for empty/conflict/immutable. */\nexport function parseJjBooleanFlag(rawValue: string | undefined): boolean {\n\tconst value = (rawValue || '').trim().toLowerCase();\n\treturn value === 'true' || value === '1' || value === 'yes';\n}\n\n/**\n * Shared jj log template fields for file/repo history lines:\n * revision, changeId, date, author, bookmarks, empty, conflict, immutable, description\n */\nexport function buildJjHistoryLogTemplate(): string {\n\treturn [\n\t\t'commit_id.short()',\n\t\t'\"\\\\t\"',\n\t\t'change_id.shortest()',\n\t\t'\"\\\\t\"',\n\t\t'author.timestamp().format(\"%Y-%m-%dT%H:%M:%S%:z\")',\n\t\t'\"\\\\t\"',\n\t\t'author.name()',\n\t\t'\"\\\\t\"',\n\t\t'self.local_bookmarks().map(|b| b.name()).join(\",\")',\n\t\t'\"\\\\t\"',\n\t\t'if(empty, \"true\", \"false\")',\n\t\t'\"\\\\t\"',\n\t\t'if(conflict, \"true\", \"false\")',\n\t\t'\"\\\\t\"',\n\t\t'if(immutable, \"true\", \"false\")',\n\t\t'\"\\\\t\"',\n\t\t'description.first_line()',\n\t\t'\"\\\\n\"',\n\t].join(' ++ ');\n}\n\nexport function parseJjHistoryLine(line: string): FileRevisionEntry {\n\tconst parts = line.split('\\t');\n\tconst revision = parts[0] || '';\n\tconst changeId = parts[1] || '';\n\tconst authorDate = parts[2] || '';\n\tconst authorName = parts[3] || '';\n\tconst bookmarkNames = parts[4] || '';\n\n\t// New format: … bookmarks, empty, conflict, immutable, description…\n\t// Legacy: … bookmarks, description…\n\tconst looksLikeFlags =\n\t\tparts.length >= 8 &&\n\t\t/^(true|false|0|1)$/iu.test((parts[5] || '').trim()) &&\n\t\t/^(true|false|0|1)$/iu.test((parts[6] || '').trim()) &&\n\t\t/^(true|false|0|1)$/iu.test((parts[7] || '').trim());\n\n\tconst isEmpty = looksLikeFlags ? parseJjBooleanFlag(parts[5]) : undefined;\n\tconst hasConflict = looksLikeFlags ? parseJjBooleanFlag(parts[6]) : undefined;\n\tconst isImmutable = looksLikeFlags ? parseJjBooleanFlag(parts[7]) : undefined;\n\tconst description = looksLikeFlags ? parts.slice(8).join('\\t') : parts.slice(5).join('\\t');\n\n\treturn {\n\t\tid: revision,\n\t\trevision,\n\t\tshortRevision: changeId || revision.slice(0, 8),\n\t\tchangeId: changeId || undefined,\n\t\tbookmarkNames: parseJjBookmarkNames(bookmarkNames),\n\t\tauthorDate,\n\t\tauthorName: authorName || 'Unknown author',\n\t\tdescription: description || 'No description',\n\t\tisWorkingTree: false,\n\t\ttouchesFile: true,\n\t\ttimestamp: Date.parse(authorDate) || 0,\n\t\t...(isEmpty ? { isEmpty: true } : {}),\n\t\t...(hasConflict ? { hasConflict: true } : {}),\n\t\t...(isImmutable ? { isImmutable: true } : {}),\n\t};\n}\n\nexport function parseJjSummaryChangedPaths(summaryLines: string[] | string): string[] {\n\tconst lines = Array.isArray(summaryLines) ? summaryLines : String(summaryLines || '').split(/\\r?\\n/u);\n\tconst renameLines = parseJjSummaryRenameLines(lines.join('\\n'));\n\tconst renamePaths = renameLines.flatMap((entry) => [entry.fromPath, entry.toPath]);\n\tconst directPaths = lines.reduce<string[]>((paths, rawLine) => {\n\t\tconst line = rawLine.trim();\n\t\tif (!line || /^R\\s+/u.test(line)) {\n\t\t\treturn paths;\n\t\t}\n\n\t\tconst match = /^[A-Z?]\\s+(.+)$/u.exec(line);\n\t\tif (match) {\n\t\t\tpaths.push(match[1].trim());\n\t\t}\n\n\t\treturn paths;\n\t}, []);\n\n\treturn [...new Set([...directPaths, ...renamePaths])];\n}\n\nexport function getGitHubRemoteBaseUrl(remote: string): string | undefined {\n\tconst trimmed = remote.trim();\n\tif (!trimmed) {\n\t\treturn undefined;\n\t}\n\n\tconst httpsMatch = /^https?:\\/\\/github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git)?$/u.exec(trimmed);\n\tif (httpsMatch) {\n\t\treturn `https://github.com/${httpsMatch[1]}/${httpsMatch[2]}`;\n\t}\n\n\tconst sshMatch = /^(?:ssh:\\/\\/)?git@github\\.com[:/]([^/]+)\\/([^/]+?)(?:\\.git)?$/u.exec(trimmed);\n\tif (sshMatch) {\n\t\treturn `https://github.com/${sshMatch[1]}/${sshMatch[2]}`;\n\t}\n\n\treturn undefined;\n}\n\nexport function dedupeAdjacentEntriesByChangeId<T extends { changeId?: string }>(entries: T[]): T[] {\n\treturn entries.filter((entry, index) => {\n\t\tif (!entry.changeId || index === 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn entries[index - 1]?.changeId !== entry.changeId;\n\t});\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
const require_diff_content_search = require("./diff-content-search.cjs");
|
|
2
|
+
//#region src/shared/history-search.ts
|
|
3
|
+
function normalizeHistorySearchQuery(query) {
|
|
4
|
+
return query.trim();
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Walk oldest→newest file contents and classify when `query` first appears / last disappears.
|
|
8
|
+
* `contentsByIndex` maps absolute entry index → file text at that stop.
|
|
9
|
+
*/
|
|
10
|
+
function searchHistoryContents(args) {
|
|
11
|
+
const query = normalizeHistorySearchQuery(args.query);
|
|
12
|
+
const hits = [];
|
|
13
|
+
let introducedAt = null;
|
|
14
|
+
let removedAt = null;
|
|
15
|
+
if (!query) return {
|
|
16
|
+
query,
|
|
17
|
+
hits,
|
|
18
|
+
introducedAt,
|
|
19
|
+
removedAt
|
|
20
|
+
};
|
|
21
|
+
let wasPresent = false;
|
|
22
|
+
for (const entryIndex of args.orderedEntryIndexes) {
|
|
23
|
+
const present = (args.contentsByIndex.get(entryIndex) ?? "").includes(query);
|
|
24
|
+
if (present) {
|
|
25
|
+
hits.push({
|
|
26
|
+
entryIndex,
|
|
27
|
+
kind: wasPresent ? "present" : "introduced"
|
|
28
|
+
});
|
|
29
|
+
if (!wasPresent) introducedAt = entryIndex;
|
|
30
|
+
} else if (wasPresent) {
|
|
31
|
+
hits.push({
|
|
32
|
+
entryIndex,
|
|
33
|
+
kind: "removed"
|
|
34
|
+
});
|
|
35
|
+
removedAt = entryIndex;
|
|
36
|
+
}
|
|
37
|
+
wasPresent = present;
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
query,
|
|
41
|
+
hits,
|
|
42
|
+
introducedAt,
|
|
43
|
+
removedAt
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Sidebar `content:` matches — only revisions whose parent→self diff hunks contain the needle.
|
|
48
|
+
*/
|
|
49
|
+
function searchHistoryDiffContents(args) {
|
|
50
|
+
const query = normalizeHistorySearchQuery(args.query);
|
|
51
|
+
const hits = [];
|
|
52
|
+
if (!query) return {
|
|
53
|
+
query,
|
|
54
|
+
hits,
|
|
55
|
+
introducedAt: null,
|
|
56
|
+
removedAt: null,
|
|
57
|
+
purpose: "sidebar"
|
|
58
|
+
};
|
|
59
|
+
let previousContent = "";
|
|
60
|
+
for (const entryIndex of args.orderedEntryIndexes) {
|
|
61
|
+
const content = args.contentsByIndex.get(entryIndex) ?? "";
|
|
62
|
+
if (require_diff_content_search.diffHunkContainsNeedle({
|
|
63
|
+
before: previousContent,
|
|
64
|
+
after: content,
|
|
65
|
+
needle: query
|
|
66
|
+
})) hits.push({
|
|
67
|
+
entryIndex,
|
|
68
|
+
kind: "present"
|
|
69
|
+
});
|
|
70
|
+
previousContent = content;
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
query,
|
|
74
|
+
hits,
|
|
75
|
+
introducedAt: hits[0]?.entryIndex ?? null,
|
|
76
|
+
removedAt: null,
|
|
77
|
+
purpose: "sidebar"
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
exports.normalizeHistorySearchQuery = normalizeHistorySearchQuery;
|
|
82
|
+
exports.searchHistoryContents = searchHistoryContents;
|
|
83
|
+
exports.searchHistoryDiffContents = searchHistoryDiffContents;
|
|
84
|
+
|
|
85
|
+
//# sourceMappingURL=history-search.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-search.cjs","names":["diffHunkContainsNeedle"],"sources":["../../src/shared/history-search.ts"],"sourcesContent":["import { diffHunkContainsNeedle } from './diff-content-search.ts';\n\nexport type HistorySearchHit = {\n\tentryIndex: number;\n\tkind: 'introduced' | 'removed' | 'present';\n};\n\nexport type HistorySearchResult = {\n\tquery: string;\n\thits: HistorySearchHit[];\n\tintroducedAt: number | null;\n\tremovedAt: number | null;\n\tpurpose?: 'history' | 'sidebar';\n};\n\nexport function normalizeHistorySearchQuery(query: string): string {\n\treturn query.trim();\n}\n\n/**\n * Walk oldest→newest file contents and classify when `query` first appears / last disappears.\n * `contentsByIndex` maps absolute entry index → file text at that stop.\n */\nexport function searchHistoryContents(args: {\n\tquery: string;\n\torderedEntryIndexes: number[];\n\tcontentsByIndex: Map<number, string>;\n}): HistorySearchResult {\n\tconst query = normalizeHistorySearchQuery(args.query);\n\tconst hits: HistorySearchHit[] = [];\n\tlet introducedAt: number | null = null;\n\tlet removedAt: number | null = null;\n\tif (!query) {\n\t\treturn { query, hits, introducedAt, removedAt };\n\t}\n\n\tlet wasPresent = false;\n\tfor (const entryIndex of args.orderedEntryIndexes) {\n\t\tconst content = args.contentsByIndex.get(entryIndex) ?? '';\n\t\tconst present = content.includes(query);\n\t\tif (present) {\n\t\t\thits.push({ entryIndex, kind: wasPresent ? 'present' : 'introduced' });\n\t\t\tif (!wasPresent) {\n\t\t\t\tintroducedAt = entryIndex;\n\t\t\t}\n\t\t} else if (wasPresent) {\n\t\t\thits.push({ entryIndex, kind: 'removed' });\n\t\t\tremovedAt = entryIndex;\n\t\t}\n\t\twasPresent = present;\n\t}\n\n\treturn { query, hits, introducedAt, removedAt };\n}\n\n/**\n * Sidebar `content:` matches — only revisions whose parent→self diff hunks contain the needle.\n */\nexport function searchHistoryDiffContents(args: {\n\tquery: string;\n\torderedEntryIndexes: number[];\n\tcontentsByIndex: Map<number, string>;\n}): HistorySearchResult {\n\tconst query = normalizeHistorySearchQuery(args.query);\n\tconst hits: HistorySearchHit[] = [];\n\tif (!query) {\n\t\treturn { query, hits, introducedAt: null, removedAt: null, purpose: 'sidebar' };\n\t}\n\n\tlet previousContent = '';\n\tfor (const entryIndex of args.orderedEntryIndexes) {\n\t\tconst content = args.contentsByIndex.get(entryIndex) ?? '';\n\t\tif (diffHunkContainsNeedle({ before: previousContent, after: content, needle: query })) {\n\t\t\thits.push({ entryIndex, kind: 'present' });\n\t\t}\n\t\tpreviousContent = content;\n\t}\n\n\treturn {\n\t\tquery,\n\t\thits,\n\t\tintroducedAt: hits[0]?.entryIndex ?? null,\n\t\tremovedAt: null,\n\t\tpurpose: 'sidebar',\n\t};\n}\n"],"mappings":";;AAeA,SAAgB,4BAA4B,OAAuB;CAClE,OAAO,MAAM,KAAK;AACnB;;;;;AAMA,SAAgB,sBAAsB,MAId;CACvB,MAAM,QAAQ,4BAA4B,KAAK,KAAK;CACpD,MAAM,OAA2B,CAAC;CAClC,IAAI,eAA8B;CAClC,IAAI,YAA2B;CAC/B,IAAI,CAAC,OACJ,OAAO;EAAE;EAAO;EAAM;EAAc;CAAU;CAG/C,IAAI,aAAa;CACjB,KAAK,MAAM,cAAc,KAAK,qBAAqB;EAElD,MAAM,WADU,KAAK,gBAAgB,IAAI,UAAU,KAAK,GAAA,CAChC,SAAS,KAAK;EACtC,IAAI,SAAS;GACZ,KAAK,KAAK;IAAE;IAAY,MAAM,aAAa,YAAY;GAAa,CAAC;GACrE,IAAI,CAAC,YACJ,eAAe;EAEjB,OAAO,IAAI,YAAY;GACtB,KAAK,KAAK;IAAE;IAAY,MAAM;GAAU,CAAC;GACzC,YAAY;EACb;EACA,aAAa;CACd;CAEA,OAAO;EAAE;EAAO;EAAM;EAAc;CAAU;AAC/C;;;;AAKA,SAAgB,0BAA0B,MAIlB;CACvB,MAAM,QAAQ,4BAA4B,KAAK,KAAK;CACpD,MAAM,OAA2B,CAAC;CAClC,IAAI,CAAC,OACJ,OAAO;EAAE;EAAO;EAAM,cAAc;EAAM,WAAW;EAAM,SAAS;CAAU;CAG/E,IAAI,kBAAkB;CACtB,KAAK,MAAM,cAAc,KAAK,qBAAqB;EAClD,MAAM,UAAU,KAAK,gBAAgB,IAAI,UAAU,KAAK;EACxD,IAAIA,4BAAAA,uBAAuB;GAAE,QAAQ;GAAiB,OAAO;GAAS,QAAQ;EAAM,CAAC,GACpF,KAAK,KAAK;GAAE;GAAY,MAAM;EAAU,CAAC;EAE1C,kBAAkB;CACnB;CAEA,OAAO;EACN;EACA;EACA,cAAc,KAAK,EAAE,EAAE,cAAc;EACrC,WAAW;EACX,SAAS;CACV;AACD"}
|