@hienlh/ppm 0.9.85 → 0.9.87
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/260415-0932-git-graph-stash-rebase-conflicts/reports/code-reviewer-260415-1020-stash-rebase-conflicts.md +288 -0
- package/260415-0932-git-graph-stash-rebase-conflicts/reports/tester-260415-1020-build-check.md +117 -0
- package/260415-1150-ext-silent-failure-debugging/reports/code-reviewer-260415-1159-ext-error-reporting-review.md +205 -0
- package/260415-1150-ext-silent-failure-debugging/reports/docs-manager-260415-1206-ext-error-reporting.md +99 -0
- package/260415-1150-ext-silent-failure-debugging/reports/tester-260415-1159-extension-error-reporting.md +174 -0
- package/CHANGELOG.md +24 -0
- package/dist/web/assets/{_basePickBy-D-bUmjma.js → _basePickBy-Bj0dI1ei.js} +1 -1
- package/dist/web/assets/{_baseUniq-BnXXIfRB.js → _baseUniq-CyzdZeQH.js} +1 -1
- package/dist/web/assets/ai-settings-section-Bo9lCaTd.js +1 -0
- package/dist/web/assets/{api-settings-Qi2xRiHa.js → api-settings-CUxg9RE5.js} +1 -1
- package/dist/web/assets/{arc-DB9vXGzd.js → arc-CxgHJ7Z4.js} +1 -1
- package/dist/web/assets/architecture-PBZL5I3N-DDFO_NKq.js +1 -0
- package/dist/web/assets/{architectureDiagram-2XIMDMQ5-BBV25747.js → architectureDiagram-2XIMDMQ5-D16OotsC.js} +1 -1
- package/dist/web/assets/arrow-up-I9-21gkR.js +1 -0
- package/dist/web/assets/{blockDiagram-WCTKOSBZ-BOTnY2Lq.js → blockDiagram-WCTKOSBZ-Ct57Wtfk.js} +1 -1
- package/dist/web/assets/{c4Diagram-IC4MRINW-D7QAUdHD.js → c4Diagram-IC4MRINW-BIymcNsg.js} +1 -1
- package/dist/web/assets/channel-wumTB1if.js +1 -0
- package/dist/web/assets/chat-tab-R4gKsnxD.js +10 -0
- package/dist/web/assets/chevron-right-DY_wImxB.js +1 -0
- package/dist/web/assets/{chunk-4BX2VUAB-BnOVw77D.js → chunk-4BX2VUAB-CENmY7Kw.js} +1 -1
- package/dist/web/assets/{chunk-55IACEB6-BftA8DxR.js → chunk-55IACEB6-DhZGI1l3.js} +1 -1
- package/dist/web/assets/{chunk-7E7YKBS2-B0vnP8v3.js → chunk-7E7YKBS2-DZcnC7Ow.js} +1 -1
- package/dist/web/assets/{chunk-7R4GIKGN-Czlaj26D.js → chunk-7R4GIKGN-y8bfHEy-.js} +2 -2
- package/dist/web/assets/{chunk-C72U2L5F-DpEbDtMo.js → chunk-C72U2L5F-BHPkfQj2.js} +1 -1
- package/dist/web/assets/{chunk-EGIJ26TM-BWXe6lkx.js → chunk-EGIJ26TM-nant2LXl.js} +1 -1
- package/dist/web/assets/{chunk-FMBD7UC4-DspqhPfk.js → chunk-FMBD7UC4-Bog4cpN-.js} +1 -1
- package/dist/web/assets/{chunk-GEFDOKGD-D6HHRbYk.js → chunk-GEFDOKGD-86LFbsAC.js} +1 -1
- package/dist/web/assets/chunk-GLR3WWYH-Re-5eSlQ.js +2 -0
- package/dist/web/assets/chunk-HHEYEP7N-C45i5G_3.js +1 -0
- package/dist/web/assets/{chunk-JSJVCQXG-BC8wnMwf.js → chunk-JSJVCQXG-23eG9mgt.js} +1 -1
- package/dist/web/assets/{chunk-KX2RTZJC-D3VDtyvX.js → chunk-KX2RTZJC-CHj8TnTB.js} +1 -1
- package/dist/web/assets/{chunk-KYZI473N-Z-NBw_HS.js → chunk-KYZI473N-gqRLpJ4w.js} +1 -1
- package/dist/web/assets/{chunk-L3YUKLVL--RGkEh__.js → chunk-L3YUKLVL-DnSMmNFC.js} +1 -1
- package/dist/web/assets/{chunk-MX3YWQON-2B76t_Kx.js → chunk-MX3YWQON-B6g1ZH9X.js} +1 -1
- package/dist/web/assets/{chunk-NQ4KR5QH-BekY3tEi.js → chunk-NQ4KR5QH-DX32345Y.js} +1 -1
- package/dist/web/assets/{chunk-O4XLMI2P-2CJLfx_1.js → chunk-O4XLMI2P-Vp_V4P-b.js} +1 -1
- package/dist/web/assets/{chunk-OZEHJAEY-sug_L09P.js → chunk-OZEHJAEY-lKq2SWjA.js} +1 -1
- package/dist/web/assets/{chunk-PQ6SQG4A-_fwPRLQy.js → chunk-PQ6SQG4A-Bik13fTV.js} +1 -1
- package/dist/web/assets/{chunk-PU5JKC2W-BUaTFJVQ.js → chunk-PU5JKC2W-DD95Rx35.js} +1 -1
- package/dist/web/assets/chunk-QZHKN3VN-N3VXx1VH.js +1 -0
- package/dist/web/assets/{chunk-R5LLSJPH-C37xW0vj.js → chunk-R5LLSJPH-dRhXRnrb.js} +1 -1
- package/dist/web/assets/{chunk-WL4C6EOR-CCkt_MT6.js → chunk-WL4C6EOR-B1iIvLOG.js} +1 -1
- package/dist/web/assets/{chunk-XIRO2GV7-Dz2LBq7Y.js → chunk-XIRO2GV7-DZBoNl1_.js} +1 -1
- package/dist/web/assets/{chunk-XPW4576I-DenTbBuj.js → chunk-XPW4576I-CgLyyW03.js} +1 -1
- package/dist/web/assets/{chunk-XZSTWKYB-Dbp1nUSQ.js → chunk-XZSTWKYB-DjV8xl5A.js} +1 -1
- package/dist/web/assets/{chunk-YBOYWFTD-3OTKowjE.js → chunk-YBOYWFTD-D_ILLe6_.js} +1 -1
- package/dist/web/assets/classDiagram-VBA2DB6C-mr-Cb1me.js +1 -0
- package/dist/web/assets/classDiagram-v2-RAHNMMFH-BKe8_uda.js +1 -0
- package/dist/web/assets/clone--z5KLAuR.js +1 -0
- package/dist/web/assets/code-editor-Br0vzTOy.js +8 -0
- package/dist/web/assets/columns-2-IeETSfON.js +1 -0
- package/dist/web/assets/conflict-editor-BPgCjnNz.js +19 -0
- package/dist/web/assets/{cose-bilkent-S5V4N54A-MbmGZnt0.js → cose-bilkent-S5V4N54A-BGNPFv3x.js} +1 -1
- package/dist/web/assets/{csv-preview-uZ_7b8I7.js → csv-preview-BZRICDP0.js} +2 -2
- package/dist/web/assets/{dagre-CPhI6v-K.js → dagre-CkhlMHnx.js} +1 -1
- package/dist/web/assets/{dagre-KLK3FWXG-CmSE-oNj.js → dagre-KLK3FWXG-Cnp996VG.js} +1 -1
- package/dist/web/assets/database-CgTomMxt.js +1 -0
- package/dist/web/assets/{database-viewer-5xljX0JI.js → database-viewer-DaUoQ-oR.js} +2 -2
- package/dist/web/assets/{diagram-E7M64L7V-B5XG3ZT7.js → diagram-E7M64L7V-BZF0tSOr.js} +1 -1
- package/dist/web/assets/{diagram-IFDJBPK2-BsP248aX.js → diagram-IFDJBPK2-nUcO8sN8.js} +1 -1
- package/dist/web/assets/{diagram-P4PSJMXO-Cna3408N.js → diagram-P4PSJMXO-CW0eCkwC.js} +1 -1
- package/dist/web/assets/diff-viewer-BzvK3gAE.js +4 -0
- package/dist/web/assets/dist-CM0oD8tQ.js +1 -0
- package/dist/web/assets/{erDiagram-INFDFZHY-B7SgktiR.js → erDiagram-INFDFZHY-DSkriYZ9.js} +1 -1
- package/dist/web/assets/extension-webview-CGepEw-b.js +3 -0
- package/dist/web/assets/{flowDiagram-PKNHOUZH-FOYZZ1OB.js → flowDiagram-PKNHOUZH-CFYAfZBx.js} +1 -1
- package/dist/web/assets/{ganttDiagram-A5KZAMGK-CnHVYh9v.js → ganttDiagram-A5KZAMGK-KSn4XAU4.js} +1 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-OkvBPi6H.js +1 -0
- package/dist/web/assets/{gitGraphDiagram-K3NZZRJ6-0G9XxZay.js → gitGraphDiagram-K3NZZRJ6-BMgjjVys.js} +1 -1
- package/dist/web/assets/{graphlib-CNiBwlg_.js → graphlib-BWe1iK_s.js} +1 -1
- package/dist/web/assets/index-CKsEzQ4f.js +26 -0
- package/dist/web/assets/index-Chf0otez.css +2 -0
- package/dist/web/assets/info-3K5VOQVL-BDU2_bYD.js +1 -0
- package/dist/web/assets/infoDiagram-LFFYTUFH-Diq4Cyc3.js +2 -0
- package/dist/web/assets/input-BHj0veau.js +45 -0
- package/dist/web/assets/{isEmpty-CcCb5n2-.js → isEmpty-BfLnxq-B.js} +1 -1
- package/dist/web/assets/{ishikawaDiagram-PHBUUO56-D4QCzh5J.js → ishikawaDiagram-PHBUUO56-CiVEvp8o.js} +1 -1
- package/dist/web/assets/{journeyDiagram-4ABVD52K-CnHYNfKW.js → journeyDiagram-4ABVD52K-CG_v5Aho.js} +1 -1
- package/dist/web/assets/jsx-runtime-BRW_vwa9.js +1 -0
- package/dist/web/assets/{kanban-definition-K7BYSVSG-Bh_g3EVu.js → kanban-definition-K7BYSVSG-miB0-_Zq.js} +1 -1
- package/dist/web/assets/keybindings-store-D5zgHod8.js +1 -0
- package/dist/web/assets/{line-6d3eBADm.js → line-CSuSrJ9J.js} +1 -1
- package/dist/web/assets/{linear-cA_2lQy7.js → linear-DFN_MPsw.js} +1 -1
- package/dist/web/assets/{markdown-renderer-CZ07F7T6.js → markdown-renderer-DSYnGywb.js} +6 -6
- package/dist/web/assets/{mermaid-parser.core-C3kd7JXM.js → mermaid-parser.core-CFdP1Z5_.js} +2 -2
- package/dist/web/assets/{mindmap-definition-YRQLILUH-CYiUwhr_.js → mindmap-definition-YRQLILUH-pYPWwASE.js} +1 -1
- package/dist/web/assets/{ordinal-XHK5vIzZ.js → ordinal-DpFn432U.js} +1 -1
- package/dist/web/assets/packet-RMMSAZCW-BwpIpYB3.js +1 -0
- package/dist/web/assets/pie-UPGHQEXC-BPgAfmes.js +1 -0
- package/dist/web/assets/{pieDiagram-SKSYHLDU-D0S7jeZA.js → pieDiagram-SKSYHLDU-Dovdlvhu.js} +1 -1
- package/dist/web/assets/plus-DQGIb4mQ.js +1 -0
- package/dist/web/assets/port-forwarding-tab-vmqDKmk2.js +1 -0
- package/dist/web/assets/{postgres-viewer-RldlAO_m.js → postgres-viewer-0lIAosrr.js} +3 -3
- package/dist/web/assets/{quadrantDiagram-337W2JSQ-0hNP63hW.js → quadrantDiagram-337W2JSQ-TXe6cU_F.js} +1 -1
- package/dist/web/assets/radar-KQ55EAFF-TqxBkWx-.js +1 -0
- package/dist/web/assets/refresh-cw-Clk8fdUD.js +1 -0
- package/dist/web/assets/{requirementDiagram-Z7DCOOCP-BVnmqFbL.js → requirementDiagram-Z7DCOOCP-CuiiuGS9.js} +1 -1
- package/dist/web/assets/{sankeyDiagram-WA2Y5GQK-DVkYdCJb.js → sankeyDiagram-WA2Y5GQK-BbRmhv0t.js} +1 -1
- package/dist/web/assets/scroll-area-BpXCNme3.js +1 -0
- package/dist/web/assets/{sequenceDiagram-2WXFIKYE-B80s7sOg.js → sequenceDiagram-2WXFIKYE-B2D8IQDb.js} +1 -1
- package/dist/web/assets/settings-tab-CMnv1fce.js +1 -0
- package/dist/web/assets/{sql-query-editor-CjZ7Z6XL.js → sql-query-editor-Bc2hAwqT.js} +1 -1
- package/dist/web/assets/sqlite-viewer-B60MS2Dy.js +1 -0
- package/dist/web/assets/square-vBdqj0bF.js +1 -0
- package/dist/web/assets/{stateDiagram-RAJIS63D-BPLXgXRR.js → stateDiagram-RAJIS63D-ylr4HxPu.js} +1 -1
- package/dist/web/assets/stateDiagram-v2-FVOUBMTO-D6zvxf3M.js +1 -0
- package/dist/web/assets/table-Bi27fEaN.js +1 -0
- package/dist/web/assets/{terminal-tab-DjzD8GLn.js → terminal-tab-CCJoLstH.js} +2 -2
- package/dist/web/assets/text-wrap-D_OmSzhp.js +1 -0
- package/dist/web/assets/{timeline-definition-YZTLITO2-fa_51u1X.js → timeline-definition-YZTLITO2-pMv1grvM.js} +1 -1
- package/dist/web/assets/trash-2-CNuB-htI.js +1 -0
- package/dist/web/assets/treemap-KZPCXAKY-Kck06FKU.js +1 -0
- package/dist/web/assets/{use-monaco-theme-D9XFxQuU.js → use-monaco-theme-BJK48EmK.js} +1 -1
- package/dist/web/assets/{vennDiagram-LZ73GAT5-kX4jJn6W.js → vennDiagram-LZ73GAT5-C-rkIUbo.js} +1 -1
- package/dist/web/assets/x-Dw3TjeY_.js +1 -0
- package/dist/web/assets/{xychartDiagram-JWTSCODW-Bzm5lZBs.js → xychartDiagram-JWTSCODW-CtpjAakO.js} +1 -1
- package/dist/web/index.html +18 -22
- package/dist/web/sw.js +1 -1
- package/docs/codebase-summary.md +169 -13
- package/docs/extension-development-guide.md +98 -1
- package/docs/journals/260414-1400-ext-git-graph-port-complete.md +147 -0
- package/docs/journals/260414-1452-git-graph-faithful-port.md +144 -0
- package/docs/journals/260414-1810-git-graph-ui-improvements-complete.md +261 -0
- package/docs/journals/260414-2001-bundled-extensions.md +219 -0
- package/docs/project-changelog.md +123 -21
- package/docs/project-roadmap.md +4 -2
- package/docs/system-architecture.md +77 -6
- package/package.json +1 -1
- package/packages/ext-git-graph/package.json +30 -0
- package/packages/ext-git-graph/src/extension-integration.test.ts +230 -0
- package/packages/ext-git-graph/src/extension-parsers.test.ts +193 -0
- package/packages/ext-git-graph/src/extension.ts +921 -0
- package/packages/ext-git-graph/src/git-log-parser.test.ts +271 -0
- package/packages/ext-git-graph/src/git-log-parser.ts +38 -0
- package/packages/ext-git-graph/src/types.ts +192 -0
- package/packages/ext-git-graph/src/webview-html.test.ts +142 -0
- package/packages/ext-git-graph/src/webview-html.ts +2417 -0
- package/packages/vscode-compat/src/index.ts +4 -0
- package/packages/vscode-compat/src/process.ts +25 -0
- package/packages/vscode-compat/src/window.ts +10 -0
- package/src/cli/commands/ext-cmd.ts +3 -1
- package/src/server/ws/extensions.ts +34 -4
- package/src/services/contribution-registry.ts +14 -1
- package/src/services/extension-host-worker.ts +12 -3
- package/src/services/extension-manifest.ts +18 -1
- package/src/services/extension-rpc-handlers.ts +68 -2
- package/src/services/extension.service.ts +63 -9
- package/src/types/extension-messages.ts +3 -1
- package/src/types/extension.ts +8 -0
- package/src/web/components/editor/code-editor.tsx +16 -4
- package/src/web/components/editor/conflict-editor.tsx +368 -0
- package/src/web/components/extensions/extension-webview.tsx +153 -12
- package/src/web/components/layout/command-palette.tsx +41 -17
- package/src/web/components/layout/editor-panel.tsx +16 -4
- package/src/web/components/layout/mobile-nav.tsx +6 -5
- package/src/web/components/layout/tab-bar.tsx +3 -3
- package/src/web/components/layout/tab-content.tsx +17 -5
- package/src/web/components/settings/keyboard-shortcuts-section.tsx +46 -1
- package/src/web/hooks/use-extension-ws.ts +30 -4
- package/src/web/hooks/use-global-keybindings.ts +24 -2
- package/src/web/hooks/use-url-sync.ts +8 -3
- package/src/web/stores/extension-store.ts +8 -0
- package/src/web/stores/keybindings-store.ts +2 -3
- package/src/web/stores/panel-store.ts +2 -2
- package/src/web/stores/panel-utils.ts +6 -2
- package/src/web/stores/tab-store.ts +3 -2
- package/dist/web/assets/ai-settings-section-D6d-RmR6.js +0 -1
- package/dist/web/assets/architecture-PBZL5I3N-DpVzOETR.js +0 -1
- package/dist/web/assets/arrow-up-BigIMx-e.js +0 -1
- package/dist/web/assets/channel-Cgy1thYT.js +0 -1
- package/dist/web/assets/chat-tab-DXBb9Y3U.js +0 -10
- package/dist/web/assets/check-ePA3ZvK4.js +0 -1
- package/dist/web/assets/chevron-down-EQA06nR-.js +0 -1
- package/dist/web/assets/chevron-right-CXzzT44u.js +0 -1
- package/dist/web/assets/chunk-GLR3WWYH-CxUl1sdz.js +0 -2
- package/dist/web/assets/chunk-HHEYEP7N-DN7ebS2Y.js +0 -1
- package/dist/web/assets/chunk-QZHKN3VN-C4La7oLj.js +0 -1
- package/dist/web/assets/classDiagram-VBA2DB6C-C3IyfqG-.js +0 -1
- package/dist/web/assets/classDiagram-v2-RAHNMMFH-Dcvhz2pb.js +0 -1
- package/dist/web/assets/clone--C7Tby8z.js +0 -1
- package/dist/web/assets/code-editor-Cr7JrBKC.js +0 -8
- package/dist/web/assets/columns-2-BZ9uqssV.js +0 -1
- package/dist/web/assets/createLucideIcon-PuMiQgHl.js +0 -1
- package/dist/web/assets/database-D1ToEV9d.js +0 -1
- package/dist/web/assets/diff-viewer-BBr6e_gb.js +0 -4
- package/dist/web/assets/dist-KUoHa6tg.js +0 -1
- package/dist/web/assets/extension-webview-B0klBip8.js +0 -3
- package/dist/web/assets/eye-CNcBU6Tx.js +0 -1
- package/dist/web/assets/git-graph-CDiwGa0g.js +0 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-DcPyMEIJ.js +0 -1
- package/dist/web/assets/index-CkaCzNgO.css +0 -2
- package/dist/web/assets/index-Ic5uTu20.js +0 -26
- package/dist/web/assets/info-3K5VOQVL-Dw4O15cw.js +0 -1
- package/dist/web/assets/infoDiagram-LFFYTUFH-DFhmsucr.js +0 -2
- package/dist/web/assets/input-CcbTF6ih.js +0 -45
- package/dist/web/assets/jsx-runtime-R_NjdZtX.js +0 -1
- package/dist/web/assets/keybindings-store-CxE6BlG2.js +0 -1
- package/dist/web/assets/packet-RMMSAZCW-o3LmdL8H.js +0 -1
- package/dist/web/assets/pie-UPGHQEXC-BjNP0M3B.js +0 -1
- package/dist/web/assets/plus-Iso5r9vD.js +0 -1
- package/dist/web/assets/port-forwarding-tab-BPuSc6pI.js +0 -1
- package/dist/web/assets/radar-KQ55EAFF-gDgOiaME.js +0 -1
- package/dist/web/assets/refresh-cw-BgQzFNaG.js +0 -1
- package/dist/web/assets/scroll-area-i4EZlOl_.js +0 -1
- package/dist/web/assets/settings-tab-BzSSN2BQ.js +0 -1
- package/dist/web/assets/sqlite-viewer-CoyZOM_Y.js +0 -1
- package/dist/web/assets/square-pfn_LYYy.js +0 -1
- package/dist/web/assets/stateDiagram-v2-FVOUBMTO-DksQJ7es.js +0 -1
- package/dist/web/assets/table-CHv2x_qg.js +0 -1
- package/dist/web/assets/tag-Bb_UFXt0.js +0 -1
- package/dist/web/assets/text-wrap-D8BbQYTx.js +0 -1
- package/dist/web/assets/trash-2-DYCa06CV.js +0 -1
- package/dist/web/assets/treemap-KZPCXAKY-DwFqAvnj.js +0 -1
- package/dist/web/assets/x-BXecj-16.js +0 -1
- package/src/web/components/git/git-graph-branch-label.tsx +0 -124
- package/src/web/components/git/git-graph-constants.ts +0 -185
- package/src/web/components/git/git-graph-detail.tsx +0 -107
- package/src/web/components/git/git-graph-dialog.tsx +0 -72
- package/src/web/components/git/git-graph-row.tsx +0 -167
- package/src/web/components/git/git-graph-settings-dialog.tsx +0 -104
- package/src/web/components/git/git-graph-svg.tsx +0 -54
- package/src/web/components/git/git-graph-toolbar.tsx +0 -195
- package/src/web/components/git/git-graph.tsx +0 -193
- package/src/web/components/git/use-column-resize.ts +0 -33
- package/src/web/components/git/use-git-graph.ts +0 -201
- /package/dist/web/assets/{api-client-wQbeUyeh.js → api-client-BvxmRZUi.js} +0 -0
- /package/dist/web/assets/{array-X0JlPOfd.js → array-BFDiaBgf.js} +0 -0
- /package/dist/web/assets/{csv-parser-CElqio6o.js → csv-parser-i7fjqP2H.js} +0 -0
- /package/dist/web/assets/{cytoscape.esm-BfIOPvwt.js → cytoscape.esm-C8i2jUzT.js} +0 -0
- /package/dist/web/assets/{defaultLocale-B6RGN4id.js → defaultLocale-ZeknFqNe.js} +0 -0
- /package/dist/web/assets/{dist-CK1enexV.js → dist-DZmJeHOA.js} +0 -0
- /package/dist/web/assets/{init-BmUWJJHz.js → init-0VJVrkRJ.js} +0 -0
- /package/dist/web/assets/{isArrayLikeObject-BrCM-iA1.js → isArrayLikeObject-ClzWCpcm.js} +0 -0
- /package/dist/web/assets/{katex-xQS_6bNb.js → katex-DR0kdMDv.js} +0 -0
- /package/dist/web/assets/{lib-CfWBrYll.js → lib-DSLzfeW0.js} +0 -0
- /package/dist/web/assets/{math-CpLFzrfV.js → math-CRc16Nj6.js} +0 -0
- /package/dist/web/assets/{path-CoPyR7c2.js → path-INs8XTPH.js} +0 -0
- /package/dist/web/assets/{preload-helper-CH6UZRzu.js → preload-helper-mr3rCizq.js} +0 -0
- /package/dist/web/assets/{react-j5zqhEum.js → react-0tkk-ztn.js} +0 -0
- /package/dist/web/assets/{rough.esm-D5NinLFK.js → rough.esm-eLccZ4OJ.js} +0 -0
- /package/dist/web/assets/{sql-completion-provider-D0xutVaK.js → sql-completion-provider-B8uUWWej.js} +0 -0
- /package/dist/web/assets/{src-j04igtQ5.js → src-CqyWLlNZ.js} +0 -0
- /package/dist/web/assets/{utils-CSCvNZxE.js → utils-DX8jb5qv.js} +0 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { describe, it, expect } from "bun:test";
|
|
2
|
+
import { parseGitLog } from "./git-log-parser.ts";
|
|
3
|
+
import type { GitVertex } from "./types.ts";
|
|
4
|
+
|
|
5
|
+
describe("git-log-parser: parseGitLog", () => {
|
|
6
|
+
it("parses single commit with minimal data", () => {
|
|
7
|
+
const input = `abc123
|
|
8
|
+
def456
|
|
9
|
+
John Doe
|
|
10
|
+
john@example.com
|
|
11
|
+
1609459200
|
|
12
|
+
Jane Reviewer
|
|
13
|
+
jane@example.com
|
|
14
|
+
1609459200
|
|
15
|
+
|
|
16
|
+
Initial commit
|
|
17
|
+
<END_COMMIT>`;
|
|
18
|
+
|
|
19
|
+
const result = parseGitLog(input);
|
|
20
|
+
expect(result).toHaveLength(1);
|
|
21
|
+
const commit = result[0] as GitVertex;
|
|
22
|
+
expect(commit.hash).toBe("abc123");
|
|
23
|
+
expect(commit.parents).toEqual(["def456"]);
|
|
24
|
+
expect(commit.author).toBe("John Doe");
|
|
25
|
+
expect(commit.authorEmail).toBe("john@example.com");
|
|
26
|
+
expect(commit.authorDate).toBe(1609459200);
|
|
27
|
+
expect(commit.committer).toBe("Jane Reviewer");
|
|
28
|
+
expect(commit.committerEmail).toBe("jane@example.com");
|
|
29
|
+
expect(commit.commitDate).toBe(1609459200);
|
|
30
|
+
expect(commit.message).toBe("Initial commit");
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("parses commit with multiple parents (merge commit)", () => {
|
|
34
|
+
const input = `abc123
|
|
35
|
+
def456 ghi789
|
|
36
|
+
Author Name
|
|
37
|
+
author@example.com
|
|
38
|
+
1609459200
|
|
39
|
+
Committer Name
|
|
40
|
+
committer@example.com
|
|
41
|
+
1609459200
|
|
42
|
+
|
|
43
|
+
Merge branch 'feature'
|
|
44
|
+
<END_COMMIT>`;
|
|
45
|
+
|
|
46
|
+
const result = parseGitLog(input);
|
|
47
|
+
expect(result).toHaveLength(1);
|
|
48
|
+
const commit = result[0] as GitVertex;
|
|
49
|
+
expect(commit.parents).toEqual(["def456", "ghi789"]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("parses commit with no parents (root commit)", () => {
|
|
53
|
+
const input = `abc123
|
|
54
|
+
|
|
55
|
+
Author Name
|
|
56
|
+
author@example.com
|
|
57
|
+
1609459200
|
|
58
|
+
Committer Name
|
|
59
|
+
committer@example.com
|
|
60
|
+
1609459200
|
|
61
|
+
|
|
62
|
+
Root commit
|
|
63
|
+
<END_COMMIT>`;
|
|
64
|
+
|
|
65
|
+
const result = parseGitLog(input);
|
|
66
|
+
expect(result).toHaveLength(1);
|
|
67
|
+
const commit = result[0] as GitVertex;
|
|
68
|
+
expect(commit.parents).toEqual([]);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("parses refs with HEAD pointer", () => {
|
|
72
|
+
const input = `abc123
|
|
73
|
+
def456
|
|
74
|
+
Author
|
|
75
|
+
author@example.com
|
|
76
|
+
1609459200
|
|
77
|
+
Committer
|
|
78
|
+
committer@example.com
|
|
79
|
+
1609459200
|
|
80
|
+
HEAD -> main, origin/main
|
|
81
|
+
Commit message
|
|
82
|
+
<END_COMMIT>`;
|
|
83
|
+
|
|
84
|
+
const result = parseGitLog(input);
|
|
85
|
+
const commit = result[0] as GitVertex;
|
|
86
|
+
expect(commit.refs).toHaveLength(2);
|
|
87
|
+
expect(commit.refs[0]).toEqual({ name: "main", type: "head" });
|
|
88
|
+
expect(commit.refs[1]).toEqual({ name: "origin/main", type: "remote" });
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("parses refs with tags", () => {
|
|
92
|
+
const input = `abc123
|
|
93
|
+
def456
|
|
94
|
+
Author
|
|
95
|
+
author@example.com
|
|
96
|
+
1609459200
|
|
97
|
+
Committer
|
|
98
|
+
committer@example.com
|
|
99
|
+
1609459200
|
|
100
|
+
tag: v1.0.0, tag: latest
|
|
101
|
+
Commit message
|
|
102
|
+
<END_COMMIT>`;
|
|
103
|
+
|
|
104
|
+
const result = parseGitLog(input);
|
|
105
|
+
const commit = result[0] as GitVertex;
|
|
106
|
+
const tags = commit.refs.filter((r) => r.type === "tag");
|
|
107
|
+
expect(tags).toHaveLength(2);
|
|
108
|
+
expect(tags[0]).toEqual({ name: "v1.0.0", type: "tag" });
|
|
109
|
+
expect(tags[1]).toEqual({ name: "latest", type: "tag" });
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("parses refs with local branches", () => {
|
|
113
|
+
const input = `abc123
|
|
114
|
+
def456
|
|
115
|
+
Author
|
|
116
|
+
author@example.com
|
|
117
|
+
1609459200
|
|
118
|
+
Committer
|
|
119
|
+
committer@example.com
|
|
120
|
+
1609459200
|
|
121
|
+
feature-branch, develop
|
|
122
|
+
Commit message
|
|
123
|
+
<END_COMMIT>`;
|
|
124
|
+
|
|
125
|
+
const result = parseGitLog(input);
|
|
126
|
+
const commit = result[0] as GitVertex;
|
|
127
|
+
const locals = commit.refs.filter((r) => r.type === "local");
|
|
128
|
+
expect(locals).toHaveLength(2);
|
|
129
|
+
expect(locals[0]).toEqual({ name: "feature-branch", type: "local" });
|
|
130
|
+
expect(locals[1]).toEqual({ name: "develop", type: "local" });
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("parses commit with empty refs", () => {
|
|
134
|
+
const input = `abc123
|
|
135
|
+
def456
|
|
136
|
+
Author
|
|
137
|
+
author@example.com
|
|
138
|
+
1609459200
|
|
139
|
+
Committer
|
|
140
|
+
committer@example.com
|
|
141
|
+
1609459200
|
|
142
|
+
|
|
143
|
+
Commit with no refs
|
|
144
|
+
<END_COMMIT>`;
|
|
145
|
+
|
|
146
|
+
const result = parseGitLog(input);
|
|
147
|
+
const commit = result[0] as GitVertex;
|
|
148
|
+
expect(commit.refs).toEqual([]);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("parses multiple commits in sequence", () => {
|
|
152
|
+
const input = `abc123
|
|
153
|
+
def456
|
|
154
|
+
Author A
|
|
155
|
+
authorA@example.com
|
|
156
|
+
1609459200
|
|
157
|
+
Committer A
|
|
158
|
+
committerA@example.com
|
|
159
|
+
1609459200
|
|
160
|
+
|
|
161
|
+
First commit
|
|
162
|
+
<END_COMMIT>def456
|
|
163
|
+
ghi789
|
|
164
|
+
Author B
|
|
165
|
+
authorB@example.com
|
|
166
|
+
1609459201
|
|
167
|
+
Committer B
|
|
168
|
+
committerB@example.com
|
|
169
|
+
1609459201
|
|
170
|
+
|
|
171
|
+
Second commit
|
|
172
|
+
<END_COMMIT>`;
|
|
173
|
+
|
|
174
|
+
const result = parseGitLog(input);
|
|
175
|
+
expect(result).toHaveLength(2);
|
|
176
|
+
expect(result[0]?.hash).toBe("abc123");
|
|
177
|
+
expect(result[1]?.hash).toBe("def456");
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("handles multiline commit messages", () => {
|
|
181
|
+
const input = `abc123
|
|
182
|
+
def456
|
|
183
|
+
Author
|
|
184
|
+
author@example.com
|
|
185
|
+
1609459200
|
|
186
|
+
Committer
|
|
187
|
+
committer@example.com
|
|
188
|
+
1609459200
|
|
189
|
+
|
|
190
|
+
Fix: multiple fixes
|
|
191
|
+
- Fix issue A
|
|
192
|
+
- Fix issue B
|
|
193
|
+
<END_COMMIT>`;
|
|
194
|
+
|
|
195
|
+
const result = parseGitLog(input);
|
|
196
|
+
const commit = result[0] as GitVertex;
|
|
197
|
+
// Only the first line of the message is captured (git log format)
|
|
198
|
+
expect(commit.message).toBe("Fix: multiple fixes");
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it("filters out malformed blocks (less than 10 lines)", () => {
|
|
202
|
+
const input = `abc123
|
|
203
|
+
def456
|
|
204
|
+
Author
|
|
205
|
+
author@example.com
|
|
206
|
+
1609459200
|
|
207
|
+
Committer
|
|
208
|
+
committer@example.com
|
|
209
|
+
1609459200
|
|
210
|
+
|
|
211
|
+
Complete commit
|
|
212
|
+
<END_COMMIT>incomplete
|
|
213
|
+
block
|
|
214
|
+
<END_COMMIT>`;
|
|
215
|
+
|
|
216
|
+
const result = parseGitLog(input);
|
|
217
|
+
expect(result).toHaveLength(1);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it("parses empty input as empty array", () => {
|
|
221
|
+
const result = parseGitLog("");
|
|
222
|
+
expect(result).toEqual([]);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it("handles whitespace-only input", () => {
|
|
226
|
+
const result = parseGitLog(" \n \n ");
|
|
227
|
+
expect(result).toEqual([]);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it("correctly parses unix timestamps as numbers", () => {
|
|
231
|
+
const input = `abc123
|
|
232
|
+
def456
|
|
233
|
+
Author
|
|
234
|
+
author@example.com
|
|
235
|
+
1609459200
|
|
236
|
+
Committer
|
|
237
|
+
committer@example.com
|
|
238
|
+
1609459300
|
|
239
|
+
|
|
240
|
+
Commit
|
|
241
|
+
<END_COMMIT>`;
|
|
242
|
+
|
|
243
|
+
const result = parseGitLog(input);
|
|
244
|
+
const commit = result[0] as GitVertex;
|
|
245
|
+
expect(typeof commit.authorDate).toBe("number");
|
|
246
|
+
expect(typeof commit.commitDate).toBe("number");
|
|
247
|
+
expect(commit.authorDate).toBe(1609459200);
|
|
248
|
+
expect(commit.commitDate).toBe(1609459300);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it("parses refs with remote branches (origin/feature)", () => {
|
|
252
|
+
const input = `abc123
|
|
253
|
+
def456
|
|
254
|
+
Author
|
|
255
|
+
author@example.com
|
|
256
|
+
1609459200
|
|
257
|
+
Committer
|
|
258
|
+
committer@example.com
|
|
259
|
+
1609459200
|
|
260
|
+
origin/feature, upstream/main
|
|
261
|
+
Commit
|
|
262
|
+
<END_COMMIT>`;
|
|
263
|
+
|
|
264
|
+
const result = parseGitLog(input);
|
|
265
|
+
const commit = result[0] as GitVertex;
|
|
266
|
+
const remotes = commit.refs.filter((r) => r.type === "remote");
|
|
267
|
+
expect(remotes).toHaveLength(2);
|
|
268
|
+
expect(remotes[0]).toEqual({ name: "origin/feature", type: "remote" });
|
|
269
|
+
expect(remotes[1]).toEqual({ name: "upstream/main", type: "remote" });
|
|
270
|
+
});
|
|
271
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse git log output into structured GitVertex objects.
|
|
3
|
+
* Uses custom format: %H%n%P%n%an%n%ae%n%at%n%cn%n%ce%n%ct%n%D%n%s%n<END_COMMIT>
|
|
4
|
+
*/
|
|
5
|
+
import type { GitVertex, RefData } from "./types.ts";
|
|
6
|
+
|
|
7
|
+
export function parseGitLog(stdout: string): GitVertex[] {
|
|
8
|
+
const blocks = stdout.split("<END_COMMIT>").filter((b) => b.trim());
|
|
9
|
+
return blocks.map(parseCommitBlock).filter(Boolean) as GitVertex[];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function parseCommitBlock(block: string): GitVertex | null {
|
|
13
|
+
const lines = block.trim().split("\n");
|
|
14
|
+
if (lines.length < 10) return null;
|
|
15
|
+
|
|
16
|
+
const hash = lines[0];
|
|
17
|
+
const parents = lines[1] ? lines[1].split(" ").filter(Boolean) : [];
|
|
18
|
+
const author = lines[2];
|
|
19
|
+
const authorEmail = lines[3];
|
|
20
|
+
const authorDate = parseInt(lines[4], 10);
|
|
21
|
+
const committer = lines[5];
|
|
22
|
+
const committerEmail = lines[6];
|
|
23
|
+
const commitDate = parseInt(lines[7], 10);
|
|
24
|
+
const refs = parseRefs(lines[8]);
|
|
25
|
+
const message = lines[9];
|
|
26
|
+
|
|
27
|
+
return { hash, parents, author, authorEmail, authorDate, committer, committerEmail, commitDate, refs, message };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function parseRefs(refString: string): RefData[] {
|
|
31
|
+
if (!refString.trim()) return [];
|
|
32
|
+
return refString.split(",").map((r) => r.trim()).filter(Boolean).map((ref) => {
|
|
33
|
+
if (ref.startsWith("HEAD -> ")) return { name: ref.replace("HEAD -> ", ""), type: "head" as const };
|
|
34
|
+
if (ref.startsWith("tag: ")) return { name: ref.replace("tag: ", ""), type: "tag" as const };
|
|
35
|
+
if (ref.includes("/")) return { name: ref, type: "remote" as const };
|
|
36
|
+
return { name: ref, type: "local" as const };
|
|
37
|
+
});
|
|
38
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/** Message types for Extension ↔ Webview communication */
|
|
2
|
+
|
|
3
|
+
// --- Git data types ---
|
|
4
|
+
|
|
5
|
+
export interface GitVertex {
|
|
6
|
+
hash: string;
|
|
7
|
+
parents: string[];
|
|
8
|
+
author: string;
|
|
9
|
+
authorEmail: string;
|
|
10
|
+
authorDate: number;
|
|
11
|
+
committer: string;
|
|
12
|
+
committerEmail: string;
|
|
13
|
+
commitDate: number;
|
|
14
|
+
refs: RefData[];
|
|
15
|
+
message: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface RefData {
|
|
19
|
+
name: string;
|
|
20
|
+
type: "head" | "local" | "remote" | "tag";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface Branch {
|
|
24
|
+
name: string;
|
|
25
|
+
remote?: string;
|
|
26
|
+
current: boolean;
|
|
27
|
+
hash: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface Tag {
|
|
31
|
+
name: string;
|
|
32
|
+
hash: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface Remote {
|
|
36
|
+
name: string;
|
|
37
|
+
fetchUrl: string;
|
|
38
|
+
pushUrl: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface Stash {
|
|
42
|
+
index: number;
|
|
43
|
+
hash: string;
|
|
44
|
+
message: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface Worktree {
|
|
48
|
+
path: string;
|
|
49
|
+
branch: string;
|
|
50
|
+
head: string;
|
|
51
|
+
isMain: boolean;
|
|
52
|
+
isDetached: boolean;
|
|
53
|
+
locked: boolean;
|
|
54
|
+
lockReason?: string;
|
|
55
|
+
prunable: boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface CommitDetail {
|
|
59
|
+
hash: string;
|
|
60
|
+
author: string;
|
|
61
|
+
authorEmail: string;
|
|
62
|
+
authorDate: number;
|
|
63
|
+
committer: string;
|
|
64
|
+
committerEmail: string;
|
|
65
|
+
commitDate: number;
|
|
66
|
+
message: string;
|
|
67
|
+
parents: string[];
|
|
68
|
+
fileChanges: FileChange[];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface FileChange {
|
|
72
|
+
path: string;
|
|
73
|
+
oldPath?: string;
|
|
74
|
+
status: "A" | "M" | "D" | "R" | "C" | "U";
|
|
75
|
+
additions: number;
|
|
76
|
+
deletions: number;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface MergeState {
|
|
80
|
+
type: "merge" | "rebase" | "cherry-pick";
|
|
81
|
+
progress?: string; // e.g. "3/5" for rebase
|
|
82
|
+
message?: string; // current commit message being rebased
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface RepoInfo {
|
|
86
|
+
path: string;
|
|
87
|
+
branches: Branch[];
|
|
88
|
+
tags: Tag[];
|
|
89
|
+
remotes: Remote[];
|
|
90
|
+
stashes: Stash[];
|
|
91
|
+
head: string;
|
|
92
|
+
currentBranch: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface ActionResult {
|
|
96
|
+
ok: boolean;
|
|
97
|
+
error?: string;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface UncommittedData {
|
|
101
|
+
staged: FileChange[];
|
|
102
|
+
unstaged: FileChange[];
|
|
103
|
+
conflicted: FileChange[];
|
|
104
|
+
mergeState?: MergeState;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// --- Settings ---
|
|
108
|
+
|
|
109
|
+
export interface IssueLinkingRule {
|
|
110
|
+
pattern: string;
|
|
111
|
+
url: string;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface PrCreationConfig {
|
|
115
|
+
provider: "github" | "gitlab" | "bitbucket" | "custom";
|
|
116
|
+
urlTemplate: string;
|
|
117
|
+
owner: string;
|
|
118
|
+
repo: string;
|
|
119
|
+
defaultTargetBranch: string;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export interface GitGraphSettings {
|
|
123
|
+
maxCommits: number;
|
|
124
|
+
showTags: boolean;
|
|
125
|
+
showStashes: boolean;
|
|
126
|
+
showRemoteBranches: boolean;
|
|
127
|
+
graphStyle: "rounded" | "angular";
|
|
128
|
+
firstParentOnly: boolean;
|
|
129
|
+
dateFormat: "relative" | "absolute" | "iso";
|
|
130
|
+
commitOrdering: "topo" | "date" | "author-date";
|
|
131
|
+
issueLinkingRules: IssueLinkingRule[];
|
|
132
|
+
prCreation: PrCreationConfig | null;
|
|
133
|
+
autoFetchInterval: number;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export const DEFAULT_SETTINGS: GitGraphSettings = {
|
|
137
|
+
maxCommits: 300,
|
|
138
|
+
showTags: true,
|
|
139
|
+
showStashes: true,
|
|
140
|
+
showRemoteBranches: true,
|
|
141
|
+
graphStyle: "rounded",
|
|
142
|
+
firstParentOnly: false,
|
|
143
|
+
dateFormat: "relative",
|
|
144
|
+
commitOrdering: "topo",
|
|
145
|
+
issueLinkingRules: [{ pattern: "#(\\d+)", url: "" }],
|
|
146
|
+
prCreation: null,
|
|
147
|
+
autoFetchInterval: 0,
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// --- Extension → Webview messages ---
|
|
151
|
+
|
|
152
|
+
export type ExtToWebview =
|
|
153
|
+
| { command: "loadRepoInfo"; data: RepoInfo }
|
|
154
|
+
| { command: "loadCommits"; data: GitVertex[]; append: boolean }
|
|
155
|
+
| { command: "commitDetails"; data: CommitDetail }
|
|
156
|
+
| { command: "loadUncommitted"; data: UncommittedData | null }
|
|
157
|
+
| { command: "loadSettings"; data: GitGraphSettings }
|
|
158
|
+
| { command: "loadUserDetails"; data: { name: string; email: string } }
|
|
159
|
+
| { command: "loadOwnerRepo"; data: { owner: string; repo: string } }
|
|
160
|
+
| { command: "refresh"; data: GitVertex[]; repoInfo: RepoInfo }
|
|
161
|
+
| { command: "actionResult"; action: string; args?: Record<string, unknown>; result: ActionResult }
|
|
162
|
+
| { command: "loadWorktrees"; data: Worktree[] }
|
|
163
|
+
| { command: "loadStashes"; data: Stash[] }
|
|
164
|
+
| { command: "error"; message: string };
|
|
165
|
+
|
|
166
|
+
// --- Webview → Extension messages ---
|
|
167
|
+
|
|
168
|
+
export type WebviewToExt =
|
|
169
|
+
| { command: "ready" }
|
|
170
|
+
| { command: "requestRepoInfo" }
|
|
171
|
+
| { command: "requestCommits"; maxCommits?: number; skip?: number; branch?: string }
|
|
172
|
+
| { command: "requestCommitDetails"; hash: string }
|
|
173
|
+
| { command: "requestUncommitted" }
|
|
174
|
+
| { command: "openDiff"; filePath: string; hash: string; parentHash: string | null }
|
|
175
|
+
| { command: "requestSettings" }
|
|
176
|
+
| { command: "updateSetting"; key: string; value: unknown }
|
|
177
|
+
| { command: "requestUserDetails" }
|
|
178
|
+
| { command: "updateUserDetails"; name?: string; email?: string }
|
|
179
|
+
| { command: "addRemote"; name: string; url: string }
|
|
180
|
+
| { command: "removeRemote"; name: string }
|
|
181
|
+
| { command: "editRemoteUrl"; name: string; url: string }
|
|
182
|
+
| { command: "requestOwnerRepo" }
|
|
183
|
+
| { command: "gitAction"; action: string; args: Record<string, unknown> }
|
|
184
|
+
| { command: "requestWorktrees" }
|
|
185
|
+
| { command: "addWorktree"; path: string; branch?: string; newBranch?: string; startPoint?: string }
|
|
186
|
+
| { command: "removeWorktree"; path: string; force?: boolean }
|
|
187
|
+
| { command: "pruneWorktrees" }
|
|
188
|
+
| { command: "openWorktree"; path: string }
|
|
189
|
+
| { command: "openFile"; filePath: string }
|
|
190
|
+
| { command: "openConflictFile"; filePath: string }
|
|
191
|
+
| { command: "openSourceControl" }
|
|
192
|
+
| { command: "requestStashes" };
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { describe, it, expect } from "bun:test";
|
|
2
|
+
import { getWebviewHtml } from "./webview-html.ts";
|
|
3
|
+
|
|
4
|
+
describe("webview-html: getWebviewHtml", () => {
|
|
5
|
+
it("returns valid HTML", () => {
|
|
6
|
+
const html = getWebviewHtml();
|
|
7
|
+
expect(html).toContain("<!DOCTYPE html>");
|
|
8
|
+
expect(html).toContain("</html>");
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("includes essential elements", () => {
|
|
12
|
+
const html = getWebviewHtml();
|
|
13
|
+
expect(html).toContain('<div id="app">');
|
|
14
|
+
expect(html).toContain('<header id="toolbar">');
|
|
15
|
+
expect(html).toContain('<div id="graph-container">');
|
|
16
|
+
expect(html).toContain('<div id="detail-panel"');
|
|
17
|
+
expect(html).toContain('<div id="status-bar">');
|
|
18
|
+
expect(html).toContain('<div id="context-menu"');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("includes find bar", () => {
|
|
22
|
+
const html = getWebviewHtml();
|
|
23
|
+
expect(html).toContain('id="find-bar"');
|
|
24
|
+
expect(html).toContain('id="find-input"');
|
|
25
|
+
expect(html).toContain('id="find-count"');
|
|
26
|
+
expect(html).toContain('id="find-prev"');
|
|
27
|
+
expect(html).toContain('id="find-next"');
|
|
28
|
+
expect(html).toContain('id="find-close"');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("includes toolbar buttons", () => {
|
|
32
|
+
const html = getWebviewHtml();
|
|
33
|
+
expect(html).toContain('id="branch-selector"');
|
|
34
|
+
expect(html).toContain('id="btn-refresh"');
|
|
35
|
+
expect(html).toContain('id="btn-find"');
|
|
36
|
+
expect(html).toContain('id="btn-settings"');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("includes commit list columns", () => {
|
|
40
|
+
const html = getWebviewHtml();
|
|
41
|
+
expect(html).toContain("col-graph");
|
|
42
|
+
expect(html).toContain("col-message");
|
|
43
|
+
expect(html).toContain("col-author");
|
|
44
|
+
expect(html).toContain("col-date");
|
|
45
|
+
expect(html).toContain("col-hash");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("includes CSS styles", () => {
|
|
49
|
+
const html = getWebviewHtml();
|
|
50
|
+
expect(html).toContain("<style>");
|
|
51
|
+
expect(html).toContain("</style>");
|
|
52
|
+
expect(html).toContain("--bg:");
|
|
53
|
+
expect(html).toContain("--text:");
|
|
54
|
+
expect(html).toContain("--border:");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("includes dark mode styles", () => {
|
|
58
|
+
const html = getWebviewHtml();
|
|
59
|
+
expect(html).toContain("prefers-color-scheme: dark");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("includes JavaScript", () => {
|
|
63
|
+
const html = getWebviewHtml();
|
|
64
|
+
expect(html).toContain("<script>");
|
|
65
|
+
expect(html).toContain("</script>");
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("includes graph container and commit list", () => {
|
|
69
|
+
const html = getWebviewHtml();
|
|
70
|
+
expect(html).toContain('id="graph-header"');
|
|
71
|
+
expect(html).toContain('id="commit-list"');
|
|
72
|
+
expect(html).toContain('id="loading"');
|
|
73
|
+
expect(html).toContain('id="graph-svg-container"');
|
|
74
|
+
expect(html).toContain('id="commit-list-wrapper"');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("marks elements with proper classes", () => {
|
|
78
|
+
const html = getWebviewHtml();
|
|
79
|
+
expect(html).toContain("hidden");
|
|
80
|
+
expect(html).toContain("commit-row");
|
|
81
|
+
expect(html).toContain("header-row");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("includes viewport meta tag", () => {
|
|
85
|
+
const html = getWebviewHtml();
|
|
86
|
+
expect(html).toContain('meta charset="utf-8"');
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("includes responsive flex layout", () => {
|
|
90
|
+
const html = getWebviewHtml();
|
|
91
|
+
expect(html).toContain("flex");
|
|
92
|
+
expect(html).toContain("flex-direction");
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("sets initial status text", () => {
|
|
96
|
+
const html = getWebviewHtml();
|
|
97
|
+
expect(html).toContain("Loading repository");
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("includes SVG graph rendering capability (comment)", () => {
|
|
101
|
+
const html = getWebviewHtml();
|
|
102
|
+
// Graph rendering would be in the JavaScript section
|
|
103
|
+
expect(html).toContain("<script>");
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("includes CSS variables for theming", () => {
|
|
107
|
+
const html = getWebviewHtml();
|
|
108
|
+
expect(html).toContain("--blue:");
|
|
109
|
+
expect(html).toContain("--red:");
|
|
110
|
+
expect(html).toContain("--green:");
|
|
111
|
+
expect(html).toContain("--yellow:");
|
|
112
|
+
expect(html).toContain("--purple:");
|
|
113
|
+
expect(html).toContain("--orange:");
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("includes graph column width variable", () => {
|
|
117
|
+
const html = getWebviewHtml();
|
|
118
|
+
expect(html).toContain("--graph-col-w");
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("includes overflow handling for containers", () => {
|
|
122
|
+
const html = getWebviewHtml();
|
|
123
|
+
expect(html).toContain("overflow");
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it("is valid HTML structure", () => {
|
|
127
|
+
const html = getWebviewHtml();
|
|
128
|
+
// Check nesting: html > body > div#app
|
|
129
|
+
const bodyStart = html.indexOf("<body>");
|
|
130
|
+
const bodyEnd = html.indexOf("</body>");
|
|
131
|
+
const appDiv = html.indexOf('id="app"');
|
|
132
|
+
expect(bodyStart).toBeGreaterThan(-1);
|
|
133
|
+
expect(bodyEnd).toBeGreaterThan(bodyStart);
|
|
134
|
+
expect(appDiv).toBeGreaterThan(bodyStart);
|
|
135
|
+
expect(appDiv).toBeLessThan(bodyEnd);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("includes proper charset declaration", () => {
|
|
139
|
+
const html = getWebviewHtml();
|
|
140
|
+
expect(html).toContain('charset="utf-8"');
|
|
141
|
+
});
|
|
142
|
+
});
|